mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2025-12-31 00:10:44 -06:00
Refactor scene graph: Move scene loading to separate class.
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
return {
|
||||
-- Solar system module
|
||||
{
|
||||
Name = "SolarSystem",
|
||||
Parent = "Root"
|
||||
},
|
||||
-- Sun barycenter module
|
||||
{
|
||||
Name = "SolarSystemBarycenter",
|
||||
|
||||
Submodule ext/ghoul updated: f341d33a3b...57f9d38b3a
@@ -52,6 +52,7 @@ class ModuleEngine;
|
||||
class WindowWrapper;
|
||||
class SettingsEngine;
|
||||
class TimeManager;
|
||||
class SceneManager;
|
||||
class SyncEngine;
|
||||
class ParallelConnection;
|
||||
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
void setMaster(bool master);
|
||||
double runTime();
|
||||
void setRunTime(double t);
|
||||
void loadScene(const std::string& scenePath);
|
||||
|
||||
// Guaranteed to return a valid pointer
|
||||
ConfigurationManager& configurationManager();
|
||||
@@ -112,6 +114,7 @@ public:
|
||||
void externalControlCallback(const char* receivedChars, int size, int clientId);
|
||||
void encode();
|
||||
void decode();
|
||||
void scheduleLoadScene(const std::string& scenePath);
|
||||
|
||||
void enableBarrier();
|
||||
void disableBarrier();
|
||||
@@ -145,6 +148,7 @@ private:
|
||||
std::unique_ptr<ConfigurationManager> _configurationManager;
|
||||
std::unique_ptr<interaction::InteractionHandler> _interactionHandler;
|
||||
std::unique_ptr<RenderEngine> _renderEngine;
|
||||
std::unique_ptr<SceneManager> _sceneManager;
|
||||
std::unique_ptr<scripting::ScriptEngine> _scriptEngine;
|
||||
std::unique_ptr<scripting::ScriptScheduler> _scriptScheduler;
|
||||
std::unique_ptr<NetworkEngine> _networkEngine;
|
||||
@@ -165,6 +169,9 @@ private:
|
||||
// Others
|
||||
std::unique_ptr<properties::PropertyOwner> _globalPropertyNamespace;
|
||||
|
||||
bool _switchScene;
|
||||
std::string _scenePath;
|
||||
|
||||
bool _isMaster;
|
||||
double _runTime;
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ public:
|
||||
*/
|
||||
void removeSyncable(Syncable* syncable);
|
||||
|
||||
/**
|
||||
* Remove multiple Syncables from being synchronized over the SGCT cluster
|
||||
*/
|
||||
void removeSyncables(const std::vector<Syncable*>& syncables);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,7 +144,6 @@ private:
|
||||
|
||||
// Properties
|
||||
properties::StringProperty _origin;
|
||||
properties::StringProperty _coordinateSystem;
|
||||
|
||||
properties::BoolProperty _rotationalFriction;
|
||||
properties::BoolProperty _horizontalFriction;
|
||||
|
||||
@@ -53,8 +53,8 @@ class PerformanceManager;
|
||||
// Forward declare to minimize dependencies
|
||||
class Camera;
|
||||
class SyncBuffer;
|
||||
|
||||
class Scene;
|
||||
class SceneManager;
|
||||
class Renderer;
|
||||
class RaycasterManager;
|
||||
class ScreenLog;
|
||||
@@ -79,13 +79,14 @@ public:
|
||||
static const std::vector<FrametimeType> FrametimeTypes;
|
||||
|
||||
RenderEngine();
|
||||
~RenderEngine();
|
||||
~RenderEngine() = default;
|
||||
|
||||
bool initialize();
|
||||
bool deinitialize();
|
||||
|
||||
void setSceneGraph(Scene* sceneGraph);
|
||||
void setScene(Scene* scene);
|
||||
Scene* scene();
|
||||
void updateScene();
|
||||
|
||||
Camera* camera() const;
|
||||
Renderer* renderer() const;
|
||||
@@ -95,7 +96,7 @@ public:
|
||||
// sgct wrapped functions
|
||||
bool initializeGL();
|
||||
|
||||
void updateSceneGraph();
|
||||
|
||||
void updateShaderPrograms();
|
||||
void updateFade();
|
||||
void updateRenderer();
|
||||
@@ -153,6 +154,11 @@ public:
|
||||
*/
|
||||
void postRaycast(ghoul::opengl::ProgramObject& programObject);
|
||||
|
||||
/**
|
||||
* Set the camera to use for rendering
|
||||
*/
|
||||
void setCamera(Camera* camera);
|
||||
|
||||
|
||||
void setRendererFromString(const std::string& method);
|
||||
|
||||
@@ -174,9 +180,6 @@ public:
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
// This is a temporary method to change the origin of the coordinate system ---abock
|
||||
void changeViewPoint(std::string origin);
|
||||
|
||||
// Temporary fade functionality
|
||||
void startFading(int direction, float fadeDuration);
|
||||
|
||||
@@ -193,9 +196,9 @@ private:
|
||||
|
||||
void renderInformation();
|
||||
|
||||
Camera* _mainCamera;
|
||||
Scene* _sceneGraph;
|
||||
RaycasterManager* _raycasterManager;
|
||||
Camera* _camera;
|
||||
Scene* _scene;
|
||||
std::unique_ptr<RaycasterManager> _raycasterManager;
|
||||
|
||||
properties::BoolProperty _performanceMeasurements;
|
||||
std::unique_ptr<performance::PerformanceManager> _performanceManager;
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scene/scenegraph.h>
|
||||
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
@@ -48,28 +46,48 @@ class SceneGraphNode;
|
||||
// SceneGraphFinishedLoading
|
||||
class Scene {
|
||||
public:
|
||||
|
||||
using UpdateDependencies = ghoul::Boolean;
|
||||
|
||||
struct InvalidSceneError : ghoul::RuntimeError {
|
||||
/**
|
||||
* \param message The reason that caused this exception to be thrown
|
||||
* \param component The optional compoment that caused this exception to be thrown
|
||||
* \pre message may not be empty
|
||||
*/
|
||||
explicit InvalidSceneError(const std::string& message, const std::string& component = "");
|
||||
};
|
||||
|
||||
// constructors & destructor
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
/**
|
||||
* Initalizes the SceneGraph by loading modules from the ${SCENEPATH} directory
|
||||
* Initalizes the SceneGraph
|
||||
*/
|
||||
bool initialize();
|
||||
|
||||
/*
|
||||
* Clean up everything
|
||||
*/
|
||||
bool deinitialize();
|
||||
void initialize();
|
||||
|
||||
/*
|
||||
* Load the scenegraph from the provided folder
|
||||
*/
|
||||
void scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath);
|
||||
void clearSceneGraph();
|
||||
//void scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath);
|
||||
void clear();
|
||||
|
||||
void loadModule(const std::string& modulePath);
|
||||
/*
|
||||
* Set the root node of the scene
|
||||
*/
|
||||
void setRoot(std::unique_ptr<SceneGraphNode> root);
|
||||
|
||||
/*
|
||||
* Set the root node of the scene
|
||||
*/
|
||||
void setCamera(std::unique_ptr<Camera> camera);
|
||||
|
||||
/**
|
||||
* Return the camera
|
||||
*/
|
||||
Camera* camera() const;
|
||||
|
||||
/*
|
||||
* Updates all SceneGraphNodes relative positions
|
||||
*/
|
||||
@@ -96,13 +114,20 @@ public:
|
||||
*/
|
||||
SceneGraphNode* sceneGraphNode(const std::string& name) const;
|
||||
|
||||
std::vector<SceneGraphNode*> allSceneGraphNodes() const;
|
||||
void addNode(SceneGraphNode* node, UpdateDependencies updateDeps = UpdateDependencies::Yes);
|
||||
|
||||
SceneGraph& sceneGraph();
|
||||
void removeNode(SceneGraphNode* node, UpdateDependencies updateDeps = UpdateDependencies::Yes);
|
||||
|
||||
void updateDependencies();
|
||||
|
||||
void sortTopologically();
|
||||
|
||||
const std::vector<SceneGraphNode*>& allSceneGraphNodes() const;
|
||||
|
||||
const std::map<std::string, SceneGraphNode*>& nodesByName() const;
|
||||
|
||||
void writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename);
|
||||
|
||||
void addSceneGraphNode(SceneGraphNode* node){
|
||||
_graph.addSceneGraphNode(node);
|
||||
}
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to change the
|
||||
* scene graph. The functions contained are
|
||||
@@ -115,39 +140,16 @@ public:
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
bool loadSceneInternal(const std::string& sceneDescriptionFilePath);
|
||||
|
||||
void writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename);
|
||||
|
||||
std::string _focus;
|
||||
|
||||
// actual scenegraph
|
||||
SceneGraph _graph;
|
||||
//SceneGraphNode* _root;
|
||||
//std::vector<SceneGraphNode*> _nodes;
|
||||
//std::map<std::string, SceneGraphNode*> _allNodes;
|
||||
|
||||
std::string _sceneGraphToLoad;
|
||||
private:
|
||||
std::unique_ptr<SceneGraphNode> _root;
|
||||
std::unique_ptr<Camera> _camera;
|
||||
std::vector<SceneGraphNode*> _topologicallySortedNodes;
|
||||
std::vector<SceneGraphNode*> _circularNodes;
|
||||
std::map<std::string, SceneGraphNode*> _nodesByName;
|
||||
|
||||
std::mutex _programUpdateLock;
|
||||
std::set<ghoul::opengl::ProgramObject*> _programsToUpdate;
|
||||
std::vector<std::unique_ptr<ghoul::opengl::ProgramObject>> _programs;
|
||||
|
||||
typedef std::map<std::string, ghoul::Dictionary> NodeMap;
|
||||
typedef std::multimap<std::string, std::string> DependencyMap;
|
||||
typedef std::vector<std::string> LoadedList;
|
||||
|
||||
struct LoadMaps {
|
||||
NodeMap nodes;
|
||||
DependencyMap dependencies;
|
||||
LoadedList loadedNodes;
|
||||
};
|
||||
|
||||
void loadModules(const std::string& directory, const ghoul::Dictionary& dictionary);
|
||||
void loadModule(LoadMaps& m,const std::string& modulePath, lua_State* state);
|
||||
void loadNodes(const std::string& parentName, LoadMaps& m);
|
||||
void loadNode(const ghoul::Dictionary& dictionary);
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace openspace {
|
||||
|
||||
class SceneGraphNode : public properties::PropertyOwner {
|
||||
public:
|
||||
using UpdateScene = ghoul::Boolean;
|
||||
|
||||
struct PerformanceRecord {
|
||||
long long renderTime; // time in ns
|
||||
long long updateTimeRenderable; // time in ns
|
||||
@@ -64,21 +66,33 @@ public:
|
||||
SceneGraphNode();
|
||||
~SceneGraphNode();
|
||||
|
||||
static SceneGraphNode* createFromDictionary(const ghoul::Dictionary& dictionary);
|
||||
static std::unique_ptr<SceneGraphNode> createFromDictionary(const ghoul::Dictionary& dictionary);
|
||||
|
||||
bool initialize();
|
||||
bool deinitialize();
|
||||
|
||||
void traversePreOrder(std::function<void(SceneGraphNode*)> fn);
|
||||
void traversePostOrder(std::function<void(SceneGraphNode*)> fn);
|
||||
void update(const UpdateData& data);
|
||||
void evaluate(const Camera* camera, const psc& parentPosition = psc());
|
||||
void render(const RenderData& data, RendererTasks& tasks);
|
||||
void updateCamera(Camera* camera) const;
|
||||
|
||||
//void addNode(SceneGraphNode* child);
|
||||
void attachChild(std::unique_ptr<SceneGraphNode> child, UpdateScene updateScene = UpdateScene::Yes);
|
||||
std::unique_ptr<SceneGraphNode> detachChild(SceneGraphNode& child, UpdateScene updateScene = UpdateScene::Yes);
|
||||
void setParent(SceneGraphNode& parent, UpdateScene updateScene = UpdateScene::Yes);
|
||||
|
||||
void addChild(SceneGraphNode* child);
|
||||
void setParent(SceneGraphNode* parent);
|
||||
//bool abandonChild(SceneGraphNode* child);
|
||||
|
||||
void addDependency(SceneGraphNode& dependency, UpdateScene updateScene = UpdateScene::Yes);
|
||||
void removeDependency(SceneGraphNode& dependency, UpdateScene updateScene = UpdateScene::Yes);
|
||||
void clearDependencies(UpdateScene updateScene = UpdateScene::Yes);
|
||||
void setDependencies(const std::vector<SceneGraphNode*>& dependencies, UpdateScene updateScene = UpdateScene::Yes);
|
||||
|
||||
const std::vector<SceneGraphNode*>& dependencies() const;
|
||||
const std::vector<SceneGraphNode*>& dependentNodes() const;
|
||||
|
||||
Scene* scene();
|
||||
void setScene(Scene* scene);
|
||||
|
||||
glm::dvec3 position() const;
|
||||
const glm::dmat3& rotationMatrix() const;
|
||||
@@ -89,7 +103,7 @@ public:
|
||||
double worldScale() const;
|
||||
|
||||
SceneGraphNode* parent() const;
|
||||
const std::vector<SceneGraphNode*>& children() const;
|
||||
std::vector<SceneGraphNode*> children() const;
|
||||
|
||||
PowerScaledScalar calculateBoundingSphere();
|
||||
PowerScaledScalar boundingSphere() const;
|
||||
@@ -105,14 +119,15 @@ public:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
bool sphereInsideFrustum(const psc& s_pos, const PowerScaledScalar& s_rad, const Camera* camera);
|
||||
|
||||
glm::dvec3 calculateWorldPosition() const;
|
||||
glm::dmat3 calculateWorldRotation() const;
|
||||
double calculateWorldScale() const;
|
||||
|
||||
std::vector<SceneGraphNode*> _children;
|
||||
std::vector<std::unique_ptr<SceneGraphNode>> _children;
|
||||
SceneGraphNode* _parent;
|
||||
std::vector<SceneGraphNode*> _dependencies;
|
||||
std::vector<SceneGraphNode*> _dependentNodes;
|
||||
Scene* _scene;
|
||||
|
||||
PerformanceRecord _performanceRecord;
|
||||
|
||||
|
||||
92
include/openspace/scene/sceneloader.h
Normal file
92
include/openspace/scene/sceneloader.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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 __OPENSPACE_CORE___SCENELOADER___H__
|
||||
#define __OPENSPACE_CORE___SCENELOADER___H__
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <ghoul/lua/ghoul_lua.h>
|
||||
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/camera.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class Scene;
|
||||
|
||||
class SceneLoader {
|
||||
public:
|
||||
struct LoadedNode {
|
||||
LoadedNode(
|
||||
const std::string& nodeName,
|
||||
const std::string& parentName,
|
||||
const std::vector<std::string>& deps,
|
||||
std::unique_ptr<SceneGraphNode> n)
|
||||
{
|
||||
name = nodeName;
|
||||
parent = parentName;
|
||||
dependencies = deps;
|
||||
node = std::move(n);
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string parent;
|
||||
std::vector<std::string> dependencies;
|
||||
std::unique_ptr<SceneGraphNode> node;
|
||||
};
|
||||
|
||||
struct LoadedCamera {
|
||||
LoadedCamera(
|
||||
const std::string& parentName,
|
||||
std::unique_ptr<Camera> c)
|
||||
{
|
||||
parent = parentName;
|
||||
camera = std::move(c);
|
||||
}
|
||||
std::string parent;
|
||||
std::unique_ptr<Camera> camera;
|
||||
};
|
||||
|
||||
SceneLoader() = default;
|
||||
~SceneLoader() = default;
|
||||
|
||||
std::unique_ptr<Scene> loadScene(const std::string& path);
|
||||
std::vector<SceneGraphNode*> importDirectory(Scene& scene, const std::string& directory);
|
||||
SceneGraphNode* importNodeDictionary(Scene& scene, const ghoul::Dictionary& dictionary);
|
||||
|
||||
private:
|
||||
SceneLoader::LoadedNode loadNode(const ghoul::Dictionary& dictionary);
|
||||
std::vector<SceneLoader::LoadedNode> loadModule(const std::string& path, lua_State* luaState);
|
||||
std::vector<SceneLoader::LoadedNode> loadDirectory(const std::string& path, lua_State* luaState);
|
||||
|
||||
SceneLoader::LoadedCamera loadCamera(const ghoul::Dictionary& dictionary);
|
||||
std::vector<SceneGraphNode*> addLoadedNodes(Scene& scene, std::vector<SceneLoader::LoadedNode> nodes);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __OPENSPACE_CORE___SCENELOADER___H__
|
||||
@@ -21,55 +21,27 @@
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___SCENEGRAPH___H__
|
||||
#define __OPENSPACE_CORE___SCENEGRAPH___H__
|
||||
|
||||
#ifndef __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
#define __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class SceneGraphNode;
|
||||
class Scene;
|
||||
|
||||
class SceneGraph {
|
||||
class SceneManager {
|
||||
public:
|
||||
SceneGraph();
|
||||
~SceneGraph();
|
||||
|
||||
void clear();
|
||||
bool loadFromFile(const std::string& sceneDescription);
|
||||
|
||||
// Returns if addition was successful
|
||||
bool addSceneGraphNode(SceneGraphNode* node);
|
||||
bool removeSceneGraphNode(SceneGraphNode* node);
|
||||
|
||||
const std::vector<SceneGraphNode*>& nodes() const;
|
||||
|
||||
SceneGraphNode* rootNode() const;
|
||||
SceneGraphNode* sceneGraphNode(const std::string& name) const;
|
||||
|
||||
SceneManager() = default;
|
||||
~SceneManager() = default;
|
||||
Scene* loadScene(const std::string& path);
|
||||
void unloadScene(Scene& scene);
|
||||
private:
|
||||
struct SceneGraphNodeInternal {
|
||||
~SceneGraphNodeInternal();
|
||||
|
||||
SceneGraphNode* node = nullptr;
|
||||
// From nodes that are dependent on this one
|
||||
std::vector<SceneGraphNodeInternal*> incomingEdges;
|
||||
// To nodes that this node depends on
|
||||
std::vector<SceneGraphNodeInternal*> outgoingEdges;
|
||||
};
|
||||
|
||||
bool nodeIsDependentOnRoot(SceneGraphNodeInternal* node);
|
||||
bool sortTopologically();
|
||||
|
||||
SceneGraphNodeInternal* nodeByName(const std::string& name);
|
||||
|
||||
SceneGraphNode* _rootNode;
|
||||
std::vector<SceneGraphNodeInternal*> _nodes;
|
||||
std::vector<SceneGraphNode*> _topologicalSortedNodes;
|
||||
std::vector<std::unique_ptr<Scene>> _scenes;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
}
|
||||
|
||||
#endif // __OPENSPACE_CORE___SCENEGRAPH___H__
|
||||
#endif // __OPENSPACE_CORE___SCENEMANAGER___H__
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
namespace openspace {
|
||||
class SyncBuffer;
|
||||
class SceneGraphNode;
|
||||
|
||||
/**
|
||||
* This class still needs some more love. Suggested improvements:
|
||||
@@ -92,6 +93,7 @@ public:
|
||||
void setRotation(Quat rotation);
|
||||
void setScaling(glm::vec2 scaling);
|
||||
void setMaxFov(float fov);
|
||||
void setParent(SceneGraphNode* parent);
|
||||
|
||||
// Relative mutators
|
||||
void rotate(Quat rotation);
|
||||
@@ -109,6 +111,7 @@ public:
|
||||
const Quat& rotationQuaternion() const;
|
||||
float maxFov() const;
|
||||
float sinMaxFov() const;
|
||||
SceneGraphNode* parent() const;
|
||||
|
||||
// @TODO this should simply be called viewMatrix!
|
||||
// Or it needs to be changed so that it actually is combined. Right now it is
|
||||
@@ -181,6 +184,7 @@ private:
|
||||
SyncData<Vec3> _position;
|
||||
SyncData<Quat> _rotation;
|
||||
SyncData<glm::vec2> _scaling;
|
||||
SceneGraphNode* _parent;
|
||||
|
||||
|
||||
// _focusPosition to be removed
|
||||
|
||||
@@ -265,8 +265,9 @@ void RenderablePlaneProjection::updatePlane(const Image& img, double currentTime
|
||||
if (!_moving) {
|
||||
SceneGraphNode* thisNode = OsEng.renderEngine().scene()->sceneGraphNode(_name);
|
||||
SceneGraphNode* newParent = OsEng.renderEngine().scene()->sceneGraphNode(_target.node);
|
||||
if (thisNode != nullptr && newParent != nullptr)
|
||||
thisNode->setParent(newParent);
|
||||
if (thisNode != nullptr && newParent != nullptr) {
|
||||
thisNode->setParent(*newParent);
|
||||
}
|
||||
}
|
||||
|
||||
const GLfloat vertex_data[] = { // square of two triangles drawn within fov in target coordinates
|
||||
|
||||
@@ -80,7 +80,7 @@ Documentation RenderablePlanetProjection::Documentation() {
|
||||
},
|
||||
{
|
||||
keyGeometry,
|
||||
new ReferencingVerifier("base_geometry_planet"),
|
||||
new ReferencingVerifier("space_geometry_planet"),
|
||||
"The geometry that is used for rendering this planet.",
|
||||
Optional::No
|
||||
},
|
||||
@@ -127,7 +127,7 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
|
||||
documentation::testSpecificationAndThrow(
|
||||
Documentation(),
|
||||
dictionary,
|
||||
"RenderablePlanetProject"
|
||||
"RenderablePlanetProjection"
|
||||
);
|
||||
|
||||
std::string name;
|
||||
|
||||
@@ -127,7 +127,8 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scene_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraph.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/sceneloader.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenemanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/scene/scenegraphnode_doc.inl
|
||||
${OPENSPACE_BASE_DIR}/src/scripting/lualibrary.cpp
|
||||
@@ -269,7 +270,8 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/rotation.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scale.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scene.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraph.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/sceneloader.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scene/scenegraphnode.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/lualibrary.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/scripting/script_helper.h
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/scriptscheduler.h>
|
||||
#include <openspace/scene/translation.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenemanager.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
@@ -121,16 +121,20 @@ namespace {
|
||||
namespace openspace {
|
||||
|
||||
namespace properties {
|
||||
class Property;
|
||||
class Property;
|
||||
}
|
||||
|
||||
|
||||
class Scene;
|
||||
|
||||
OpenSpaceEngine* OpenSpaceEngine::_engine = nullptr;
|
||||
|
||||
OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
std::unique_ptr<WindowWrapper> windowWrapper)
|
||||
OpenSpaceEngine::OpenSpaceEngine(
|
||||
std::string programName,
|
||||
std::unique_ptr<WindowWrapper> windowWrapper)
|
||||
: _configurationManager(new ConfigurationManager)
|
||||
, _interactionHandler(new interaction::InteractionHandler)
|
||||
, _renderEngine(new RenderEngine)
|
||||
, _sceneManager(new SceneManager)
|
||||
, _scriptEngine(new scripting::ScriptEngine)
|
||||
, _scriptScheduler(new scripting::ScriptScheduler)
|
||||
, _networkEngine(new NetworkEngine)
|
||||
@@ -149,6 +153,8 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
|
||||
, _parallelConnection(new ParallelConnection)
|
||||
, _windowWrapper(std::move(windowWrapper))
|
||||
, _globalPropertyNamespace(new properties::PropertyOwner)
|
||||
, _switchScene(false)
|
||||
, _scenePath("")
|
||||
, _isMaster(false)
|
||||
, _runTime(0.0)
|
||||
, _isInShutdownMode(false)
|
||||
@@ -190,6 +196,11 @@ OpenSpaceEngine::~OpenSpaceEngine() {
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
_gui->deinitializeGL();
|
||||
#endif
|
||||
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_sceneManager = nullptr;
|
||||
|
||||
_interactionHandler->deinitialize();
|
||||
_renderEngine->deinitialize();
|
||||
|
||||
@@ -217,12 +228,12 @@ OpenSpaceEngine& OpenSpaceEngine::ref() {
|
||||
}
|
||||
|
||||
bool OpenSpaceEngine::create(int argc, char** argv,
|
||||
std::unique_ptr<WindowWrapper> windowWrapper,
|
||||
std::vector<std::string>& sgctArguments)
|
||||
std::unique_ptr<WindowWrapper> windowWrapper,
|
||||
std::vector<std::string>& sgctArguments)
|
||||
{
|
||||
ghoul_assert(!_engine, "OpenSpaceEngine was already created");
|
||||
ghoul_assert(windowWrapper != nullptr, "No Window Wrapper was provided");
|
||||
|
||||
|
||||
ghoul::initialize();
|
||||
|
||||
// Initialize the LogManager and add the console log as this will be used every time
|
||||
@@ -323,13 +334,13 @@ bool OpenSpaceEngine::create(int argc, char** argv,
|
||||
"${CACHE}",
|
||||
cacheFolder,
|
||||
ghoul::filesystem::FileSystem::Override::Yes
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Initialize the requested logs from the configuration file
|
||||
_engine->configureLogging();
|
||||
|
||||
LINFOC("OpenSpace Version",
|
||||
LINFOC("OpenSpace Version",
|
||||
OPENSPACE_VERSION_MAJOR << "." <<
|
||||
OPENSPACE_VERSION_MINOR << "." <<
|
||||
OPENSPACE_VERSION_PATCH << " (" << OPENSPACE_VERSION_STRING << ")");
|
||||
@@ -488,33 +499,123 @@ bool OpenSpaceEngine::initialize() {
|
||||
// Load a light and a monospaced font
|
||||
loadFonts();
|
||||
|
||||
// Initialize the Scene
|
||||
Scene* sceneGraph = new Scene;
|
||||
sceneGraph->initialize();
|
||||
|
||||
std::string scenePath = "";
|
||||
configurationManager().getValue(ConfigurationManager::KeyConfigScene, scenePath);
|
||||
sceneGraph->scheduleLoadSceneFile(scenePath);
|
||||
|
||||
// Initialize the RenderEngine
|
||||
_renderEngine->setSceneGraph(sceneGraph);
|
||||
_renderEngine->initialize();
|
||||
_renderEngine->setGlobalBlackOutFactor(0.0);
|
||||
_renderEngine->startFading(1, 3.0);
|
||||
scheduleLoadScene(scenePath);
|
||||
|
||||
LINFO("Finished initializing");
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::scheduleLoadScene(const std::string& scenePath) {
|
||||
_switchScene = true;
|
||||
_scenePath = scenePath;
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::loadScene(const std::string& scenePath) {
|
||||
windowWrapper().setSynchronization(false);
|
||||
OnExit(
|
||||
[this]() { windowWrapper().setSynchronization(true); }
|
||||
);
|
||||
|
||||
// Run start up scripts
|
||||
try {
|
||||
runPreInitializationScripts(scenePath);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
|
||||
|
||||
Scene* scene;
|
||||
try {
|
||||
scene = _sceneManager->loadScene(scenePath);
|
||||
} catch (const ghoul::FileNotFoundError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
} catch (const Scene::InvalidSceneError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
} catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return;
|
||||
}
|
||||
|
||||
Scene* previousScene = _renderEngine->scene();
|
||||
if (previousScene) {
|
||||
_syncEngine->removeSyncables(Time::ref().getSyncables());
|
||||
_syncEngine->removeSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->removeSyncable(_scriptEngine.get());
|
||||
|
||||
_renderEngine->setScene(nullptr);
|
||||
_renderEngine->setCamera(nullptr);
|
||||
_sceneManager->unloadScene(*previousScene);
|
||||
}
|
||||
|
||||
// Initialize the RenderEngine
|
||||
_renderEngine->setScene(scene);
|
||||
_renderEngine->setCamera(scene->camera());
|
||||
_renderEngine->setGlobalBlackOutFactor(0.0);
|
||||
_renderEngine->startFading(1, 3.0);
|
||||
|
||||
|
||||
scene->initialize();
|
||||
_interactionHandler->setCamera(scene->camera());
|
||||
|
||||
try {
|
||||
runPostInitializationScripts(scenePath);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LFATALC(e.component, e.message);
|
||||
}
|
||||
|
||||
// Write keyboard documentation.
|
||||
const std::string KeyboardShortcutsType =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartType;
|
||||
|
||||
const std::string KeyboardShortcutsFile =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartFile;
|
||||
|
||||
std::string type, file;
|
||||
bool hasType = configurationManager().getValue(KeyboardShortcutsType, type);
|
||||
bool hasFile = configurationManager().getValue(KeyboardShortcutsFile, file);
|
||||
|
||||
if (hasType && hasFile) {
|
||||
interactionHandler().writeKeyboardDocumentation(type, file);
|
||||
}
|
||||
|
||||
// If a PropertyDocumentationFile was specified, generate it now.
|
||||
const std::string KeyPropertyDocumentationType =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartType;
|
||||
|
||||
const std::string KeyPropertyDocumentationFile =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartFile;
|
||||
|
||||
hasType = configurationManager().hasKey(KeyPropertyDocumentationType);
|
||||
hasFile = configurationManager().hasKey(KeyPropertyDocumentationFile);
|
||||
|
||||
if (hasType && hasFile) {
|
||||
std::string propertyDocumentationType;
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationType, propertyDocumentationType);
|
||||
std::string propertyDocumentationFile;
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationFile, propertyDocumentationFile);
|
||||
|
||||
propertyDocumentationFile = absPath(propertyDocumentationFile);
|
||||
scene->writePropertyDocumentation(propertyDocumentationFile, propertyDocumentationType, scenePath);
|
||||
}
|
||||
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
LINFO("Initializing GUI");
|
||||
_gui->initialize();
|
||||
_gui->_globalProperty.setSource(
|
||||
[&]() {
|
||||
[&]() {
|
||||
std::vector<properties::PropertyOwner*> res = {
|
||||
_settingsEngine.get(),
|
||||
_interactionHandler.get(),
|
||||
@@ -548,14 +649,14 @@ bool OpenSpaceEngine::initialize() {
|
||||
groups.end(),
|
||||
std::back_inserter(res),
|
||||
[](const auto& val) {
|
||||
return val.second.get();
|
||||
return val.second.get();
|
||||
}
|
||||
);
|
||||
return res;
|
||||
}
|
||||
);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ISWA_ENABLED
|
||||
@@ -565,9 +666,6 @@ bool OpenSpaceEngine::initialize() {
|
||||
_syncEngine->addSyncables(Time::ref().getSyncables());
|
||||
_syncEngine->addSyncables(_renderEngine->getSyncables());
|
||||
_syncEngine->addSyncable(_scriptEngine.get());
|
||||
|
||||
LINFO("Finished initializing");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -865,6 +963,11 @@ void OpenSpaceEngine::setRunTime(double d){
|
||||
void OpenSpaceEngine::preSynchronization() {
|
||||
FileSys.triggerFilesystemEvents();
|
||||
|
||||
if (_switchScene) {
|
||||
loadScene(_scenePath);
|
||||
_switchScene = false;
|
||||
}
|
||||
|
||||
if (_isFirstRenderingFirstFrame) {
|
||||
_windowWrapper->setSynchronization(false);
|
||||
}
|
||||
@@ -883,7 +986,7 @@ void OpenSpaceEngine::preSynchronization() {
|
||||
|
||||
_interactionHandler->updateInputStates(dt);
|
||||
|
||||
_renderEngine->updateSceneGraph();
|
||||
_renderEngine->updateScene();
|
||||
_interactionHandler->updateCamera(dt);
|
||||
_renderEngine->camera()->invalidateCache();
|
||||
|
||||
@@ -902,7 +1005,7 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
_shutdownCountdown -= _windowWrapper->averageDeltaTime();
|
||||
}
|
||||
|
||||
_renderEngine->updateSceneGraph();
|
||||
_renderEngine->updateScene();
|
||||
_renderEngine->updateFade();
|
||||
_renderEngine->updateRenderer();
|
||||
_renderEngine->updateScreenSpaceRenderables();
|
||||
|
||||
@@ -141,19 +141,23 @@ void SettingsEngine::initSceneFiles() {
|
||||
// Load all matching files in the Scene
|
||||
// TODO: match regex with either with new ghoul readFiles or local code
|
||||
std::string sceneDir = "${SCENE}";
|
||||
std::string pathSep(1, ghoul::filesystem::FileSystem::PathSeparator);
|
||||
|
||||
std::vector<std::string> scenes = ghoul::filesystem::Directory(sceneDir).readFiles();
|
||||
for (std::size_t i = 0; i < scenes.size(); ++i) {
|
||||
std::size_t found = scenes[i].find_last_of("/\\");
|
||||
std::size_t found = scenes[i].find_last_of(pathSep);
|
||||
_scenes.addOption(i, scenes[i].substr(found+1));
|
||||
}
|
||||
|
||||
// Set interaction to change ConfigurationManager and schedule the load
|
||||
_scenes.onChange(
|
||||
[this]() {
|
||||
[this, sceneDir, pathSep]() {
|
||||
std::string sceneFile = _scenes.getDescriptionByValue(_scenes);
|
||||
OsEng.configurationManager().setValue(
|
||||
ConfigurationManager::KeyConfigScene, sceneFile);
|
||||
OsEng.renderEngine().scene()->scheduleLoadSceneFile(sceneFile);
|
||||
std::string fullPath =
|
||||
sceneDir + pathSep + sceneFile;
|
||||
OsEng.scheduleLoadScene(fullPath);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ namespace openspace {
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SyncEngine::presync(bool isMaster) {
|
||||
for (const auto& syncable : _syncables) {
|
||||
syncable->presync(isMaster);
|
||||
@@ -73,8 +72,6 @@ namespace openspace {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SyncEngine::addSyncable(Syncable* syncable) {
|
||||
_syncables.push_back(syncable);
|
||||
}
|
||||
@@ -92,4 +89,10 @@ namespace openspace {
|
||||
);
|
||||
}
|
||||
|
||||
void SyncEngine::removeSyncables(const std::vector<Syncable*>& syncables) {
|
||||
for (const auto& syncable : syncables) {
|
||||
removeSyncable(syncable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ namespace interaction {
|
||||
// InteractionHandler
|
||||
InteractionHandler::InteractionHandler()
|
||||
: _origin("origin", "Origin", "")
|
||||
, _coordinateSystem("coordinateSystem", "Coordinate System", "")
|
||||
, _rotationalFriction("rotationalFriction", "Rotational Friction", true)
|
||||
, _horizontalFriction("horizontalFriction", "Horizontal Friction", true)
|
||||
, _verticalFriction("verticalFriction", "Vertical Friction", true)
|
||||
@@ -91,10 +90,6 @@ InteractionHandler::InteractionHandler()
|
||||
resetCameraDirection();
|
||||
});
|
||||
|
||||
_coordinateSystem.onChange([this]() {
|
||||
OsEng.renderEngine().changeViewPoint(_coordinateSystem.value());
|
||||
});
|
||||
|
||||
// Create the interactionModes
|
||||
_inputState = std::make_unique<InputState>();
|
||||
// Inject the same mouse states to both orbital and global interaction mode
|
||||
@@ -137,7 +132,6 @@ InteractionHandler::InteractionHandler()
|
||||
|
||||
// Add the properties
|
||||
addProperty(_origin);
|
||||
addProperty(_coordinateSystem);
|
||||
|
||||
addProperty(_rotationalFriction);
|
||||
addProperty(_horizontalFriction);
|
||||
@@ -175,6 +169,7 @@ void InteractionHandler::setFocusNode(SceneGraphNode* node) {
|
||||
|
||||
void InteractionHandler::setCamera(Camera* camera) {
|
||||
_camera = camera;
|
||||
setFocusNode(_camera->parent());
|
||||
}
|
||||
|
||||
void InteractionHandler::resetCameraDirection() {
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/camera.h>
|
||||
#include <openspace/util/time.h>
|
||||
@@ -113,14 +112,14 @@ const std::vector<RenderEngine::FrametimeType> RenderEngine::FrametimeTypes({
|
||||
});
|
||||
|
||||
RenderEngine::RenderEngine()
|
||||
: _mainCamera(nullptr)
|
||||
: _camera(nullptr)
|
||||
, _performanceMeasurements("performanceMeasurements", "Performance Measurements")
|
||||
, _frametimeType(
|
||||
"frametimeType",
|
||||
"Type of the frametime display",
|
||||
properties::OptionProperty::DisplayType::Dropdown
|
||||
)
|
||||
, _sceneGraph(nullptr)
|
||||
, _scene(nullptr)
|
||||
, _renderer(nullptr)
|
||||
, _rendererImplementation(RendererImplementation::Invalid)
|
||||
, _performanceManager(nullptr)
|
||||
@@ -166,23 +165,11 @@ RenderEngine::RenderEngine()
|
||||
addProperty(_frametimeType);
|
||||
}
|
||||
|
||||
RenderEngine::~RenderEngine() {
|
||||
delete _sceneGraph;
|
||||
_sceneGraph = nullptr;
|
||||
|
||||
delete _mainCamera;
|
||||
delete _raycasterManager;
|
||||
|
||||
}
|
||||
|
||||
bool RenderEngine::deinitialize() {
|
||||
for (auto screenspacerenderable : _screenSpaceRenderables) {
|
||||
screenspacerenderable->deinitialize();
|
||||
}
|
||||
|
||||
MissionManager::deinitialize();
|
||||
|
||||
_sceneGraph->clearSceneGraph();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -209,8 +196,7 @@ bool RenderEngine::initialize() {
|
||||
_frameNumber = 0;
|
||||
std::string renderingMethod = DefaultRenderingMethod;
|
||||
|
||||
// If the user specified a rendering method that he would like to use, use that
|
||||
|
||||
// Set rendering method to the user-defined one if any.
|
||||
if (OsEng.configurationManager().hasKeyAndValue<std::string>(KeyRenderingMethod)) {
|
||||
renderingMethod = OsEng.configurationManager().value<std::string>(KeyRenderingMethod);
|
||||
} else {
|
||||
@@ -224,20 +210,12 @@ bool RenderEngine::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
_raycasterManager = new RaycasterManager();
|
||||
_raycasterManager = std::make_unique<RaycasterManager>();
|
||||
_nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
|
||||
|
||||
LINFO("Seting renderer from string: " << renderingMethod);
|
||||
setRendererFromString(renderingMethod);
|
||||
|
||||
// init camera and set temporary position and scaling
|
||||
_mainCamera = new Camera();
|
||||
|
||||
OsEng.interactionHandler().setCamera(_mainCamera);
|
||||
if (_renderer) {
|
||||
_renderer->setCamera(_mainCamera);
|
||||
}
|
||||
|
||||
#ifdef GHOUL_USE_DEVIL
|
||||
ghoul::io::TextureReader::ref().addReader(std::make_shared<ghoul::io::TextureReaderDevIL>());
|
||||
#endif // GHOUL_USE_DEVIL
|
||||
@@ -279,79 +257,6 @@ bool RenderEngine::initializeGL() {
|
||||
throw;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ALL OF THIS HAS TO BE CHECKED
|
||||
// ---abock
|
||||
|
||||
|
||||
// sgct::Engine::instance()->setNearAndFarClippingPlanes(0.001f, 1000.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 (sgct::Engine::instance()->getCurrentRenderTarget() == sgct::Engine::NonLinearBuffer) {
|
||||
// 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;
|
||||
|
||||
// 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];
|
||||
// sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getWindowPtr(0);
|
||||
// sgct_core::BaseViewport* vp = wPtr->getViewport(0);
|
||||
// sgct_core::SGCTProjectionPlane* projectionPlane = vp->getProjectionPlane();
|
||||
|
||||
// corners[0] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::LowerLeft));
|
||||
// corners[1] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::UpperLeft));
|
||||
// corners[2] = *(projectionPlane->getCoordinatePtr(sgct_core::SGCTProjectionPlane::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]);
|
||||
////
|
||||
//const glm::vec3 eyePosition = sgct_core::ClusterManager::instance()->getDefaultUserPtr()->getPos();
|
||||
////// get viewdirection, stores the direction in the camera, used for culling
|
||||
//const glm::vec3 viewdir = glm::normalize(eyePosition - center);
|
||||
|
||||
//const glm::vec3 upVector = corners[0] - corners[1];
|
||||
|
||||
|
||||
|
||||
//_mainCamera->setCameraDirection(glm::normalize(-viewdir));
|
||||
//_mainCamera->setCameraDirection(glm::vec3(0.f, 0.f, -1.f));
|
||||
//_mainCamera->setLookUpVector(glm::normalize(upVector));
|
||||
//_mainCamera->setLookUpVector(glm::vec3(0.f, 1.f, 0.f));
|
||||
|
||||
// set the initial fov to be 0.0 which means everything will be culled
|
||||
//float maxFov = 0.0f;
|
||||
float maxFov = std::numeric_limits<float>::max();
|
||||
|
||||
//// 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);
|
||||
//}
|
||||
|
||||
LINFO("Initializing Log");
|
||||
std::unique_ptr<ScreenLog> log = std::make_unique<ScreenLog>(ScreenLogTimeToLive);
|
||||
_log = log.get();
|
||||
@@ -361,8 +266,8 @@ bool RenderEngine::initializeGL() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderEngine::updateSceneGraph() {
|
||||
_sceneGraph->update({
|
||||
void RenderEngine::updateScene() {
|
||||
_scene->update({
|
||||
glm::dvec3(0),
|
||||
glm::dmat3(1),
|
||||
1,
|
||||
@@ -373,13 +278,7 @@ void RenderEngine::updateSceneGraph() {
|
||||
_performanceManager != nullptr
|
||||
});
|
||||
|
||||
_sceneGraph->evaluate(_mainCamera);
|
||||
|
||||
//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);
|
||||
//}
|
||||
_scene->evaluate(_camera);
|
||||
}
|
||||
|
||||
void RenderEngine::updateShaderPrograms() {
|
||||
@@ -466,8 +365,8 @@ void RenderEngine::updateFade() {
|
||||
}
|
||||
|
||||
void RenderEngine::render(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix){
|
||||
_mainCamera->sgctInternal.setViewMatrix(viewMatrix);
|
||||
_mainCamera->sgctInternal.setProjectionMatrix(projectionMatrix);
|
||||
_camera->sgctInternal.setViewMatrix(viewMatrix);
|
||||
_camera->sgctInternal.setProjectionMatrix(projectionMatrix);
|
||||
|
||||
if (!(OsEng.isMaster() && _disableMasterRendering) && !OsEng.windowWrapper().isGuiWindow()) {
|
||||
_renderer->render(_globalBlackOutFactor, _performanceManager != nullptr);
|
||||
@@ -546,20 +445,29 @@ void RenderEngine::toggleInfoText(bool b) {
|
||||
}
|
||||
|
||||
Scene* RenderEngine::scene() {
|
||||
ghoul_assert(_sceneGraph, "Scenegraph not initialized");
|
||||
return _sceneGraph;
|
||||
return _scene;
|
||||
}
|
||||
|
||||
RaycasterManager& RenderEngine::raycasterManager() {
|
||||
return *_raycasterManager;
|
||||
}
|
||||
|
||||
void RenderEngine::setSceneGraph(Scene* sceneGraph) {
|
||||
_sceneGraph = sceneGraph;
|
||||
void RenderEngine::setScene(Scene* scene) {
|
||||
_scene = scene;
|
||||
if (_renderer) {
|
||||
_renderer->setScene(scene);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::setCamera(Camera* camera) {
|
||||
_camera = camera;
|
||||
if (_renderer) {
|
||||
_renderer->setCamera(camera);
|
||||
}
|
||||
}
|
||||
|
||||
Camera* RenderEngine::camera() const {
|
||||
return _mainCamera;
|
||||
return _camera;
|
||||
}
|
||||
|
||||
Renderer* RenderEngine::renderer() const {
|
||||
@@ -718,8 +626,8 @@ void RenderEngine::setRenderer(std::unique_ptr<Renderer> renderer) {
|
||||
_renderer->setResolution(renderingResolution());
|
||||
_renderer->setNAaSamples(_nAaSamples);
|
||||
_renderer->initialize();
|
||||
_renderer->setCamera(_mainCamera);
|
||||
_renderer->setScene(_sceneGraph);
|
||||
_renderer->setCamera(_camera);
|
||||
_renderer->setScene(_scene);
|
||||
}
|
||||
|
||||
|
||||
@@ -803,395 +711,6 @@ performance::PerformanceManager* RenderEngine::performanceManager() {
|
||||
return _performanceManager.get();
|
||||
}
|
||||
|
||||
// This method is temporary and will be removed once the scalegraph is in effect ---abock
|
||||
void RenderEngine::changeViewPoint(std::string origin) {
|
||||
// SceneGraphNode* solarSystemBarycenterNode = scene()->sceneGraphNode("SolarSystemBarycenter");
|
||||
// SceneGraphNode* plutoBarycenterNode = scene()->sceneGraphNode("PlutoBarycenter");
|
||||
// SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons");
|
||||
// SceneGraphNode* newHorizonsPathNodeJ = scene()->sceneGraphNode("NewHorizonsPathJupiter");
|
||||
// SceneGraphNode* newHorizonsPathNodeP = scene()->sceneGraphNode("NewHorizonsPathPluto");
|
||||
//// SceneGraphNode* cg67pNode = scene()->sceneGraphNode("67P");
|
||||
//// SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta");
|
||||
//
|
||||
// RenderablePath* nhPath;
|
||||
//
|
||||
// SceneGraphNode* jupiterBarycenterNode = scene()->sceneGraphNode("JupiterBarycenter");
|
||||
//
|
||||
// //SceneGraphNode* newHorizonsGhostNode = scene()->sceneGraphNode("NewHorizonsGhost");
|
||||
// //SceneGraphNode* dawnNode = scene()->sceneGraphNode("Dawn");
|
||||
// //SceneGraphNode* vestaNode = scene()->sceneGraphNode("Vesta");
|
||||
//
|
||||
// // if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr ||
|
||||
// //jupiterBarycenterNode == nullptr) {
|
||||
// // LERROR("Necessary nodes does not exist");
|
||||
// //return;
|
||||
// // }
|
||||
//
|
||||
// if (origin == "Pluto") {
|
||||
// if (newHorizonsPathNodeP) {
|
||||
// Renderable* R = newHorizonsPathNodeP->renderable();
|
||||
// newHorizonsPathNodeP->setParent(plutoBarycenterNode);
|
||||
// nhPath = static_cast<RenderablePath*>(R);
|
||||
// nhPath->calculatePath("PLUTO BARYCENTER");
|
||||
// }
|
||||
//
|
||||
// plutoBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem"));
|
||||
// plutoBarycenterNode->setEphemeris(new StaticEphemeris);
|
||||
//
|
||||
// solarSystemBarycenterNode->setParent(plutoBarycenterNode);
|
||||
// newHorizonsNode->setParent(plutoBarycenterNode);
|
||||
// //newHorizonsGhostNode->setParent(plutoBarycenterNode);
|
||||
//
|
||||
// //dawnNode->setParent(plutoBarycenterNode);
|
||||
// //vestaNode->setParent(plutoBarycenterNode);
|
||||
//
|
||||
// //newHorizonsTrailNode->setParent(plutoBarycenterNode);
|
||||
// ghoul::Dictionary solarDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("SUN") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// ghoul::Dictionary jupiterDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("JUPITER BARYCENTER") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// ghoul::Dictionary newHorizonsDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary));
|
||||
// jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary));
|
||||
// newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
// //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary dawnDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("DAWN") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary));
|
||||
// //
|
||||
// //ghoul::Dictionary vestaDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("VESTA") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary));
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary newHorizonsGhostDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// // { std::string("EphmerisGhosting"), std::string("TRUE") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("PLUTO BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary));
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// if (origin == "Sun") {
|
||||
// solarSystemBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem"));
|
||||
//
|
||||
// if (plutoBarycenterNode)
|
||||
// plutoBarycenterNode->setParent(solarSystemBarycenterNode);
|
||||
// jupiterBarycenterNode->setParent(solarSystemBarycenterNode);
|
||||
// if (newHorizonsNode)
|
||||
// newHorizonsNode->setParent(solarSystemBarycenterNode);
|
||||
// //newHorizonsGhostNode->setParent(solarSystemBarycenterNode);
|
||||
//
|
||||
// //newHorizonsTrailNode->setParent(solarSystemBarycenterNode);
|
||||
// //dawnNode->setParent(solarSystemBarycenterNode);
|
||||
// //vestaNode->setParent(solarSystemBarycenterNode);
|
||||
//
|
||||
// ghoul::Dictionary plutoDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("PLUTO BARYCENTER") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("SUN") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
// ghoul::Dictionary jupiterDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("JUPITER BARYCENTER") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("SUN") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// solarSystemBarycenterNode->setEphemeris(new StaticEphemeris);
|
||||
// jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary));
|
||||
// if (plutoBarycenterNode)
|
||||
// plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary));
|
||||
//
|
||||
// ghoul::Dictionary newHorizonsDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("SUN") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
// if (newHorizonsNode)
|
||||
// newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
// //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary dawnDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("DAWN") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("SUN") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary));
|
||||
// //
|
||||
// //ghoul::Dictionary vestaDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("VESTA") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("SUN") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary));
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary newHorizonsGhostDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// // { std::string("EphmerisGhosting"), std::string("TRUE") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary));
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// if (origin == "Jupiter") {
|
||||
// if (newHorizonsPathNodeJ) {
|
||||
// Renderable* R = newHorizonsPathNodeJ->renderable();
|
||||
// newHorizonsPathNodeJ->setParent(jupiterBarycenterNode);
|
||||
// nhPath = static_cast<RenderablePath*>(R);
|
||||
// nhPath->calculatePath("JUPITER BARYCENTER");
|
||||
// }
|
||||
//
|
||||
// jupiterBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem"));
|
||||
// jupiterBarycenterNode->setEphemeris(new StaticEphemeris);
|
||||
//
|
||||
// solarSystemBarycenterNode->setParent(jupiterBarycenterNode);
|
||||
// if (newHorizonsNode)
|
||||
// newHorizonsNode->setParent(jupiterBarycenterNode);
|
||||
// //newHorizonsTrailNode->setParent(jupiterBarycenterNode);
|
||||
//
|
||||
// //dawnNode->setParent(jupiterBarycenterNode);
|
||||
// //vestaNode->setParent(jupiterBarycenterNode);
|
||||
//
|
||||
//
|
||||
// ghoul::Dictionary solarDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("SUN") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// ghoul::Dictionary plutoDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("PlUTO BARYCENTER") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// ghoul::Dictionary newHorizonsDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
// solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary));
|
||||
// if (plutoBarycenterNode)
|
||||
// plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary));
|
||||
// if (newHorizonsNode)
|
||||
// newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
// //newHorizonsGhostNode->setParent(jupiterBarycenterNode);
|
||||
// //newHorizonsTrailNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary dawnDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("DAWN") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary));
|
||||
// //
|
||||
// //ghoul::Dictionary vestaDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("VESTA") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //vestaNode->setEphemeris(new SpiceEphemeris(vestaDictionary));
|
||||
//
|
||||
//
|
||||
//
|
||||
// //ghoul::Dictionary newHorizonsGhostDictionary =
|
||||
// //{
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// // { std::string("EphmerisGhosting"), std::string("TRUE") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("JUPITER BARYCENTER") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// //};
|
||||
// //newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary));
|
||||
// //newHorizonsGhostNode->setParent(jupiterBarycenterNode);
|
||||
//
|
||||
//
|
||||
// return;
|
||||
// }
|
||||
// //if (origin == "Vesta") {
|
||||
// //
|
||||
// // vestaNode->setParent(scene()->sceneGraphNode("SolarSystem"));
|
||||
// // vestaNode->setEphemeris(new StaticEphemeris);
|
||||
// //
|
||||
// // solarSystemBarycenterNode->setParent(vestaNode);
|
||||
// // newHorizonsNode->setParent(vestaNode);
|
||||
// //
|
||||
// // dawnNode->setParent(vestaNode);
|
||||
// // plutoBarycenterNode->setParent(vestaNode);
|
||||
// //
|
||||
// //
|
||||
// // ghoul::Dictionary plutoDictionary =
|
||||
// // {
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("PLUTO BARYCENTER") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("VESTA") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// // };
|
||||
// // ghoul::Dictionary solarDictionary =
|
||||
// // {
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("SUN") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("VESTA") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// // };
|
||||
// //
|
||||
// // ghoul::Dictionary jupiterDictionary =
|
||||
// // {
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("JUPITER BARYCENTER") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("VESTA") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// // };
|
||||
// //
|
||||
// // solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary));
|
||||
// // plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary));
|
||||
// // jupiterBarycenterNode->setEphemeris(new SpiceEphemeris(jupiterDictionary));
|
||||
// //
|
||||
// // ghoul::Dictionary newHorizonsDictionary =
|
||||
// // {
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("NEW HORIZONS") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("VESTA") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// // };
|
||||
// // newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
|
||||
// //
|
||||
// // ghoul::Dictionary dawnDictionary =
|
||||
// // {
|
||||
// // { std::string("Type"), std::string("Spice") },
|
||||
// // { std::string("Body"), std::string("DAWN") },
|
||||
// // { std::string("Reference"), std::string("GALACTIC") },
|
||||
// // { std::string("Observer"), std::string("VESTA") },
|
||||
// // { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// // };
|
||||
// // dawnNode->setEphemeris(new SpiceEphemeris(dawnDictionary));
|
||||
// // vestaNode->setEphemeris(new StaticEphemeris);
|
||||
// //
|
||||
// // return;
|
||||
// //}
|
||||
//
|
||||
// if (origin == "67P") {
|
||||
// SceneGraphNode* rosettaNode = scene()->sceneGraphNode("Rosetta");
|
||||
// SceneGraphNode* cgNode = scene()->sceneGraphNode("67P");
|
||||
// //jupiterBarycenterNode->setParent(solarSystemBarycenterNode);
|
||||
// //plutoBarycenterNode->setParent(solarSystemBarycenterNode);
|
||||
// solarSystemBarycenterNode->setParent(cgNode);
|
||||
// rosettaNode->setParent(cgNode);
|
||||
//
|
||||
// ghoul::Dictionary solarDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("SUN") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
// solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary));
|
||||
//
|
||||
// ghoul::Dictionary rosettaDictionary =
|
||||
// {
|
||||
// { std::string("Type"), std::string("Spice") },
|
||||
// { std::string("Body"), std::string("ROSETTA") },
|
||||
// { std::string("Reference"), std::string("GALACTIC") },
|
||||
// { std::string("Observer"), std::string("CHURYUMOV-GERASIMENKO") },
|
||||
// { std::string("Kernels"), ghoul::Dictionary() }
|
||||
// };
|
||||
//
|
||||
// cgNode->setParent(scene()->sceneGraphNode("SolarSystem"));
|
||||
// rosettaNode->setEphemeris(new SpiceEphemeris(rosettaDictionary));
|
||||
// cgNode->setEphemeris(new StaticEphemeris);
|
||||
//
|
||||
// return;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// LFATAL("This function is being misused with an argument of '" << origin << "'");
|
||||
}
|
||||
|
||||
void RenderEngine::setShowFrameNumber(bool enabled){
|
||||
_showFrameNumber = enabled;
|
||||
}
|
||||
@@ -1370,21 +889,12 @@ void RenderEngine::renderInformation() {
|
||||
|
||||
|
||||
#ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED
|
||||
//<<<<<<< HEAD
|
||||
bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
|
||||
double currentTime = Time::ref().j2000Seconds();
|
||||
|
||||
if (MissionManager::ref().hasCurrentMission()) {
|
||||
|
||||
const Mission& mission = MissionManager::ref().currentMission();
|
||||
//=======
|
||||
// bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
|
||||
// double currentTime = Time::ref().currentTime();
|
||||
//>>>>>>> develop
|
||||
//
|
||||
// if (MissionManager::ref().hasCurrentMission()) {
|
||||
//
|
||||
// const Mission& mission = MissionManager::ref().currentMission();
|
||||
|
||||
if (mission.phases().size() > 0) {
|
||||
|
||||
@@ -1734,7 +1244,11 @@ void RenderEngine::renderScreenLog() {
|
||||
}
|
||||
|
||||
std::vector<Syncable*> RenderEngine::getSyncables(){
|
||||
return _mainCamera->getSyncables();
|
||||
if (_camera) {
|
||||
return _camera->getSyncables();
|
||||
} else {
|
||||
return std::vector<Syncable*>();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEngine::sortScreenspaceRenderables() {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/script_helper.h>
|
||||
#include <openspace/util/time.h>
|
||||
@@ -53,6 +54,8 @@
|
||||
#include <numeric>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
|
||||
#include <modules/onscreengui/include/gui.h>
|
||||
@@ -82,142 +85,121 @@ namespace {
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Scene::Scene() : _focus(SceneGraphNode::RootNodeName) {}
|
||||
Scene::Scene() {}
|
||||
|
||||
Scene::~Scene() {
|
||||
deinitialize();
|
||||
Scene::~Scene() {}
|
||||
|
||||
void Scene::setRoot(std::unique_ptr<SceneGraphNode> root) {
|
||||
if (_root) {
|
||||
removeNode(_root.get());
|
||||
}
|
||||
_root = std::move(root);
|
||||
_root->setScene(this);
|
||||
addNode(_root.get());
|
||||
}
|
||||
|
||||
bool Scene::initialize() {
|
||||
LDEBUG("Initializing SceneGraph");
|
||||
return true;
|
||||
void Scene::setCamera(std::unique_ptr<Camera> camera) {
|
||||
_camera = std::move(camera);
|
||||
}
|
||||
|
||||
bool Scene::deinitialize() {
|
||||
clearSceneGraph();
|
||||
return true;
|
||||
Camera* Scene::camera() const {
|
||||
return _camera.get();
|
||||
}
|
||||
|
||||
void Scene::update(const UpdateData& data) {
|
||||
if (!_sceneGraphToLoad.empty()) {
|
||||
OsEng.renderEngine().scene()->clearSceneGraph();
|
||||
try {
|
||||
loadSceneInternal(_sceneGraphToLoad);
|
||||
void Scene::addNode(SceneGraphNode* node, Scene::UpdateDependencies updateDeps) {
|
||||
// Add the node and all its children.
|
||||
node->traversePreOrder([this](SceneGraphNode* n) {
|
||||
_topologicallySortedNodes.push_back(n);
|
||||
_nodesByName[n->name()] = n;
|
||||
});
|
||||
|
||||
if (updateDeps) {
|
||||
updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the InteractionManager to Orbital/default mode
|
||||
// TODO: Decide if it belongs in the scene and/or how it gets reloaded
|
||||
//OsEng.interactionHandler().setInteractionMode("Orbital");
|
||||
void Scene::removeNode(SceneGraphNode* node, Scene::UpdateDependencies updateDeps) {
|
||||
// Remove the node and all its children.
|
||||
node->traversePostOrder([this](SceneGraphNode* n) {
|
||||
_topologicallySortedNodes.erase(std::remove(_topologicallySortedNodes.begin(), _topologicallySortedNodes.end(), n), _topologicallySortedNodes.end());
|
||||
_nodesByName.erase(n->name());
|
||||
});
|
||||
|
||||
if (updateDeps) {
|
||||
updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
// After loading the scene, the keyboard bindings have been set
|
||||
const std::string KeyboardShortcutsType =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartType;
|
||||
void Scene::updateDependencies() {
|
||||
sortTopologically();
|
||||
}
|
||||
|
||||
const std::string KeyboardShortcutsFile =
|
||||
ConfigurationManager::KeyKeyboardShortcuts + "." +
|
||||
ConfigurationManager::PartFile;
|
||||
void Scene::sortTopologically() {
|
||||
std::copy(_circularNodes.begin(), _circularNodes.end(), std::back_inserter(_topologicallySortedNodes));
|
||||
_circularNodes.clear();
|
||||
|
||||
ghoul_assert(_topologicallySortedNodes.size() == _nodesByName.size(), "Number of scene graph nodes is inconsistent");
|
||||
|
||||
if (_topologicallySortedNodes.empty())
|
||||
return;
|
||||
|
||||
// Only the Root node can have an in-degree of 0
|
||||
SceneGraphNode* root = _nodesByName[SceneGraphNode::RootNodeName];
|
||||
if (!root) {
|
||||
throw Scene::InvalidSceneError("No root node found");
|
||||
}
|
||||
|
||||
|
||||
std::string type;
|
||||
std::string file;
|
||||
bool hasType = OsEng.configurationManager().getValue(
|
||||
KeyboardShortcutsType, type
|
||||
);
|
||||
|
||||
bool hasFile = OsEng.configurationManager().getValue(
|
||||
KeyboardShortcutsFile, file
|
||||
);
|
||||
|
||||
if (hasType && hasFile) {
|
||||
OsEng.interactionHandler().writeKeyboardDocumentation(type, file);
|
||||
|
||||
std::unordered_map<SceneGraphNode*, size_t> inDegrees;
|
||||
for (SceneGraphNode* node : _topologicallySortedNodes) {
|
||||
size_t inDegree = node->dependencies().size();
|
||||
if (node->parent() != nullptr) {
|
||||
inDegree++;
|
||||
inDegrees[node] = inDegree;
|
||||
}
|
||||
}
|
||||
|
||||
std::stack<SceneGraphNode*> zeroInDegreeNodes;
|
||||
zeroInDegreeNodes.push(root);
|
||||
|
||||
std::vector<SceneGraphNode*> nodes;
|
||||
nodes.reserve(_topologicallySortedNodes.size());
|
||||
while (!zeroInDegreeNodes.empty()) {
|
||||
SceneGraphNode* node = zeroInDegreeNodes.top();
|
||||
nodes.push_back(node);
|
||||
zeroInDegreeNodes.pop();
|
||||
|
||||
for (auto& n : node->dependentNodes()) {
|
||||
auto it = inDegrees.find(n);
|
||||
it->second -= 1;
|
||||
if (it->second == 0) {
|
||||
zeroInDegreeNodes.push(n);
|
||||
inDegrees.erase(it);
|
||||
}
|
||||
|
||||
LINFO("Loaded " << _sceneGraphToLoad);
|
||||
_sceneGraphToLoad = "";
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERROR(e.what());
|
||||
_sceneGraphToLoad = "";
|
||||
return;
|
||||
for (auto& n : node->children()) {
|
||||
auto it = inDegrees.find(n);
|
||||
it->second -= 1;
|
||||
if (it->second == 0) {
|
||||
zeroInDegreeNodes.push(n);
|
||||
inDegrees.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
try {
|
||||
node->update(data);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
if (inDegrees.size() > 0) {
|
||||
LERROR("The scene contains circular dependencies. " << inDegrees.size() << " nodes will be disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
void Scene::evaluate(Camera* camera) {
|
||||
for (SceneGraphNode* node : _graph.nodes())
|
||||
node->evaluate(camera);
|
||||
//_root->evaluate(camera);
|
||||
}
|
||||
|
||||
void Scene::render(const RenderData& data, RendererTasks& tasks) {
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
node->render(data, tasks);
|
||||
for (auto& it : inDegrees) {
|
||||
_circularNodes.push_back(it.first);
|
||||
}
|
||||
|
||||
_topologicallySortedNodes = nodes;
|
||||
}
|
||||
|
||||
void Scene::scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath) {
|
||||
_sceneGraphToLoad = sceneDescriptionFilePath;
|
||||
}
|
||||
|
||||
void Scene::clearSceneGraph() {
|
||||
LINFO("Clearing current scene graph");
|
||||
// deallocate the scene graph. Recursive deallocation will occur
|
||||
_graph.clear();
|
||||
//if (_root) {
|
||||
// _root->deinitialize();
|
||||
// delete _root;
|
||||
// _root = nullptr;
|
||||
//}
|
||||
|
||||
// _nodes.erase(_nodes.begin(), _nodes.end());
|
||||
// _allNodes.erase(_allNodes.begin(), _allNodes.end());
|
||||
|
||||
_focus.clear();
|
||||
}
|
||||
|
||||
bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
|
||||
ghoul::Dictionary dictionary;
|
||||
|
||||
OsEng.windowWrapper().setSynchronization(false);
|
||||
OnExit(
|
||||
[](){ OsEng.windowWrapper().setSynchronization(true); }
|
||||
);
|
||||
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
// Delete the Lua state at the end of the scope, no matter what
|
||||
[state](){ ghoul::lua::destroyLuaState(state); }
|
||||
);
|
||||
|
||||
OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
ghoul::lua::loadDictionaryFromFile(
|
||||
sceneDescriptionFilePath,
|
||||
dictionary,
|
||||
state
|
||||
);
|
||||
|
||||
// Perform testing against the documentation/specification
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
Scene::Documentation(),
|
||||
dictionary,
|
||||
"Scene"
|
||||
);
|
||||
|
||||
|
||||
_graph.loadFromFile(sceneDescriptionFilePath);
|
||||
|
||||
// Initialize all nodes
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
void Scene::initialize() {
|
||||
for (SceneGraphNode* node : _topologicallySortedNodes) {
|
||||
try {
|
||||
bool success = node->initialize();
|
||||
if (success)
|
||||
@@ -229,221 +211,64 @@ bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
|
||||
LERRORC(_loggerCat + "(" + e.component + ")", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// update the position of all nodes
|
||||
// TODO need to check this; unnecessary? (ab)
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
try {
|
||||
node->update({
|
||||
glm::dvec3(0),
|
||||
glm::dmat3(1),
|
||||
1,
|
||||
Time::ref().j2000Seconds() });
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = _graph.nodes().rbegin(); it != _graph.nodes().rend(); ++it)
|
||||
(*it)->calculateBoundingSphere();
|
||||
|
||||
// Read the camera dictionary and set the camera state
|
||||
ghoul::Dictionary cameraDictionary;
|
||||
if (dictionary.getValue(KeyCamera, cameraDictionary)) {
|
||||
OsEng.interactionHandler().setCameraStateFromDictionary(cameraDictionary);
|
||||
}
|
||||
|
||||
// If a PropertyDocumentationFile was specified, generate it now
|
||||
const std::string KeyPropertyDocumentationType =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartType;
|
||||
|
||||
const std::string KeyPropertyDocumentationFile =
|
||||
ConfigurationManager::KeyPropertyDocumentation + '.' +
|
||||
ConfigurationManager::PartFile;
|
||||
|
||||
const bool hasType = OsEng.configurationManager().hasKey(KeyPropertyDocumentationType);
|
||||
const bool hasFile = OsEng.configurationManager().hasKey(KeyPropertyDocumentationFile);
|
||||
if (hasType && hasFile) {
|
||||
std::string propertyDocumentationType;
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationType, propertyDocumentationType);
|
||||
std::string propertyDocumentationFile;
|
||||
OsEng.configurationManager().getValue(KeyPropertyDocumentationFile, propertyDocumentationFile);
|
||||
|
||||
propertyDocumentationFile = absPath(propertyDocumentationFile);
|
||||
writePropertyDocumentation(propertyDocumentationFile, propertyDocumentationType, sceneDescriptionFilePath);
|
||||
}
|
||||
|
||||
|
||||
OsEng.runPostInitializationScripts(sceneDescriptionFilePath);
|
||||
|
||||
OsEng.enableBarrier();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//void Scene::loadModules(
|
||||
// const std::string& directory,
|
||||
// const ghoul::Dictionary& dictionary)
|
||||
//{
|
||||
// // Struct containing dependencies and nodes
|
||||
// LoadMaps m;
|
||||
//
|
||||
// // Get the common directory
|
||||
// std::string commonDirectory(_defaultCommonDirectory);
|
||||
// dictionary.getValue(constants::scenegraph::keyCommonFolder, commonDirectory);
|
||||
// FileSys.registerPathToken(_commonModuleToken, commonDirectory);
|
||||
//
|
||||
// lua_State* state = ghoul::lua::createNewLuaState();
|
||||
// OsEng.scriptEngine()->initializeLuaState(state);
|
||||
//
|
||||
// LDEBUG("Loading common module folder '" << commonDirectory << "'");
|
||||
// // Load common modules into LoadMaps struct
|
||||
// loadModule(m, FileSys.pathByAppendingComponent(directory, commonDirectory), state);
|
||||
//
|
||||
// // Load the rest of the modules into LoadMaps struct
|
||||
// ghoul::Dictionary moduleDictionary;
|
||||
// if (dictionary.getValue(constants::scenegraph::keyModules, moduleDictionary)) {
|
||||
// std::vector<std::string> keys = moduleDictionary.keys();
|
||||
// std::sort(keys.begin(), keys.end());
|
||||
// for (const std::string& key : keys) {
|
||||
// std::string moduleFolder;
|
||||
// if (moduleDictionary.getValue(key, moduleFolder)) {
|
||||
// loadModule(m, FileSys.pathByAppendingComponent(directory, moduleFolder), state);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Load and construct scenegraphnodes from LoadMaps struct
|
||||
// loadNodes(SceneGraphNode::RootNodeName, m);
|
||||
//
|
||||
// // Remove loaded nodes from dependency list
|
||||
// for(const auto& name: m.loadedNodes) {
|
||||
// m.dependencies.erase(name);
|
||||
// }
|
||||
//
|
||||
// // Check to see what dependencies are not resolved.
|
||||
// for(auto& node: m.dependencies) {
|
||||
// LWARNING(
|
||||
// "'" << node.second << "'' not loaded, parent '"
|
||||
// << node.first << "' not defined!");
|
||||
// }
|
||||
//}
|
||||
void Scene::update(const UpdateData& data) {
|
||||
for (auto& node : _topologicallySortedNodes) {
|
||||
try {
|
||||
node->update(data);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void Scene::loadModule(LoadMaps& m,const std::string& modulePath, lua_State* state) {
|
||||
// auto pos = modulePath.find_last_of(ghoul::filesystem::FileSystem::PathSeparator);
|
||||
// if (pos == modulePath.npos) {
|
||||
// LERROR("Bad format for module path: " << modulePath);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// std::string fullModule = modulePath + modulePath.substr(pos) + _moduleExtension;
|
||||
// LDEBUG("Loading nodes from: " << fullModule);
|
||||
//
|
||||
// ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
// FileSys.setCurrentDirectory(modulePath);
|
||||
//
|
||||
// ghoul::Dictionary moduleDictionary;
|
||||
// ghoul::lua::loadDictionaryFromFile(fullModule, moduleDictionary, state);
|
||||
// std::vector<std::string> keys = moduleDictionary.keys();
|
||||
// for (const std::string& key : keys) {
|
||||
// if (!moduleDictionary.hasValue<ghoul::Dictionary>(key)) {
|
||||
// LERROR("SceneGraphElement '" << key << "' is not a table in module '"
|
||||
// << fullModule << "'");
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// ghoul::Dictionary element;
|
||||
// std::string nodeName;
|
||||
// std::string parentName;
|
||||
//
|
||||
// moduleDictionary.getValue(key, element);
|
||||
// element.setValue(constants::scenegraph::keyPathModule, modulePath);
|
||||
//
|
||||
// element.getValue(constants::scenegraphnode::keyName, nodeName);
|
||||
// element.getValue(constants::scenegraphnode::keyParentName, parentName);
|
||||
//
|
||||
// m.nodes[nodeName] = element;
|
||||
// m.dependencies.emplace(parentName,nodeName);
|
||||
// }
|
||||
//
|
||||
// FileSys.setCurrentDirectory(oldDirectory);
|
||||
//}
|
||||
void Scene::evaluate(Camera* camera) {
|
||||
for (auto& node : _topologicallySortedNodes) {
|
||||
try {
|
||||
node->evaluate(camera);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void Scene::loadNodes(const std::string& parentName, LoadMaps& m) {
|
||||
// auto eqRange = m.dependencies.equal_range(parentName);
|
||||
// for (auto it = eqRange.first; it != eqRange.second; ++it) {
|
||||
// auto node = m.nodes.find((*it).second);
|
||||
// loadNode(node->second);
|
||||
// loadNodes((*it).second, m);
|
||||
// }
|
||||
// m.loadedNodes.emplace_back(parentName);
|
||||
//}
|
||||
//
|
||||
//void Scene::loadNode(const ghoul::Dictionary& dictionary) {
|
||||
// SceneGraphNode* node = SceneGraphNode::createFromDictionary(dictionary);
|
||||
// if(node) {
|
||||
// _allNodes.emplace(node->name(), node);
|
||||
// _nodes.push_back(node);
|
||||
// }
|
||||
//}
|
||||
void Scene::render(const RenderData& data, RendererTasks& tasks) {
|
||||
for (auto& node : _topologicallySortedNodes) {
|
||||
try {
|
||||
node->render(data, tasks);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
LERRORC(e.component, e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void SceneGraph::loadModule(const std::string& modulePath) {
|
||||
// auto pos = modulePath.find_last_of(ghoul::filesystem::FileSystem::PathSeparator);
|
||||
// if (pos == modulePath.npos) {
|
||||
// LERROR("Bad format for module path: " << modulePath);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// std::string fullModule = modulePath + modulePath.substr(pos) + _moduleExtension;
|
||||
// LDEBUG("Loading modules from: " << fullModule);
|
||||
//
|
||||
// ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
// FileSys.setCurrentDirectory(modulePath);
|
||||
//
|
||||
// ghoul::Dictionary moduleDictionary;
|
||||
// ghoul::lua::loadDictionaryFromFile(fullModule, moduleDictionary);
|
||||
// std::vector<std::string> keys = moduleDictionary.keys();
|
||||
// for (const std::string& key : keys) {
|
||||
// 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(constants::scenegraph::keyPathModule, modulePath);
|
||||
//
|
||||
// //each element in this new dictionary becomes a scenegraph node.
|
||||
// SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
|
||||
//
|
||||
// _allNodes.emplace(node->name(), node);
|
||||
// _nodes.push_back(node);
|
||||
// }
|
||||
//
|
||||
// FileSys.setCurrentDirectory(oldDirectory);
|
||||
//
|
||||
// // Print the tree
|
||||
// //printTree(_root);
|
||||
//}
|
||||
void Scene::clear() {
|
||||
LINFO("Clearing current scene graph");
|
||||
_root = nullptr;
|
||||
}
|
||||
|
||||
const std::map<std::string, SceneGraphNode*>& Scene::nodesByName() const {
|
||||
return _nodesByName;
|
||||
}
|
||||
|
||||
SceneGraphNode* Scene::root() const {
|
||||
return _graph.rootNode();
|
||||
return _root.get();
|
||||
}
|
||||
|
||||
SceneGraphNode* Scene::sceneGraphNode(const std::string& name) const {
|
||||
return _graph.sceneGraphNode(name);
|
||||
auto it = _nodesByName.find(name);
|
||||
if (it != _nodesByName.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> Scene::allSceneGraphNodes() const {
|
||||
return _graph.nodes();
|
||||
}
|
||||
|
||||
SceneGraph& Scene::sceneGraph() {
|
||||
return _graph;
|
||||
const std::vector<SceneGraphNode*>& Scene::allSceneGraphNodes() const {
|
||||
return _topologicallySortedNodes;
|
||||
}
|
||||
|
||||
void Scene::writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename) {
|
||||
@@ -454,7 +279,7 @@ void Scene::writePropertyDocumentation(const std::string& filename, const std::s
|
||||
file.open(filename);
|
||||
|
||||
using properties::Property;
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
for (SceneGraphNode* node : allSceneGraphNodes()) {
|
||||
std::vector<Property*> properties = node->propertiesRecursive();
|
||||
if (!properties.empty()) {
|
||||
file << node->name() << std::endl;
|
||||
@@ -544,7 +369,7 @@ void Scene::writePropertyDocumentation(const std::string& filename, const std::s
|
||||
|
||||
std::stringstream json;
|
||||
json << "[";
|
||||
std::vector<SceneGraphNode*> nodes = _graph.nodes();
|
||||
std::vector<SceneGraphNode*> nodes = allSceneGraphNodes();
|
||||
if (!nodes.empty()) {
|
||||
json << std::accumulate(
|
||||
std::next(nodes.begin()),
|
||||
@@ -595,45 +420,6 @@ void Scene::writePropertyDocumentation(const std::string& filename, const std::s
|
||||
<< "\t<body>\n"
|
||||
<< "\t<body>\n"
|
||||
<< "</html>\n";
|
||||
|
||||
/*
|
||||
|
||||
html << "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
<< "\t\t<title>Properties</title>\n"
|
||||
<< "\t</head>\n"
|
||||
<< "<body>\n"
|
||||
<< "<table cellpadding=3 cellspacing=0 border=1>\n"
|
||||
<< "\t<caption>Properties</caption>\n\n"
|
||||
<< "\t<thead>\n"
|
||||
<< "\t\t<tr>\n"
|
||||
<< "\t\t\t<th>ID</th>\n"
|
||||
<< "\t\t\t<th>Type</th>\n"
|
||||
<< "\t\t\t<th>Description</th>\n"
|
||||
<< "\t\t</tr>\n"
|
||||
<< "\t</thead>\n"
|
||||
<< "\t<tbody>\n";
|
||||
|
||||
for (SceneGraphNode* node : _graph.nodes()) {
|
||||
for (properties::Property* p : node->propertiesRecursive()) {
|
||||
html << "\t\t<tr>\n"
|
||||
<< "\t\t\t<td>" << p->fullyQualifiedIdentifier() << "</td>\n"
|
||||
<< "\t\t\t<td>" << p->className() << "</td>\n"
|
||||
<< "\t\t\t<td>" << p->guiName() << "</td>\n"
|
||||
<< "\t\t</tr>\n";
|
||||
}
|
||||
|
||||
if (!node->propertiesRecursive().empty()) {
|
||||
html << "\t<tr><td style=\"line-height: 10px;\" colspan=3></td></tr>\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
html << "\t</tbody>\n"
|
||||
<< "</table>\n"
|
||||
<< "</html>;";
|
||||
|
||||
*/
|
||||
file << html.str();
|
||||
}
|
||||
else
|
||||
@@ -700,4 +486,8 @@ scripting::LuaLibrary Scene::luaLibrary() {
|
||||
};
|
||||
}
|
||||
|
||||
Scene::InvalidSceneError::InvalidSceneError(const std::string& error, const std::string& comp)
|
||||
: ghoul::RuntimeError(error, comp)
|
||||
{}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -213,9 +213,8 @@ int loadScene(lua_State* L) {
|
||||
SCRIPT_CHECK_ARGUMENTS("loadScene", L, 1, nArguments);
|
||||
|
||||
std::string sceneFile = luaL_checkstring(L, -1);
|
||||
|
||||
OsEng.renderEngine().scene()->scheduleLoadSceneFile(sceneFile);
|
||||
|
||||
|
||||
OsEng.scheduleLoadScene(sceneFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -234,22 +233,11 @@ int addSceneGraphNode(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SceneGraphNode* node = SceneGraphNode::createFromDictionary(d);
|
||||
|
||||
std::string parent = d.value<std::string>(SceneGraphNode::KeyParentName);
|
||||
SceneGraphNode* parentNode = OsEng.renderEngine().scene()->sceneGraphNode(parent);
|
||||
if (!parentNode) {
|
||||
LERRORC(
|
||||
"addSceneGraphNode",
|
||||
errorLocation(L) << "Could not find parent node '" << parent << "'"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
node->setParent(parentNode);
|
||||
node->initialize();
|
||||
OsEng.renderEngine().scene()->sceneGraph().addSceneGraphNode(node);
|
||||
SceneLoader loader;
|
||||
SceneGraphNode* importedNode = loader.importNodeDictionary(*OsEng.renderEngine().scene(), d);
|
||||
importedNode->initialize();
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int removeSceneGraphNode(lua_State* L) {
|
||||
@@ -257,21 +245,25 @@ int removeSceneGraphNode(lua_State* L) {
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("removeSceneGraphNode", L, 1, nArguments);
|
||||
|
||||
|
||||
std::string nodeName = luaL_checkstring(L, -1);
|
||||
SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(nodeName);
|
||||
if (!node) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNode",
|
||||
errorLocation(L) << "Could not find node '" << nodeName << "'"
|
||||
);
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OsEng.renderEngine().scene()->sceneGraph().removeSceneGraphNode(node);
|
||||
node->deinitialize();
|
||||
delete node;
|
||||
|
||||
SceneGraphNode* parent = node->parent();
|
||||
if (!parent) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNode",
|
||||
errorLocation(L) << "Cannot remove root node"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
parent->detachChild(*node);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,578 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/scene/scenegraph.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
#include <ghoul/misc/onscopeexit.h>
|
||||
|
||||
#include <stack>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef OPENSPACE_ENABLE_VLD
|
||||
#include <vld.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SceneGraph";
|
||||
const std::string _moduleExtension = ".mod";
|
||||
const std::string _defaultCommonDirectory = "common";
|
||||
const std::string _commonModuleToken = "${COMMON_MODULE}";
|
||||
|
||||
const std::string KeyPathScene = "ScenePath";
|
||||
const std::string KeyModules = "Modules";
|
||||
const std::string KeyCommonFolder = "CommonFolder";
|
||||
const std::string KeyPathModule = "ModulePath";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
SceneGraph::SceneGraphNodeInternal::~SceneGraphNodeInternal() {
|
||||
delete node;
|
||||
}
|
||||
|
||||
SceneGraph::SceneGraph()
|
||||
: _rootNode(nullptr)
|
||||
{}
|
||||
|
||||
SceneGraph::~SceneGraph() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void SceneGraph::clear() {
|
||||
// Untested ---abock
|
||||
for (SceneGraphNodeInternal* n : _nodes)
|
||||
delete n;
|
||||
|
||||
_nodes.clear();
|
||||
_rootNode = nullptr;
|
||||
}
|
||||
|
||||
bool SceneGraph::loadFromFile(const std::string& sceneDescription) {
|
||||
clear(); // Move this to a later stage to retain a proper scenegraph when the loading fails ---abock
|
||||
|
||||
std::string absSceneFile = absPath(sceneDescription);
|
||||
|
||||
// See if scene file exists
|
||||
using RawPath = ghoul::filesystem::FileSystem::RawPath;
|
||||
if (!FileSys.fileExists(absSceneFile, RawPath::Yes)) {
|
||||
LERROR("Could not load scene file '" << absSceneFile << "'. " <<
|
||||
"File not found");
|
||||
return false;
|
||||
}
|
||||
LINFO("Loading SceneGraph from file '" << absSceneFile << "'");
|
||||
|
||||
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
// Delete the Lua state at the end of the scope, no matter what
|
||||
[state](){ghoul::lua::destroyLuaState(state);}
|
||||
);
|
||||
|
||||
OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
|
||||
// Load dictionary
|
||||
ghoul::Dictionary sceneDictionary;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(
|
||||
absSceneFile,
|
||||
sceneDictionary,
|
||||
state
|
||||
);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sceneDescriptionDirectory = ghoul::filesystem::File(
|
||||
absSceneFile,
|
||||
ghoul::filesystem::File::RawPath::Yes
|
||||
).directoryName();
|
||||
std::string sceneDirectory(".");
|
||||
sceneDictionary.getValue(KeyPathScene, sceneDirectory);
|
||||
|
||||
// The scene path could either be an absolute or relative path to the description
|
||||
// paths directory
|
||||
std::string relativeCandidate = sceneDescriptionDirectory +
|
||||
ghoul::filesystem::FileSystem::PathSeparator + sceneDirectory;
|
||||
std::string absoluteCandidate = absPath(sceneDirectory);
|
||||
|
||||
if (FileSys.directoryExists(relativeCandidate))
|
||||
sceneDirectory = relativeCandidate;
|
||||
else if (FileSys.directoryExists(absoluteCandidate))
|
||||
sceneDirectory = absoluteCandidate;
|
||||
else {
|
||||
LERROR("The '" << KeyPathScene << "' pointed to a "
|
||||
"path '" << sceneDirectory << "' that did not exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
ghoul::Dictionary moduleDictionary;
|
||||
bool success = sceneDictionary.getValue(KeyModules, moduleDictionary);
|
||||
if (!success)
|
||||
// There are no modules that are loaded
|
||||
return true;
|
||||
|
||||
// lua_State* state = ghoul::lua::createNewLuaState();
|
||||
// OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
// Above we generated a ghoul::Dictionary from the scene file; now we run the scene
|
||||
// file again to load any variables defined inside into the state that is passed to
|
||||
// the modules. This allows us to specify global variables that can then be used
|
||||
// inside the modules to toggle settings
|
||||
ghoul::lua::runScriptFile(state, absSceneFile);
|
||||
|
||||
// Get the common directory
|
||||
bool commonFolderSpecified = sceneDictionary.hasKey(KeyCommonFolder);
|
||||
bool commonFolderCorrectType = sceneDictionary.hasKeyAndValue<std::string>(KeyCommonFolder);
|
||||
|
||||
if (commonFolderSpecified) {
|
||||
if (commonFolderCorrectType) {
|
||||
std::string commonFolder = sceneDictionary.value<std::string>(KeyCommonFolder);
|
||||
std::string fullCommonFolder = FileSys.pathByAppendingComponent(
|
||||
sceneDirectory,
|
||||
commonFolder
|
||||
);
|
||||
if (!FileSys.directoryExists(fullCommonFolder))
|
||||
LERROR("Specified common folder '" << fullCommonFolder << "' did not exist");
|
||||
else {
|
||||
if (!commonFolder.empty()) {
|
||||
FileSys.registerPathToken(
|
||||
_commonModuleToken, commonFolder,
|
||||
ghoul::filesystem::FileSystem::Override::Yes
|
||||
);
|
||||
size_t nKeys = moduleDictionary.size();
|
||||
moduleDictionary.setValue(
|
||||
std::to_string(nKeys + 1),
|
||||
commonFolder
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
LERROR("Specification for 'common' folder has invalid type");
|
||||
}
|
||||
|
||||
std::vector<std::string> keys = moduleDictionary.keys();
|
||||
|
||||
std::map<std::string, std::vector<std::string>> dependencies;
|
||||
std::map<std::string, std::string> parents;
|
||||
|
||||
_rootNode = new SceneGraphNode;
|
||||
_rootNode->setName(SceneGraphNode::RootNodeName);
|
||||
SceneGraphNodeInternal* internalRoot = new SceneGraphNodeInternal;
|
||||
internalRoot->node = _rootNode;
|
||||
_nodes.push_back(internalRoot);
|
||||
|
||||
std::sort(keys.begin(), keys.end());
|
||||
ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
for (const std::string& key : keys) {
|
||||
std::string fullModuleName = moduleDictionary.value<std::string>(key);
|
||||
|
||||
std::replace(fullModuleName.begin(), fullModuleName.end(), '/', FileSys.PathSeparator);
|
||||
|
||||
std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, fullModuleName);
|
||||
|
||||
std::string moduleName = fullModuleName;
|
||||
std::string::size_type pos = fullModuleName.find_last_of(FileSys.PathSeparator);
|
||||
if (pos != std::string::npos)
|
||||
moduleName = fullModuleName.substr(pos + 1);
|
||||
|
||||
if (!FileSys.directoryExists(modulePath)) {
|
||||
LERROR("Could not load module '" << moduleName << "'. Directory did not exist");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string moduleFile = FileSys.pathByAppendingComponent(
|
||||
modulePath,
|
||||
moduleName + _moduleExtension
|
||||
);
|
||||
|
||||
struct ModuleInformation {
|
||||
ghoul::Dictionary dictionary;
|
||||
std::string moduleFile;
|
||||
std::string modulePath;
|
||||
std::string moduleName;
|
||||
};
|
||||
std::vector<ModuleInformation> moduleDictionaries;
|
||||
if (FileSys.fileExists(moduleFile)) {
|
||||
// We have a module file, so it is a direct include
|
||||
try {
|
||||
ghoul::Dictionary moduleDictionary;
|
||||
ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state);
|
||||
moduleDictionaries.push_back({
|
||||
moduleDictionary,
|
||||
moduleFile,
|
||||
modulePath,
|
||||
moduleName
|
||||
});
|
||||
}
|
||||
catch (const ghoul::lua::LuaRuntimeException& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// If we do not have a module file, we have to include all subdirectories
|
||||
using ghoul::filesystem::Directory;
|
||||
using std::string;
|
||||
std::vector<string> directories = Directory(modulePath).readDirectories();
|
||||
|
||||
for (const string& s : directories) {
|
||||
std::string::size_type pos = s.find_last_of(FileSys.PathSeparator);
|
||||
if (pos == std::string::npos) {
|
||||
LERROR("Error parsing subdirectory name '" << s << "'");
|
||||
continue;
|
||||
}
|
||||
string moduleName = s.substr(pos+1);
|
||||
|
||||
string submodulePath = s;
|
||||
string moduleFile = FileSys.pathByAppendingComponent(submodulePath, moduleName) + _moduleExtension;
|
||||
// string moduleName = s;
|
||||
|
||||
if (!FileSys.fileExists(moduleFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a module file, so it is a direct include
|
||||
try {
|
||||
ghoul::Dictionary moduleDictionary;
|
||||
ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state);
|
||||
moduleDictionaries.push_back({
|
||||
moduleDictionary,
|
||||
moduleFile,
|
||||
submodulePath,
|
||||
moduleName
|
||||
});
|
||||
}
|
||||
catch (const ghoul::lua::LuaRuntimeException& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto addModule = [this, &dependencies, &parents](const ModuleInformation& moduleInformation) {
|
||||
const ghoul::Dictionary& moduleDictionary = moduleInformation.dictionary;
|
||||
const std::string& moduleFile = moduleInformation.moduleFile;
|
||||
const std::string& modulePath = moduleInformation.modulePath;
|
||||
const std::string& moduleName = moduleInformation.moduleName;
|
||||
|
||||
std::vector<std::string> keys = moduleDictionary.keys();
|
||||
for (const std::string& key : keys) {
|
||||
if (!moduleDictionary.hasValue<ghoul::Dictionary>(key)) {
|
||||
LERROR("SceneGraphNode '" << key << "' is not a table in module '"
|
||||
<< moduleFile << "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
ghoul::Dictionary element;
|
||||
std::string nodeName;
|
||||
std::string parentName;
|
||||
|
||||
moduleDictionary.getValue(key, element);
|
||||
element.setValue(KeyPathModule, modulePath);
|
||||
|
||||
element.getValue(SceneGraphNode::KeyName, nodeName);
|
||||
element.getValue(SceneGraphNode::KeyParentName, parentName);
|
||||
|
||||
FileSys.setCurrentDirectory(modulePath);
|
||||
LDEBUGC("Create from dictionary", "Node name: " << nodeName << " Parent name:" << parentName << " Path: " << modulePath);
|
||||
SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
|
||||
if (node == nullptr) {
|
||||
LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
dependencies[nodeName].push_back(parentName);
|
||||
parents[nodeName] = parentName;
|
||||
// Also include loaded dependencies
|
||||
|
||||
if (element.hasKey(SceneGraphNode::KeyDependencies)) {
|
||||
if (element.hasValue<ghoul::Dictionary>(SceneGraphNode::KeyDependencies)) {
|
||||
ghoul::Dictionary nodeDependencies;
|
||||
element.getValue(SceneGraphNode::KeyDependencies, nodeDependencies);
|
||||
|
||||
std::vector<std::string> keys = nodeDependencies.keys();
|
||||
for (const std::string& key : keys) {
|
||||
std::string value = nodeDependencies.value<std::string>(key);
|
||||
dependencies[nodeName].push_back(value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LERROR("Dependencies did not have the corrent type");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal;
|
||||
internalNode->node = node;
|
||||
_nodes.push_back(internalNode);
|
||||
}
|
||||
};
|
||||
|
||||
for (const ModuleInformation& i : moduleDictionaries) {
|
||||
try {
|
||||
LINFO("Adding module: " << i.moduleName);
|
||||
addModule(i);
|
||||
}
|
||||
catch (const documentation::SpecificationError& specError) {
|
||||
LERROR("Error loading module: " << i.moduleName);
|
||||
LERRORC(specError.component, specError.message);
|
||||
for (const auto& offense : specError.result.offenses) {
|
||||
LERRORC(offense.offender, std::to_string(offense.reason));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ghoul::lua::destroyLuaState(state);
|
||||
FileSys.setCurrentDirectory(oldDirectory);
|
||||
|
||||
for (SceneGraphNodeInternal* node : _nodes) {
|
||||
if (node->node == _rootNode)
|
||||
continue;
|
||||
std::string parent = parents[node->node->name()];
|
||||
SceneGraphNode* parentNode = sceneGraphNode(parent);
|
||||
if (parentNode == nullptr) {
|
||||
LERROR("Could not find parent '" << parent << "' for '" << node->node->name() << "'");
|
||||
continue;
|
||||
}
|
||||
|
||||
node->node->setParent(parentNode);
|
||||
parentNode->addChild(node->node);
|
||||
|
||||
}
|
||||
|
||||
// Setup dependencies
|
||||
for (SceneGraphNodeInternal* node : _nodes) {
|
||||
std::vector<std::string> nodeDependencies = dependencies[node->node->name()];
|
||||
|
||||
for (const std::string& dep : nodeDependencies) {
|
||||
SceneGraphNodeInternal* n = nodeByName(dep);
|
||||
if (n == nullptr) {
|
||||
LERROR("Dependent node '" << dep << "' was not loaded for '" <<node->node->name() << "'");
|
||||
continue;
|
||||
}
|
||||
node->outgoingEdges.push_back(n);
|
||||
n->incomingEdges.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNodeInternal*> nodesToDelete;
|
||||
for (SceneGraphNodeInternal* node : _nodes) {
|
||||
if (!nodeIsDependentOnRoot(node)) {
|
||||
LERROR("Node '" << node->node->name() << "' has no direct connection to Root.");
|
||||
nodesToDelete.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
for (SceneGraphNodeInternal* node : nodesToDelete) {
|
||||
_nodes.erase(std::find(_nodes.begin(), _nodes.end(), node));
|
||||
delete node;
|
||||
}
|
||||
|
||||
bool s = sortTopologically();
|
||||
if (!s) {
|
||||
LERROR("Topological sort failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceneGraph::nodeIsDependentOnRoot(SceneGraphNodeInternal* node) {
|
||||
if (node->node->name() == SceneGraphNode::RootNodeName)
|
||||
return true;
|
||||
else {
|
||||
for (SceneGraphNodeInternal* n : node->outgoingEdges) {
|
||||
bool dep = nodeIsDependentOnRoot(n);
|
||||
if (dep)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SceneGraph::sortTopologically() {
|
||||
if (_nodes.empty())
|
||||
return true;
|
||||
|
||||
// Only the Root node can have an in-degree of 0
|
||||
SceneGraphNodeInternal* root = nodeByName(SceneGraphNode::RootNodeName);
|
||||
ghoul_assert(root != nullptr, "Could not find Root node");
|
||||
|
||||
std::stack<SceneGraphNodeInternal*> zeroInDegreeNodes;
|
||||
zeroInDegreeNodes.push(root);
|
||||
|
||||
std::unordered_map<SceneGraphNodeInternal*, size_t> inDegrees;
|
||||
for (SceneGraphNodeInternal* node : _nodes)
|
||||
inDegrees[node] = node->outgoingEdges.size();
|
||||
//inDegrees[node] = node->incomingEdges.size();
|
||||
|
||||
_topologicalSortedNodes.clear();
|
||||
_topologicalSortedNodes.reserve(_nodes.size());
|
||||
while (!zeroInDegreeNodes.empty()) {
|
||||
SceneGraphNodeInternal* node = zeroInDegreeNodes.top();
|
||||
|
||||
_topologicalSortedNodes.push_back(node->node);
|
||||
zeroInDegreeNodes.pop();
|
||||
|
||||
//for (SceneGraphNodeInternal* n : node->outgoingEdges) {
|
||||
for (SceneGraphNodeInternal* n : node->incomingEdges) {
|
||||
inDegrees[n] -= 1;
|
||||
if (inDegrees[n] == 0)
|
||||
zeroInDegreeNodes.push(n);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceneGraph::addSceneGraphNode(SceneGraphNode* node) {
|
||||
// @TODO rework this ---abock
|
||||
ghoul_assert(node, "Node must not be nullptr");
|
||||
|
||||
SceneGraphNodeInternal* internalNode = new SceneGraphNodeInternal;
|
||||
internalNode->node = node;
|
||||
|
||||
auto it = std::find_if(
|
||||
_nodes.begin(),
|
||||
_nodes.end(),
|
||||
[node](SceneGraphNodeInternal* i) {
|
||||
return i->node == node->parent();
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _nodes.end()) {
|
||||
LERROR("Parent node was not found");
|
||||
delete internalNode;
|
||||
return false;
|
||||
}
|
||||
|
||||
(*it)->incomingEdges.push_back(internalNode);
|
||||
internalNode->outgoingEdges.push_back(*it);
|
||||
|
||||
_nodes.push_back(internalNode);
|
||||
sortTopologically();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SceneGraph::removeSceneGraphNode(SceneGraphNode* node) {
|
||||
// @TODO rework this ---abock
|
||||
ghoul_assert(node, "Node must not be nullptr");
|
||||
|
||||
auto it = std::find_if(
|
||||
_nodes.begin(),
|
||||
_nodes.end(),
|
||||
[node](SceneGraphNodeInternal* i) {
|
||||
return i->node == node;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _nodes.end()) {
|
||||
LERROR("The node '" << node->name() << "' did not exist in the scenegraph");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove internal node from the list of nodes
|
||||
//SceneGraphNodeInternal* internalNode = *it;
|
||||
_nodes.erase(it);
|
||||
|
||||
if (OsEng.interactionHandler().focusNode() == node)
|
||||
OsEng.interactionHandler().setFocusNode(node->parent());
|
||||
|
||||
sortTopologically();
|
||||
|
||||
#if 0
|
||||
SceneGraphNodeInternal* parentInternalNode = nodeByName(node->parent()->name());
|
||||
ghoul_assert(parentInternalNode, "Could not find internal parent node");
|
||||
|
||||
// Reparent its children to its parent
|
||||
for (SceneGraphNode* c : node->children())
|
||||
c->setParent(node->parent());
|
||||
|
||||
// Reset the dependencies accordingly
|
||||
// VERY untested ---abock
|
||||
for (SceneGraphNodeInternal* c : internalNode->incomingEdges) {
|
||||
parentInternalNode->outgoingEdges.insert(parentInternalNode->outgoingEdges.end(), c->outgoingEdges.begin(), c->outgoingEdges.end());
|
||||
parentInternalNode->incomingEdges.insert(parentInternalNode->incomingEdges.end(), c->incomingEdges.begin(), c->incomingEdges.end());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SceneGraph::SceneGraphNodeInternal* SceneGraph::nodeByName(const std::string& name) {
|
||||
auto it = std::find_if(
|
||||
_nodes.begin(),
|
||||
_nodes.end(),
|
||||
[name](SceneGraphNodeInternal* node) {
|
||||
return node->node->name() == name;
|
||||
}
|
||||
);
|
||||
|
||||
if (it == _nodes.end())
|
||||
return nullptr;
|
||||
else
|
||||
return *it;
|
||||
}
|
||||
|
||||
const std::vector<SceneGraphNode*>& SceneGraph::nodes() const {
|
||||
return _topologicalSortedNodes;
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraph::rootNode() const {
|
||||
return _rootNode;
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
|
||||
auto it = std::find_if(
|
||||
_nodes.begin(),
|
||||
_nodes.end(),
|
||||
[name](SceneGraphNodeInternal* node) {
|
||||
return node->node->name() == name;
|
||||
}
|
||||
);
|
||||
if (it != _nodes.end())
|
||||
return (*it)->node;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
@@ -66,14 +66,14 @@ const std::string SceneGraphNode::KeyName = "Name";
|
||||
const std::string SceneGraphNode::KeyParentName = "Parent";
|
||||
const std::string SceneGraphNode::KeyDependencies = "Dependencies";
|
||||
|
||||
SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){
|
||||
std::unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
SceneGraphNode::Documentation(),
|
||||
dictionary,
|
||||
"SceneGraphNode"
|
||||
);
|
||||
|
||||
SceneGraphNode* result = new SceneGraphNode;
|
||||
std::unique_ptr<SceneGraphNode> result = std::make_unique<SceneGraphNode>();
|
||||
|
||||
std::string name = dictionary.value<std::string>(KeyName);
|
||||
result->setName(name);
|
||||
@@ -88,7 +88,6 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
|
||||
if (result->_renderable == nullptr) {
|
||||
LERROR("Failed to create renderable for SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
result->addPropertySubOwner(result->_renderable);
|
||||
@@ -103,7 +102,6 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
|
||||
if (result->_transform.translation == nullptr) {
|
||||
LERROR("Failed to create ephemeris for SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
result->addPropertySubOwner(result->_transform.translation.get());
|
||||
@@ -118,7 +116,6 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
|
||||
if (result->_transform.rotation == nullptr) {
|
||||
LERROR("Failed to create rotation for SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
result->addPropertySubOwner(result->_transform.rotation.get());
|
||||
@@ -133,7 +130,6 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
|
||||
if (result->_transform.scale == nullptr) {
|
||||
LERROR("Failed to create scale for SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
delete result;
|
||||
return nullptr;
|
||||
}
|
||||
result->addPropertySubOwner(result->_transform.scale.get());
|
||||
@@ -142,11 +138,12 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
|
||||
|
||||
LDEBUG("Successfully created SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
return result;
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
SceneGraphNode::SceneGraphNode()
|
||||
: _parent(nullptr)
|
||||
, _scene(nullptr)
|
||||
, _transform {
|
||||
std::make_unique<StaticTranslation>(),
|
||||
std::make_unique<StaticRotation>(),
|
||||
@@ -201,6 +198,20 @@ bool SceneGraphNode::deinitialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void SceneGraphNode::traversePreOrder(std::function<void(SceneGraphNode*)> fn) {
|
||||
fn(this);
|
||||
for (auto& child : _children) {
|
||||
child->traversePreOrder(fn);
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::traversePostOrder(std::function<void(SceneGraphNode*)> fn) {
|
||||
for (auto& child : _children) {
|
||||
child->traversePostOrder(fn);
|
||||
}
|
||||
fn(this);
|
||||
}
|
||||
|
||||
void SceneGraphNode::update(const UpdateData& data) {
|
||||
if (_transform.translation) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
@@ -366,26 +377,135 @@ void SceneGraphNode::render(const RenderData& data, RendererTasks& tasks) {
|
||||
// _children.push_back(child);
|
||||
//}
|
||||
|
||||
void SceneGraphNode::setParent(SceneGraphNode* parent) {
|
||||
_parent = parent;
|
||||
void SceneGraphNode::setParent(SceneGraphNode& parent, UpdateScene updateScene) {
|
||||
ghoul_assert(_parent != nullptr, "Node must be attached to a parent");
|
||||
ghoul_assert(
|
||||
!updateScene || _scene == parent._scene,
|
||||
"For the scene to be updated, this object must belong to the same scene as the parent"
|
||||
);
|
||||
ghoul_assert(
|
||||
!updateScene || _parent->_scene == parent._scene,
|
||||
"Old and new parent cannot belong to separate scenes"
|
||||
);
|
||||
|
||||
parent.attachChild(_parent->detachChild(*this, UpdateScene::No), UpdateScene::No);
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::addChild(SceneGraphNode* child) {
|
||||
_children.push_back(child);
|
||||
void SceneGraphNode::attachChild(std::unique_ptr<SceneGraphNode> child, UpdateScene updateScene) {
|
||||
ghoul_assert(child->parent() == nullptr, "Child may not already have a parent");
|
||||
|
||||
child->_parent = this;
|
||||
if (_scene) {
|
||||
child->setScene(_scene);
|
||||
}
|
||||
|
||||
_children.push_back(std::move(child));
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->addNode(child.get());
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<SceneGraphNode> SceneGraphNode::detachChild(SceneGraphNode& child, UpdateScene updateScene) {
|
||||
ghoul_assert(child._dependentNodes.empty(), "Nodes cannot depend on a node being detached");
|
||||
ghoul_assert(child._parent != nullptr, "Node must be attached to a parent");
|
||||
|
||||
// Update of deps is deffered to the removal of the node from the scene
|
||||
clearDependencies(UpdateScene::No);
|
||||
|
||||
auto iter = std::find_if(
|
||||
_children.begin(),
|
||||
_children.end(),
|
||||
[&child] (const auto& c) {
|
||||
return &child == c.get();
|
||||
}
|
||||
);
|
||||
|
||||
std::unique_ptr<SceneGraphNode> c = std::move(*iter);
|
||||
_children.erase(iter);
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->removeNode(&child);
|
||||
}
|
||||
|
||||
if (_scene) {
|
||||
setScene(nullptr);
|
||||
}
|
||||
return std::move(c);
|
||||
}
|
||||
|
||||
void SceneGraphNode::addDependency(SceneGraphNode& dependency, UpdateScene updateScene) {
|
||||
dependency._dependentNodes.push_back(this);
|
||||
_dependencies.push_back(&dependency);
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::removeDependency(SceneGraphNode& dependency, UpdateScene updateScene) {
|
||||
dependency._dependentNodes.erase(std::remove_if(
|
||||
dependency._dependentNodes.begin(),
|
||||
dependency._dependentNodes.end(),
|
||||
[this](const auto& d) {
|
||||
return this == d;
|
||||
}
|
||||
), dependency._dependentNodes.end());
|
||||
_dependencies.erase(std::remove_if(
|
||||
_dependencies.begin(),
|
||||
_dependencies.end(),
|
||||
[&dependency](const auto& d) {
|
||||
return &dependency == d;
|
||||
}
|
||||
), _dependencies.end());
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::clearDependencies(UpdateScene updateScene) {
|
||||
for (auto& dependency : _dependencies) {
|
||||
dependency->_dependentNodes.erase(std::remove_if(
|
||||
dependency->_dependentNodes.begin(),
|
||||
dependency->_dependentNodes.end(),
|
||||
[this](const auto& d) {
|
||||
return this == d;
|
||||
}
|
||||
), dependency->_dependentNodes.end());
|
||||
}
|
||||
_dependencies.clear();
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
void SceneGraphNode::setDependencies(const std::vector<SceneGraphNode*>& dependencies, UpdateScene updateScene) {
|
||||
clearDependencies(UpdateScene::No);
|
||||
|
||||
_dependencies = dependencies;
|
||||
for (auto& dependency : dependencies) {
|
||||
dependency->_dependentNodes.push_back(this);
|
||||
}
|
||||
|
||||
if (_scene && updateScene) {
|
||||
_scene->updateDependencies();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//not used anymore @AA
|
||||
//bool SceneGraphNode::abandonChild(SceneGraphNode* child) {
|
||||
// std::vector < SceneGraphNode* >::iterator it = std::find(_children.begin(), _children.end(), child);
|
||||
//
|
||||
// if (it != _children.end()){
|
||||
// _children.erase(it);
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
//}
|
||||
const std::vector<SceneGraphNode*>& SceneGraphNode::dependencies() const {
|
||||
return _dependencies;
|
||||
}
|
||||
|
||||
const std::vector<SceneGraphNode*>& SceneGraphNode::dependentNodes() const {
|
||||
return _dependentNodes;
|
||||
}
|
||||
|
||||
glm::dvec3 SceneGraphNode::position() const
|
||||
{
|
||||
@@ -451,15 +571,28 @@ double SceneGraphNode::calculateWorldScale() const {
|
||||
}
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneGraphNode::parent() const
|
||||
{
|
||||
SceneGraphNode* SceneGraphNode::parent() const {
|
||||
return _parent;
|
||||
}
|
||||
const std::vector<SceneGraphNode*>& SceneGraphNode::children() const{
|
||||
return _children;
|
||||
|
||||
Scene* SceneGraphNode::scene() {
|
||||
return _scene;
|
||||
}
|
||||
|
||||
void SceneGraphNode::setScene(Scene* scene) {
|
||||
traversePreOrder([scene](SceneGraphNode* node) {
|
||||
node->_scene = scene;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> SceneGraphNode::children() const {
|
||||
std::vector<SceneGraphNode*> nodes;
|
||||
for (auto& child : _children) {
|
||||
nodes.push_back(child.get());
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
// bounding sphere
|
||||
PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){
|
||||
// set the bounding sphere to 0.0
|
||||
_boundingSphere = 0.0;
|
||||
@@ -490,7 +623,6 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){
|
||||
if(renderableBS > _boundingSphere)
|
||||
_boundingSphere = renderableBS;
|
||||
}
|
||||
//LINFO("Bounding Sphere of '" << name() << "': " << _boundingSphere);
|
||||
|
||||
return _boundingSphere;
|
||||
}
|
||||
@@ -499,13 +631,11 @@ PowerScaledScalar SceneGraphNode::boundingSphere() const{
|
||||
return _boundingSphere;
|
||||
}
|
||||
|
||||
// renderable
|
||||
void SceneGraphNode::setRenderable(Renderable* renderable) {
|
||||
_renderable = renderable;
|
||||
}
|
||||
|
||||
const Renderable* SceneGraphNode::renderable() const
|
||||
{
|
||||
const Renderable* SceneGraphNode::renderable() const {
|
||||
return _renderable;
|
||||
}
|
||||
|
||||
@@ -513,7 +643,7 @@ Renderable* SceneGraphNode::renderable() {
|
||||
return _renderable;
|
||||
}
|
||||
|
||||
// private helper methods
|
||||
/*
|
||||
bool SceneGraphNode::sphereInsideFrustum(const psc& s_pos, const PowerScaledScalar& s_rad,
|
||||
const Camera* camera)
|
||||
{
|
||||
@@ -544,15 +674,16 @@ bool SceneGraphNode::sphereInsideFrustum(const psc& s_pos, const PowerScaledScal
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
SceneGraphNode* SceneGraphNode::childNode(const std::string& name)
|
||||
{
|
||||
if (this->name() == name)
|
||||
return this;
|
||||
else
|
||||
for (SceneGraphNode* it : _children) {
|
||||
for (auto& it : _children) {
|
||||
SceneGraphNode* tmp = it->childNode(name);
|
||||
if (tmp != nullptr)
|
||||
if (tmp)
|
||||
return tmp;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
391
src/scene/sceneloader.cpp
Normal file
391
src/scene/sceneloader.cpp
Normal file
@@ -0,0 +1,391 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/filesystem/file.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/onscopeexit.h>
|
||||
|
||||
#include <unordered_set>
|
||||
#include <memory>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "SceneLoader";
|
||||
const std::string KeyPathScene = "ScenePath";
|
||||
const std::string KeyModules = "Modules";
|
||||
const std::string ModuleExtension = ".mod";
|
||||
const std::string KeyPathModule = "ModulePath";
|
||||
|
||||
const std::string RootNodeName = "Root";
|
||||
const std::string KeyName = "Name";
|
||||
const std::string KeyParentName = "Parent";
|
||||
const std::string KeyDependencies = "Dependencies";
|
||||
const std::string KeyCamera = "Camera";
|
||||
const std::string KeyCameraFocus = "Focus";
|
||||
const std::string KeyCameraPosition = "Position";
|
||||
const std::string KeyCameraRotation = "Rotation";
|
||||
}
|
||||
|
||||
struct ModuleInformation {
|
||||
ghoul::Dictionary dictionary;
|
||||
std::string moduleFile;
|
||||
std::string modulePath;
|
||||
std::string moduleName;
|
||||
};
|
||||
|
||||
namespace openspace {
|
||||
|
||||
std::unique_ptr<Scene> SceneLoader::loadScene(const std::string& path) {
|
||||
// Set up lua state.
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
// Delete the Lua state at the end of the scope, no matter what.
|
||||
[state]() {ghoul::lua::destroyLuaState(state); }
|
||||
);
|
||||
OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
std::string absScenePath = absPath(path);
|
||||
ghoul::filesystem::File sceneFile(absScenePath);
|
||||
std::string sceneDirectory = sceneFile.directoryName();
|
||||
|
||||
ghoul::Dictionary sceneDictionary;
|
||||
if (!FileSys.fileExists(absScenePath)) {
|
||||
throw ghoul::FileNotFoundError(absScenePath);
|
||||
}
|
||||
ghoul::lua::loadDictionaryFromFile(absScenePath, sceneDictionary, state);
|
||||
|
||||
documentation::testSpecificationAndThrow(Scene::Documentation(), sceneDictionary, "Scene");
|
||||
|
||||
std::string relativeSceneDirectory = ".";
|
||||
sceneDictionary.getValue<std::string>(KeyPathScene, relativeSceneDirectory);
|
||||
std::string modulesPath = FileSys.absPath(sceneDirectory + FileSys.PathSeparator + relativeSceneDirectory);
|
||||
|
||||
ghoul::Dictionary moduleDictionary;
|
||||
sceneDictionary.getValue(KeyModules, moduleDictionary);
|
||||
|
||||
// Above we generated a ghoul::Dictionary from the scene file; now we run the scene
|
||||
// file again to load any variables defined inside into the state that is passed to
|
||||
// the modules. This allows us to specify global variables that can then be used
|
||||
// inside the modules to toggle settings.
|
||||
ghoul::lua::runScriptFile(state, absScenePath);
|
||||
std::vector<std::string> keys = moduleDictionary.keys();
|
||||
ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> allNodes;
|
||||
|
||||
for (const std::string& key : keys) {
|
||||
std::string fullModuleName = moduleDictionary.value<std::string>(key);
|
||||
std::replace(fullModuleName.begin(), fullModuleName.end(), '/', FileSys.PathSeparator);
|
||||
std::string modulePath = FileSys.pathByAppendingComponent(modulesPath, fullModuleName);
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> nodes = loadDirectory(modulePath, state);
|
||||
std::move(nodes.begin(), nodes.end(), std::back_inserter(allNodes));
|
||||
}
|
||||
|
||||
FileSys.setCurrentDirectory(oldDirectory);
|
||||
|
||||
std::unique_ptr<Scene> scene = std::make_unique<Scene>();
|
||||
|
||||
std::unique_ptr<SceneGraphNode> rootNode = std::make_unique<SceneGraphNode>();
|
||||
rootNode->setName(SceneGraphNode::RootNodeName);
|
||||
scene->setRoot(std::move(rootNode));
|
||||
|
||||
addLoadedNodes(*scene, std::move(allNodes));
|
||||
|
||||
ghoul::Dictionary cameraDictionary;
|
||||
sceneDictionary.getValue(KeyCamera, cameraDictionary);
|
||||
LoadedCamera loadedCamera = loadCamera(cameraDictionary);
|
||||
|
||||
auto& nodeMap = scene->nodesByName();
|
||||
auto it = nodeMap.find(loadedCamera.parent);
|
||||
if (it != nodeMap.end()) {
|
||||
loadedCamera.camera->setParent(it->second);
|
||||
}
|
||||
|
||||
scene->setCamera(std::move(loadedCamera.camera));
|
||||
|
||||
return std::move(scene);
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> SceneLoader::importDirectory(Scene& scene, const std::string& path) {
|
||||
lua_State* state = ghoul::lua::createNewLuaState();
|
||||
OnExit(
|
||||
// Delete the Lua state at the end of the scope, no matter what.
|
||||
[state]() {ghoul::lua::destroyLuaState(state); }
|
||||
);
|
||||
OsEng.scriptEngine().initializeLuaState(state);
|
||||
|
||||
std::string absDirectoryPath = absPath(path);
|
||||
|
||||
ghoul::filesystem::Directory oldDirectory = FileSys.currentDirectory();
|
||||
std::vector<SceneLoader::LoadedNode> nodes = loadDirectory(path, state);
|
||||
FileSys.setCurrentDirectory(oldDirectory);
|
||||
return addLoadedNodes(scene, std::move(nodes));
|
||||
}
|
||||
|
||||
SceneGraphNode* SceneLoader::importNodeDictionary(Scene& scene, const ghoul::Dictionary& dict) {
|
||||
std::vector<SceneLoader::LoadedNode> loadedNodes;
|
||||
loadedNodes.push_back(loadNode(dict));
|
||||
std::vector<SceneGraphNode*> nodes = addLoadedNodes(scene, std::move(loadedNodes));
|
||||
if (nodes.size() == 1) {
|
||||
return nodes[0];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SceneLoader::LoadedCamera SceneLoader::loadCamera(const ghoul::Dictionary& cameraDict) {
|
||||
std::string focus;
|
||||
glm::vec3 cameraPosition;
|
||||
glm::vec4 cameraRotation;
|
||||
|
||||
bool readSuccessful = true;
|
||||
readSuccessful &= cameraDict.getValue(KeyCameraFocus, focus);
|
||||
readSuccessful &= cameraDict.getValue(KeyCameraPosition, cameraPosition);
|
||||
readSuccessful &= cameraDict.getValue(KeyCameraRotation, cameraRotation);
|
||||
|
||||
std::unique_ptr<Camera> camera = std::make_unique<Camera>();
|
||||
|
||||
camera->setPositionVec3(cameraPosition);
|
||||
camera->setRotation(glm::dquat(
|
||||
cameraRotation.x, cameraRotation.y, cameraRotation.z, cameraRotation.w));
|
||||
|
||||
LoadedCamera loadedCamera(focus, std::move(camera));
|
||||
|
||||
if (!readSuccessful) {
|
||||
throw Scene::InvalidSceneError(
|
||||
"Position, Rotation and Focus need to be defined for camera dictionary.");
|
||||
}
|
||||
|
||||
return loadedCamera;
|
||||
}
|
||||
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> SceneLoader::loadDirectory(
|
||||
const std::string& path,
|
||||
lua_State* luaState)
|
||||
{
|
||||
std::string::size_type pos = path.find_last_of(FileSys.PathSeparator);
|
||||
if (pos == std::string::npos) {
|
||||
LERROR("Error parsing directory name '" << path << "'");
|
||||
return std::vector<SceneLoader::LoadedNode>();
|
||||
}
|
||||
std::string moduleName = path.substr(pos + 1);
|
||||
std::string moduleFile = FileSys.pathByAppendingComponent(path, moduleName) + ModuleExtension;
|
||||
|
||||
if (FileSys.fileExists(moduleFile)) {
|
||||
// TODO: Get rid of changing the working directory (global state is bad) -- emiax
|
||||
// This requires refactoring all renderables to not use relative paths in constructors.
|
||||
FileSys.setCurrentDirectory(ghoul::filesystem::Directory(path));
|
||||
|
||||
// We have a module file, so it is a direct include.
|
||||
return loadModule(moduleFile, luaState);
|
||||
} else {
|
||||
std::vector<SceneLoader::LoadedNode> allLoadedNodes;
|
||||
// If we do not have a module file, we have to include all subdirectories.
|
||||
using ghoul::filesystem::Directory;
|
||||
using std::string;
|
||||
std::vector<string> directories = Directory(path).readDirectories();
|
||||
|
||||
for (const string& s : directories) {
|
||||
//std::string submodulePath = FileSys.pathByAppendingComponent(path, s);
|
||||
std::vector<SceneLoader::LoadedNode> loadedNodes = loadDirectory(s, luaState);
|
||||
std::move(loadedNodes.begin(), loadedNodes.end(), std::back_inserter(allLoadedNodes));
|
||||
}
|
||||
return allLoadedNodes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SceneLoader::LoadedNode SceneLoader::loadNode(const ghoul::Dictionary& dictionary) {
|
||||
std::vector<std::string> dependencies;
|
||||
|
||||
std::string nodeName = dictionary.value<std::string>(KeyName);
|
||||
std::string parentName = dictionary.value<std::string>(KeyParentName);
|
||||
std::unique_ptr<SceneGraphNode> node = SceneGraphNode::createFromDictionary(dictionary);
|
||||
|
||||
if (dictionary.hasKey(SceneGraphNode::KeyDependencies)) {
|
||||
if (!dictionary.hasValue<ghoul::Dictionary>(SceneGraphNode::KeyDependencies)) {
|
||||
LERROR("Dependencies did not have the corrent type");
|
||||
}
|
||||
ghoul::Dictionary nodeDependencies;
|
||||
dictionary.getValue(SceneGraphNode::KeyDependencies, nodeDependencies);
|
||||
|
||||
std::vector<std::string> keys = nodeDependencies.keys();
|
||||
for (const std::string& key : keys) {
|
||||
std::string value = nodeDependencies.value<std::string>(key);
|
||||
dependencies.push_back(value);
|
||||
}
|
||||
}
|
||||
return SceneLoader::LoadedNode(nodeName, parentName, dependencies, std::move(node));
|
||||
}
|
||||
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> SceneLoader::loadModule(const std::string& path, lua_State* luaState) {
|
||||
ghoul::Dictionary moduleDictionary;
|
||||
try {
|
||||
ghoul::lua::loadDictionaryFromFile(path, moduleDictionary, luaState);
|
||||
} catch (const ghoul::lua::LuaRuntimeException& e) {
|
||||
LERRORC(e.component, e.message);
|
||||
return std::vector<SceneLoader::LoadedNode>();
|
||||
}
|
||||
|
||||
std::vector<SceneLoader::LoadedNode> loadedNodes;
|
||||
std::vector<std::string> keys = moduleDictionary.keys();
|
||||
for (const std::string& key : keys) {
|
||||
ghoul::Dictionary nodeDictionary;
|
||||
if (!moduleDictionary.getValue(key, nodeDictionary)) {
|
||||
LERROR("Node dictionary did not have the corrent type");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
loadedNodes.push_back(loadNode(nodeDictionary));
|
||||
} catch (ghoul::RuntimeError& e) {
|
||||
LERROR("Failed loading node from " << path << ": " << e.message << ", " << e.component);
|
||||
}
|
||||
}
|
||||
return loadedNodes;
|
||||
};
|
||||
|
||||
std::vector<SceneGraphNode*> SceneLoader::addLoadedNodes(Scene& scene, std::vector<SceneLoader::LoadedNode> loadedNodes) {
|
||||
std::map<std::string, SceneGraphNode*> existingNodes = scene.nodesByName();
|
||||
std::map<std::string, SceneGraphNode*> addedNodes;
|
||||
|
||||
// Populate map of nodes to be added.
|
||||
// Also track new branches of nodes that are attached
|
||||
// to allow for recovery in case an invalid scene is generated.
|
||||
for (auto& loadedNode : loadedNodes) {
|
||||
std::string name = loadedNode.name;
|
||||
if (existingNodes.count(name) > 0) {
|
||||
LERROR("Node with name '" + name + "' already exists in scene");
|
||||
continue;
|
||||
}
|
||||
if (addedNodes.count(name) > 0) {
|
||||
LERROR("Duplicate node names '" + name + "' among loaded nodes");
|
||||
}
|
||||
|
||||
SceneGraphNode* node = loadedNode.node.get();
|
||||
addedNodes[name] = node;
|
||||
}
|
||||
|
||||
// Find a node by name among the exising nodes and the added nodes.
|
||||
auto findNode = [&existingNodes, &addedNodes](const std::string name) {
|
||||
std::map<std::string, SceneGraphNode*>::iterator it;
|
||||
if ((it = existingNodes.find(name)) != existingNodes.end()) {
|
||||
return it->second;
|
||||
}
|
||||
if ((it = addedNodes.find(name)) != addedNodes.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return static_cast<SceneGraphNode*>(nullptr);
|
||||
};
|
||||
|
||||
|
||||
std::vector<SceneGraphNode*> attachedBranches;
|
||||
std::vector<std::unique_ptr<SceneGraphNode>> badNodes;
|
||||
|
||||
// Attach each node to its parent and set up dependencies.
|
||||
for (auto& loadedNode : loadedNodes) {
|
||||
std::string parentName = loadedNode.parent;
|
||||
std::vector<std::string> dependencyNames = loadedNode.dependencies;
|
||||
|
||||
SceneGraphNode* parent = findNode(parentName);
|
||||
if (!parent) {
|
||||
LERROR("Could not find parent '" + parentName + "' for '" + loadedNode.name + "'");
|
||||
badNodes.push_back(std::move(loadedNode.node));
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<SceneGraphNode*> dependencies;
|
||||
bool foundAllDeps = true;
|
||||
for (const auto& depName : dependencyNames) {
|
||||
SceneGraphNode* dep = findNode(depName);
|
||||
if (!dep) {
|
||||
LERROR("Could not find dependency '" + depName + "' for '" + loadedNode.name + "'");
|
||||
foundAllDeps = false;
|
||||
continue;
|
||||
}
|
||||
dependencies.push_back(dep);
|
||||
}
|
||||
|
||||
if (!foundAllDeps) {
|
||||
badNodes.push_back(std::move(loadedNode.node));
|
||||
continue;
|
||||
}
|
||||
|
||||
SceneGraphNode* child = loadedNode.node.get();
|
||||
parent->attachChild(std::move(loadedNode.node), SceneGraphNode::UpdateScene::No);
|
||||
child->setDependencies(dependencies, SceneGraphNode::UpdateScene::No);
|
||||
|
||||
if (existingNodes.find(parentName) != existingNodes.end()) {
|
||||
attachedBranches.push_back(child);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the nodes to the scene.
|
||||
for (auto& node : attachedBranches) {
|
||||
scene.addNode(node, Scene::UpdateDependencies::No);
|
||||
}
|
||||
|
||||
// Remove all bad nodes (parent or deps missing) and all their children and dependent nodes.
|
||||
// Use unsorted set `visited` to avoid infinite loop in case of circular deps.
|
||||
std::unordered_set<SceneGraphNode*> visited;
|
||||
for (size_t i = 0; i < badNodes.size(); i++) {
|
||||
auto& badNode = badNodes[i];
|
||||
for (auto c : badNode->children()) {
|
||||
visited.insert(c);
|
||||
badNodes.push_back(std::move(badNode->detachChild(*c, SceneGraphNode::UpdateScene::No)));
|
||||
}
|
||||
for (auto& d : badNode->dependentNodes()) {
|
||||
SceneGraphNode* parent = d->parent();
|
||||
if (visited.count(d) == 0) {
|
||||
visited.insert(d);
|
||||
if (parent) {
|
||||
badNodes.push_back(std::move(parent->detachChild(*d, SceneGraphNode::UpdateScene::No)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Warn for nodes that lack connection to the root.
|
||||
for (auto& node : addedNodes) {
|
||||
if (!node.second->scene()) {
|
||||
LWARNING("Node '" << node.first << "' is not connected to the root and will not be added to the scene");
|
||||
}
|
||||
}
|
||||
// Update dependencies: sort nodes topologically.
|
||||
scene.updateDependencies();
|
||||
|
||||
// Return a vector of all added nodes.
|
||||
std::vector<SceneGraphNode*> addedNodesVector;
|
||||
for (auto& it : addedNodes) {
|
||||
addedNodesVector.push_back(it.second);
|
||||
}
|
||||
return addedNodesVector;
|
||||
}
|
||||
}
|
||||
48
src/scene/scenemanager.cpp
Normal file
48
src/scene/scenemanager.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <openspace/scene/scenemanager.h>
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <openspace/scene/scene.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
Scene* SceneManager::loadScene(const std::string& path) {
|
||||
SceneLoader loader;
|
||||
std::unique_ptr<Scene> scene = loader.loadScene(path);
|
||||
Scene* s = scene.get();
|
||||
if (s) {
|
||||
_scenes.push_back(std::move(scene));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void SceneManager::unloadScene(Scene& scene) {
|
||||
std::remove_if(_scenes.begin(), _scenes.end(), [&scene] (auto& s) {
|
||||
return s.get() == &scene;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,10 @@ namespace openspace {
|
||||
_cachedSinMaxFov.isDirty = true;
|
||||
}
|
||||
|
||||
void Camera::setParent(SceneGraphNode* parent) {
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
// Relative mutators
|
||||
void Camera::rotate(Quat rotation) {
|
||||
std::lock_guard<std::mutex> _lock(_mutex);
|
||||
@@ -167,6 +171,10 @@ namespace openspace {
|
||||
return _cachedSinMaxFov.datum;
|
||||
}
|
||||
|
||||
SceneGraphNode * Camera::parent() const {
|
||||
return _parent;
|
||||
}
|
||||
|
||||
const Camera::Mat4& Camera::viewRotationMatrix() const {
|
||||
if (_cachedViewRotationMatrix.isDirty) {
|
||||
_cachedViewRotationMatrix.datum = glm::mat4_cast(glm::inverse((glm::dquat)_rotation));
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
return {
|
||||
{
|
||||
Name = "ChildAndDependent",
|
||||
Parent = "NoDependency",
|
||||
Dependencies = {
|
||||
"Dependent"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
return {
|
||||
{
|
||||
Name = "DirectDependency",
|
||||
Name = "Child",
|
||||
Parent = "NoDependency"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
return {
|
||||
{
|
||||
Name = "CircularDependency1",
|
||||
Parent = "CircularDependency2"
|
||||
Parent = "Root",
|
||||
Dependencies = {"CircularDependency2"}
|
||||
},
|
||||
{
|
||||
Name = "CircularDependency2",
|
||||
7
tests/SceneLoaderTest/dependent/dependent.mod
Normal file
7
tests/SceneLoaderTest/dependent/dependent.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
return {
|
||||
{
|
||||
Name = "Dependent",
|
||||
Parent = "Root",
|
||||
Dependencies = {"NoDependency"}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
-- Malformed script
|
||||
return {
|
||||
ScenePath = ".",
|
||||
ScenePath = 1337,
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
-- Malformed script
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = 2,
|
||||
Modules = {
|
||||
}
|
||||
Modules = 2
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
return {
|
||||
{
|
||||
Name = "DirectDependency",
|
||||
Name = "Child",
|
||||
Parent = "NoDependency"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
-- Loading an empty common and module dictionary in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
12
tests/SceneLoaderTest/test00.scene
Normal file
12
tests/SceneLoaderTest/test00.scene
Normal file
@@ -0,0 +1,12 @@
|
||||
-- Loading an empty common and module dictionary
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
-- Loading a module without dependencies in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "common",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"no-dependency"
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
-- Loading a module without dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "common",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"no-dependency"
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
-- Loading a module with a direct dependency in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "common",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"no-dependency",
|
||||
"direct-dependency"
|
||||
"child"
|
||||
}
|
||||
}
|
||||
|
||||
14
tests/SceneLoaderTest/test02.scene
Normal file
14
tests/SceneLoaderTest/test02.scene
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Loading a module with a direct dependency
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"no-dependency",
|
||||
"child"
|
||||
}
|
||||
}
|
||||
|
||||
14
tests/SceneLoaderTest/test03.scene
Normal file
14
tests/SceneLoaderTest/test03.scene
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Multiple Dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"no-dependency",
|
||||
"dependent"
|
||||
}
|
||||
}
|
||||
|
||||
16
tests/SceneLoaderTest/test04.scene
Normal file
16
tests/SceneLoaderTest/test04.scene
Normal file
@@ -0,0 +1,16 @@
|
||||
-- Multiple Dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"child",
|
||||
"child-and-dependent",
|
||||
"no-dependency",
|
||||
"dependent"
|
||||
}
|
||||
}
|
||||
|
||||
13
tests/SceneLoaderTest/test05.scene
Normal file
13
tests/SceneLoaderTest/test05.scene
Normal file
@@ -0,0 +1,13 @@
|
||||
-- Circular Dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Camera = {
|
||||
Position = {0.0, 0.0, 0.0},
|
||||
Rotation = {0.0, 0.0, 0.0, 0.0},
|
||||
Focus = "Root"
|
||||
},
|
||||
Modules = {
|
||||
"circular-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "CommonDependency",
|
||||
Parent = "Common"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "Common",
|
||||
Parent = "Root",
|
||||
},
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Malformed script
|
||||
return {
|
||||
ScenePath = "foobar",
|
||||
CommonFolder = "",
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Malformed script
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "nonexisting",
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "MultipleDependencies",
|
||||
Parent = "NoDependency",
|
||||
Dependency = {
|
||||
"DirectDependency"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "CommonDependency",
|
||||
Parent = "Common"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "Common",
|
||||
Parent = "Root",
|
||||
},
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
return {
|
||||
{
|
||||
Name = "MultipleDependencies",
|
||||
Parent = "NoDependency",
|
||||
Dependency = {
|
||||
"DirectDependency"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Loading an empty common and module dictionary
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "",
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Loading an empty module dictionary in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
-- Loading an empty module dictionary
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
-- Loading a module with a dependency on the common module in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
"common-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
-- Loading a module with a dependency on the common module
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
"common-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
-- Loading a module with a direct dependency
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
"no-dependency",
|
||||
"direct-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
-- Multiple Dependencies in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
"multiple-dependencies",
|
||||
"no-dependency",
|
||||
"direct-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
-- Multiple Dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
CommonFolder = "common",
|
||||
Modules = {
|
||||
"multiple-dependencies",
|
||||
"no-dependency",
|
||||
"direct-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
-- Circular Dependencies in a different folder
|
||||
return {
|
||||
ScenePath = "scene-folder",
|
||||
Modules = {
|
||||
"common",
|
||||
"circular-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
-- Circular Dependencies
|
||||
return {
|
||||
ScenePath = ".",
|
||||
Modules = {
|
||||
"common",
|
||||
"circular-dependency"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
// test files
|
||||
#include <test_common.inl>
|
||||
#include <test_spicemanager.inl>
|
||||
#include <test_scenegraphloader.inl>
|
||||
#include <test_sceneloader.inl>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
//#include <test_chunknode.inl>
|
||||
|
||||
@@ -1,381 +0,0 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
class SceneGraphLoaderTest : public testing::Test {};
|
||||
|
||||
//TEST_F(SceneGraphLoaderTest, NonExistingFileTest) {
|
||||
// const std::string file = "NonExistingFile";
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, IllformedFileTest) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/illformed.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, IllformedFileTestWrongCommonFolderType) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/illformedWrongType.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, IllformedFileTestInvalidSceneFolder) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/illformedInvalidScene.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, IllformedFileTestWrongCommonFolder) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/illformedWrongCommon.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, IllformedFileTestNonExistingCommonFolder) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/illformedNonExistingCommon.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// EXPECT_FALSE(success) << "Unsuccessful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "Empty scenegraph nodes list";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test00) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test00.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "No scenegraph nodes loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test00Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test00-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "No scenegraph nodes loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, AbsoluteScenePath) {
|
||||
// const std::string scenePath = absPath("${TEMPORARY}/tmp.scene");
|
||||
// std::ofstream scene(scenePath.c_str());
|
||||
//
|
||||
// scene << "return {" << std::endl <<
|
||||
// " ScenePath = \"" << absPath("${TESTDIR}/SceneGraphLoaderTest/scene-folder") <<
|
||||
// "\"," << std::endl <<
|
||||
// " CommonFolder = \"\"," << std::endl <<
|
||||
// " Modules = {}}" << std::endl;
|
||||
// scene.close();
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(scenePath, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// EXPECT_TRUE(nodes.empty()) << "No scenegraph nodes loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test01) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test01.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 1) << "Correct number of nodes";
|
||||
// EXPECT_TRUE(nodes[0]->name() == "Common") << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test01Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test01-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 1) << "Correct number of nodes";
|
||||
// EXPECT_TRUE(nodes[0]->name() == "Common") << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test02) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test02.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 2) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "NoDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test02Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test02-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 2) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "NoDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test03) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test03.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 2) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "CommonDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test03Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test03-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 2) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "CommonDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test04) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test04.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 3) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "DirectDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test04Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test04-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 3) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "DirectDependency")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test05) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test05.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 4) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "MultipleDependencies")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test05Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test05-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 4) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "MultipleDependencies")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "Correct node loaded";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test06) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test06.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_FALSE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.empty()) << "Correct number of nodes";
|
||||
//}
|
||||
//
|
||||
//TEST_F(SceneGraphLoaderTest, Test06Location) {
|
||||
// const std::string file = absPath("${TESTDIR}/SceneGraphLoaderTest/test06-location.scene");
|
||||
//
|
||||
// std::vector<openspace::SceneGraphNode*> nodes;
|
||||
// bool success = openspace::SceneGraphLoader::load(file, nodes);
|
||||
//
|
||||
// ASSERT_TRUE(success) << "Successful loading";
|
||||
// ASSERT_TRUE(nodes.size() == 4) << "Correct number of nodes";
|
||||
// bool found = false;
|
||||
// for (openspace::SceneGraphNode* n : nodes)
|
||||
// if (n->name() == "MultipleDependencies")
|
||||
// found = true;
|
||||
//
|
||||
// EXPECT_TRUE(found) << "No scenegraph nodes loaded";
|
||||
//}
|
||||
//
|
||||
////
|
||||
////
|
||||
////
|
||||
////TEST_F(SceneGraphTest, SceneGraphNode) {
|
||||
////
|
||||
//// openspace::SceneGraphNode *node =
|
||||
//// openspace::SceneGraphNode::createFromDictionary(ghoul::Dictionary());
|
||||
////
|
||||
//// // Should not have a renderable and position should be 0,0,0,0 (undefined).
|
||||
//// EXPECT_EQ(nullptr, node->renderable());
|
||||
//// EXPECT_EQ(openspace::psc(), node->position());
|
||||
////
|
||||
//// delete node;
|
||||
//// ghoul::Dictionary nodeDictionary;
|
||||
////
|
||||
//// ghoul::Dictionary positionDictionary;
|
||||
//// ghoul::Dictionary positionPositionArrayDictionary;
|
||||
////
|
||||
//// ghoul::Dictionary renderableDictionary;
|
||||
////
|
||||
//// renderableDictionary.setValue("Type", std::string("RenderablePlanet"));
|
||||
////
|
||||
//// positionPositionArrayDictionary.setValue("1", 1.0);
|
||||
//// positionPositionArrayDictionary.setValue("2", 1.0);
|
||||
//// positionPositionArrayDictionary.setValue("3", 1.0);
|
||||
//// positionPositionArrayDictionary.setValue("4", 1.0);
|
||||
////
|
||||
//// positionDictionary.setValue("Type", std::string("Static"));
|
||||
//// positionDictionary.setValue("Position", positionPositionArrayDictionary);
|
||||
////
|
||||
//// nodeDictionary.setValue("Position", positionDictionary);
|
||||
//// nodeDictionary.setValue("Renderable", renderableDictionary);
|
||||
////
|
||||
//// node =
|
||||
//// openspace::SceneGraphNode::createFromDictionary(nodeDictionary);
|
||||
////
|
||||
//// // This node should have a renderable (probably no good values but an existing one)
|
||||
//// EXPECT_TRUE(node->renderable());
|
||||
////
|
||||
//// // position should be initialized
|
||||
//// EXPECT_EQ(openspace::psc(1.0,1.0,1.0,1.0), node->position());
|
||||
////
|
||||
//// delete node;
|
||||
////}
|
||||
////
|
||||
////TEST_F(SceneGraphTest, Loading) {
|
||||
////
|
||||
////
|
||||
//// // Should not successfully load a non existing scenegraph
|
||||
//// EXPECT_FALSE(_scenegraph->loadScene(absPath("${TESTDIR}/ScenegraphTestNonExisting"), absPath("${TESTDIR}")));
|
||||
////
|
||||
//// // Existing scenegraph should load
|
||||
//// EXPECT_TRUE(_scenegraph->loadScene(absPath("${TESTDIR}/ScenegraphTest"), absPath("${TESTDIR}")));
|
||||
//// // TODO need to check for correctness
|
||||
////
|
||||
//// // This loading should fail regardless of existing or not since the
|
||||
//// // scenegraph is already loaded
|
||||
//// EXPECT_FALSE(_scenegraph->loadScene(absPath("${TESTDIR}/ScenegraphTest"), absPath("${TESTDIR}")));
|
||||
////}
|
||||
////
|
||||
////TEST_F(SceneGraphTest, Reinitializing) {
|
||||
////
|
||||
//// // Existing scenegraph should load
|
||||
//// EXPECT_TRUE(_scenegraph->loadScene(absPath("${TESTDIR}/ScenegraphTest"), absPath("${TESTDIR}")));
|
||||
////
|
||||
//// _scenegraph->deinitialize();
|
||||
////
|
||||
//// // Existing scenegraph should load
|
||||
//// EXPECT_TRUE(_scenegraph->loadScene(absPath("${TESTDIR}/ScenegraphTest"), absPath("${TESTDIR}")));
|
||||
//// // TODO need to check for correctness
|
||||
////}
|
||||
//
|
||||
|
||||
|
||||
|
||||
265
tests/test_sceneloader.inl
Normal file
265
tests/test_sceneloader.inl
Normal file
@@ -0,0 +1,265 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <openspace/scene/sceneloader.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <ghoul/misc/dictionaryluaformatter.h>
|
||||
|
||||
#include <ghoul/lua/lua_helper.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
//class SceneLoaderTest : public testing::Test {};
|
||||
|
||||
TEST(SceneLoaderTest, NonExistingFileTest) {
|
||||
const std::string file = absPath("NonExistingFile");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
EXPECT_THROW(loader.loadScene(file), ghoul::FileNotFoundError);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, IllformedFileTest) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/illformed.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
EXPECT_THROW(loader.loadScene(file), ghoul::lua::LuaRuntimeException);
|
||||
}
|
||||
|
||||
|
||||
TEST(SceneLoaderTest, IllformedFileTestInvalidSceneFolder) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/illformedInvalidScene.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
EXPECT_THROW(loader.loadScene(file), openspace::documentation::SpecificationError);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, IllformedFileTestWrongType) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/illformedWrongType.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
EXPECT_THROW(loader.loadScene(file), openspace::documentation::SpecificationError);
|
||||
}
|
||||
|
||||
|
||||
TEST(SceneLoaderTest, AbsoluteScenePath) {
|
||||
const std::string scenePath = absPath("${TEMPORARY}/tmp.scene");
|
||||
std::ofstream sceneFile(scenePath.c_str());
|
||||
|
||||
ghoul::DictionaryLuaFormatter formatter;
|
||||
ghoul::Dictionary sceneFileDictionary;
|
||||
ghoul::Dictionary cameraDictionary;
|
||||
|
||||
cameraDictionary.setValue<glm::vec3>("Position", glm::vec3(0.0));
|
||||
cameraDictionary.setValue<glm::vec4>("Rotation", glm::vec4(0.0));
|
||||
cameraDictionary.setValue<std::string>("Focus", "Root");
|
||||
|
||||
sceneFileDictionary.setValue<std::string>("ScenePath", absPath("${TESTDIR}/SceneLoaderTest/scene-folder"));
|
||||
sceneFileDictionary.setValue<ghoul::Dictionary>("Modules", ghoul::Dictionary());
|
||||
sceneFileDictionary.setValue<ghoul::Dictionary>("Camera", cameraDictionary);
|
||||
|
||||
sceneFile << "return " << formatter.format(sceneFileDictionary);
|
||||
sceneFile.close();
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(scenePath);
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 1) << "Expected scene to consist of one root node";
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test00) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test00.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 1) << "Expected scene to consist of one root node";
|
||||
}
|
||||
|
||||
|
||||
TEST(SceneLoaderTest, Test00Location) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test00-location.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 1) << "Expected scene to consist of one root node";
|
||||
}
|
||||
|
||||
|
||||
TEST(SceneLoaderTest, Test01) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test01.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 2) << "Expected scene to consist of two nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 2) << "Expected scene to consist of two nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test01Location) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test01-location.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 2) << "Expected scene to consist of two nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 2) << "Expected scene to consist of two nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test02) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test02.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 3) << "Expected scene to consist of two nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 3) << "Expected scene to consist of two nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
EXPECT_EQ(nodesByName["Child"]->parent(), nodesByName["NoDependency"]);
|
||||
|
||||
EXPECT_EQ(nodesByName["Root"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["Child"]->dependencies().size(), 0);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test02Location) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test02-location.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 3) << "Expected scene to consist of three nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 3) << "Expected scene to consist of three nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["Child"]->name(), "Child");
|
||||
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
EXPECT_EQ(nodesByName["Child"]->parent(), nodesByName["NoDependency"]);
|
||||
|
||||
EXPECT_EQ(nodesByName["Root"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["Child"]->dependencies().size(), 0);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test03) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test03.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 3) << "Expected scene to consist of three nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 3) << "Expected scene to consist of three nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["Dependent"]->name(), "Dependent");
|
||||
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
EXPECT_EQ(nodesByName["Dependent"]->parent(), nodesByName["Root"]);
|
||||
|
||||
EXPECT_EQ(nodesByName["Root"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["Dependent"]->dependencies().size(), 1);
|
||||
|
||||
EXPECT_EQ(nodesByName["Dependent"]->dependencies()[0], nodesByName["NoDependency"]);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test04) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test04.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
|
||||
ASSERT_NE(scene, nullptr) << "loadScene returned nullptr";
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
EXPECT_EQ(nodes.size(), 5) << "Expected scene to consist of five nodes";
|
||||
|
||||
std::map<std::string, openspace::SceneGraphNode*> nodesByName = scene->nodesByName();
|
||||
EXPECT_EQ(nodesByName.size(), 5) << "Expected scene to consist of five nodes";
|
||||
EXPECT_EQ(nodesByName["Root"]->name(), "Root");
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->name(), "NoDependency");
|
||||
EXPECT_EQ(nodesByName["Dependent"]->name(), "Dependent");
|
||||
EXPECT_EQ(nodesByName["ChildAndDependent"]->name(), "ChildAndDependent");
|
||||
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->parent(), nodesByName["Root"]);
|
||||
EXPECT_EQ(nodesByName["Child"]->parent(), nodesByName["NoDependency"]);
|
||||
EXPECT_EQ(nodesByName["Dependent"]->parent(), nodesByName["Root"]);
|
||||
EXPECT_EQ(nodesByName["ChildAndDependent"]->parent(), nodesByName["NoDependency"]);
|
||||
|
||||
EXPECT_EQ(nodesByName["Root"]->dependencies().size(), 0);
|
||||
EXPECT_EQ(nodesByName["NoDependency"]->dependencies().size(), 0);
|
||||
|
||||
EXPECT_EQ(nodesByName["Dependent"]->dependencies().size(), 1);
|
||||
EXPECT_EQ(nodesByName["Dependent"]->dependencies()[0], nodesByName["NoDependency"]);
|
||||
|
||||
EXPECT_EQ(nodesByName["ChildAndDependent"]->dependencies().size(), 1);
|
||||
EXPECT_EQ(nodesByName["ChildAndDependent"]->dependencies()[0], nodesByName["Dependent"]);
|
||||
}
|
||||
|
||||
TEST(SceneLoaderTest, Test05) {
|
||||
const std::string file = absPath("${TESTDIR}/SceneLoaderTest/test05.scene");
|
||||
|
||||
openspace::SceneLoader loader;
|
||||
std::unique_ptr<openspace::Scene> scene = loader.loadScene(file);
|
||||
std::vector<openspace::SceneGraphNode*> nodes = scene->allSceneGraphNodes();
|
||||
|
||||
EXPECT_EQ(nodes.size(), 1);
|
||||
// TODO: Add more tests regarding circular deps.
|
||||
}
|
||||
Reference in New Issue
Block a user