Merge remote-tracking branch 'origin/NewHorizonsMerge' into feature/timelinegui

Conflicts:
	src/rendering/renderengine.cpp
	src/util/imagesequencer2.cpp
This commit is contained in:
Alexander Bock
2015-05-05 11:42:49 +02:00
133 changed files with 4483 additions and 1819 deletions
+1 -1
View File
@@ -31,6 +31,6 @@
</Window>
</Node>
<User eyeSeparation="0.065">
<Pos x="0.0" y="0.0" z="4.0" />
<Pos x="0.0" y="0.0" z="2.0" />
</User>
</Cluster>
+2 -1
View File
@@ -2,7 +2,8 @@
<Cluster masterAddress="127.0.0.1">
<Node address="127.0.0.1" port="20401">
<Window fullScreen="false">
<Stereo type="none" />
<Stereo type="side_by_side" />
<!-- <Stereo type="side_by_side_inverted" /> -->
<Pos x="200" y="300" />
<!-- 16:9 aspect ratio -->
<Size x="1280" y="360" />
+1 -1
View File
@@ -25,7 +25,7 @@
#ifndef __CONTROLLER_H__
#define __CONTROLLER_H__
#include <openspace/scenegraph/scenegraphnode.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/glm.h>
#include <glm/gtx/vector_angle.hpp>
+2 -2
View File
@@ -33,10 +33,10 @@ namespace properties {
class Property;
}
class Renderable;
class SceneGraph;
class Scene;
class SceneGraphNode;
SceneGraph* sceneGraph();
Scene* sceneGraph();
SceneGraphNode* sceneGraphNode(const std::string& name);
Renderable* renderable(const std::string& name);
properties::Property* property(const std::string& uri);
@@ -37,14 +37,34 @@ class ModelGeometry : public properties::PropertyOwner {
public:
static ModelGeometry* createFromDictionary(const ghoul::Dictionary& dictionary);
ModelGeometry();
ModelGeometry(const ghoul::Dictionary& dictionary);
virtual ~ModelGeometry();
virtual bool initialize(RenderableModel* parent);
virtual void deinitialize();
virtual void render() = 0;
void render();
virtual bool loadModel(const std::string& filename) = 0;
void changeRenderMode(const GLenum mode);
protected:
RenderableModel* _parent;
struct Vertex {
GLfloat location[4];
GLfloat tex[2];
GLfloat normal[3];
};
bool loadObj(const std::string& filename);
bool loadCachedFile(const std::string& filename);
bool saveCachedFile(const std::string& filename);
GLuint _vaoID;
GLuint _vbo;
GLuint _ibo;
GLenum _mode;
std::vector<Vertex> _vertices;
std::vector<int> _indices;
std::string _file;
};
} // namespace modelgeometry
@@ -57,27 +57,25 @@ protected:
private:
properties::StringProperty _colorTexturePath;
properties::StringProperty _bumpTexturePath;
properties::BoolProperty _performFade;
properties::FloatProperty _fading;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::Texture* _texture;
ghoul::opengl::Texture* _bumpMap;
modelgeometry::ModelGeometry* _geometry;
float _alpha;
glm::dmat3 _stateMatrix;
std::string _source;
std::string _destination;
std::string _target;
bool _isGhost;
psc _sunPosition;
properties::BoolProperty _performShading;
properties::BoolProperty _performFade;
properties::FloatProperty _fading;
};
} // namespace openspace
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __WAVEFRONTOBJECT_H__
#define __WAVEFRONTOBJECT_H__
#ifndef __WAVEFRONTGEOMETRY_H__
#define __WAVEFRONTGEOMETRY_H__
#include <openspace/rendering/model/modelgeometry.h>
@@ -37,28 +37,11 @@ class WavefrontGeometry : public ModelGeometry {
public:
WavefrontGeometry(const ghoul::Dictionary& dictionary);
bool initialize(RenderableModel* parent) override;
bool initialize(RenderableModel* parent) override;
void deinitialize() override;
void render() override;
private:
struct Vertex {
GLfloat location[4];
GLfloat tex[2];
GLfloat normal[3];
};
bool loadObj(const std::string& filename);
bool loadCachedFile(const std::string& filename);
bool saveCachedFile(const std::string& filename);
bool loadModel(const std::string& filename);
GLuint _vaoID;
GLuint _vbo;
GLuint _ibo;
std::vector<Vertex> _vertices;
std::vector<int> _indices;
bool loadModel(const std::string& filename);
};
} // namespace modelgeometry
@@ -64,13 +64,17 @@ private:
properties::StringProperty _colorTexturePath;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::Texture* _texture;
ghoul::opengl::Texture* _nightTexture;
planetgeometry::PlanetGeometry* _geometry;
properties::BoolProperty _performShading;
properties::IntProperty _rotation;
float _alpha;
glm::dmat3 _stateMatrix;
std::string _nightTexturePath;
std::string _frame;
std::string _target;
bool _hasNightTexture;
double _time;
};
@@ -28,7 +28,6 @@
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/util/imagesequencer.h>
#include <openspace/util/imagesequencer2.h>
#include <openspace/util/sequenceparser.h>
@@ -82,12 +81,14 @@ private:
properties::StringProperty _colorTexturePath;
properties::StringProperty _projectionTexturePath;
properties::TriggerProperty _imageTrigger;
properties::IntProperty _rotation;
properties::FloatProperty _fadeProjection;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::ProgramObject* _fboProgramObject;
ghoul::opengl::Texture* _texture;
ghoul::opengl::Texture* _textureOriginal;
ghoul::opengl::Texture* _textureProj;
planetgeometryprojection::PlanetGeometryProjection* _geometry;
@@ -123,12 +124,14 @@ private:
double _previousCapture;
double lightTime;
std::vector<std::pair<double, std::string>> _imageTimes;
std::vector<Image> _imageTimes;
int _sequenceID;
std::string _target;
std::string _frame;
std::string _defaultProjImage;
std::string _next;
bool _capture;
// FBO stuff
@@ -50,8 +50,10 @@ public:
private:
void createSphere();
properties::Vec2Property _radius;
glm::vec2 _modRadius;
properties::Vec4Property _realRadius;
properties::IntProperty _segments;
std::string _name;
PowerScaledSphere* _sphere;
};
@@ -49,9 +49,10 @@ public:
private:
void createSphere();
properties::Vec2Property _radius;
glm::vec2 _modRadius;
properties::Vec4Property _realRadius;
properties::IntProperty _segments;
std::string _name;
properties::IntProperty _vaoID;
properties::IntProperty _vBufferID;
+12
View File
@@ -69,6 +69,13 @@ public:
virtual void update(const UpdateData& data);
bool isVisible() const;
bool hasTimeInterval();
bool getInterval(double& start, double& end);
bool hasBody();
bool getBody(std::string& body);
void setBody(std::string& body);
protected:
std::string findPath(const std::string& path);
@@ -79,6 +86,11 @@ private:
PowerScaledScalar boundingSphere_;
std::string _relativePath;
std::string _startTime;
std::string _endTime;
std::string _targetBody;
bool _hasBody;
bool _hasTimeInterval;
};
} // namespace openspace
+3 -2
View File
@@ -53,6 +53,7 @@ public:
private:
properties::FloatProperty _lineWidth;
properties::BoolProperty _drawSolid;
ghoul::opengl::ProgramObject* _programObject;
ghoul::opengl::Texture* _texture;
openspace::SceneGraphNode* _targetNode;
@@ -76,9 +77,9 @@ public:
int _nrInserted = 0;
int _isteps;
bool _rebuild = false;
bool _interceptTag[5];
bool _interceptTag[9];
bool _withinFOV;
psc _projectionBounds[4];
psc _projectionBounds[8];
psc _interceptVector;
// spice
@@ -0,0 +1,98 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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 _RENDERABLEPLANEPROJECTION_H_
#define _RENDERABLEPLANEPROJECTION_H_
#include <openspace/rendering/renderable.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/imagesequencer2.h>
#include <openspace/properties/vectorproperty.h>
#include <openspace/util/updatestructures.h>
namespace ghoul {
namespace filesystem {
class File;
}
namespace opengl {
class ProgramObject;
class Texture;
}
}
namespace openspace {
struct LinePoint;
struct target {
std::string body;
std::string frame;
std::string node;
};
class RenderablePlaneProjection : public Renderable {
public:
RenderablePlaneProjection(const ghoul::Dictionary& dictionary);
~RenderablePlaneProjection();
bool initialize() override;
bool deinitialize() override;
bool isReady() const override;
void render(const RenderData& data) override;
void update(const UpdateData& data) override;
private:
void loadTexture();
void updatePlane(const Image* img, double currentTime);
std::string findClosestTarget(double currentTime);
void setTarget(std::string body);
std::string _texturePath;
bool _planeIsDirty;
glm::dmat3 _stateMatrix;
std::string _frame;
ghoul::opengl::ProgramObject* _shader;
bool _programIsDirty;
bool _textureIsDirty;
ghoul::opengl::Texture* _texture;
ghoul::filesystem::File* _textureFile;
GLuint _quad;
GLuint _vertexPositionBuffer;
std::string _spacecraft;
std::string _instrument;
target _target;
std::string _name;
bool _moving;
};
} // namespace openspace
#endif
@@ -63,6 +63,7 @@ private:
properties::Vec3Property _lineColor;
properties::FloatProperty _lineFade;
properties::FloatProperty _lineWidth;
properties::BoolProperty _showTimestamps;
ghoul::opengl::ProgramObject* _programObject;
bool _programIsDirty;
@@ -86,6 +87,8 @@ private:
float _increment;
float _oldTime = 0;
float _time;
float _distanceFade;
};
} // namespace openspace
+4 -4
View File
@@ -39,7 +39,7 @@ namespace openspace {
// Forward declare to minimize dependencies
class Camera;
class SyncBuffer;
class SceneGraph;
class Scene;
class ABuffer;
class ABufferVisualizer;
class ScreenLog;
@@ -53,8 +53,8 @@ public:
bool initialize();
void setSceneGraph(SceneGraph* sceneGraph);
SceneGraph* sceneGraph();
void setSceneGraph(Scene* sceneGraph);
Scene* scene();
Camera* camera() const;
ABuffer* abuffer() const;
@@ -111,7 +111,7 @@ private:
void storePerformanceMeasurements();
Camera* _mainCamera;
SceneGraph* _sceneGraph;
Scene* _sceneGraph;
ABuffer* _abuffer;
ScreenLog* _log;
@@ -0,0 +1,46 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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 __DYNAMICEPHEMERIS_H__
#define __DYNAMICEPHEMERIS_H__
#include "ephemeris.h"
namespace openspace {
class DynamicEphemeris: public Ephemeris {
public:
DynamicEphemeris(const ghoul::Dictionary& dictionary
= ghoul::Dictionary());
virtual ~DynamicEphemeris();
virtual const psc& position() const;
virtual void update(const UpdateData& data) override;
void setPosition(psc pos);
private:
psc _position;
};
} // namespace openspace
#endif // __DYNAMICEPHEMERIS_H__
@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __SCENEGRAPH_H__
#define __SCENEGRAPH_H__
#ifndef __SCENE_H__
#define __SCENE_H__
// std includes
#include <vector>
@@ -34,6 +34,7 @@
#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>
@@ -45,11 +46,11 @@ class SceneGraphNode;
// Notifications:
// SceneGraphFinishedLoading
class SceneGraph {
class Scene {
public:
// constructors & destructor
SceneGraph();
~SceneGraph();
Scene();
~Scene();
/**
* Initalizes the SceneGraph by loading modules from the ${SCENEPATH} directory
@@ -95,7 +96,7 @@ public:
*/
SceneGraphNode* sceneGraphNode(const std::string& name) const;
std::vector<SceneGraphNode*> allSceneGraphNodes() const;
std::vector<SceneGraphNode*> allSceneGraphNodes();
/**
* Returns the Lua library that contains all Lua functions available to change the
@@ -115,9 +116,10 @@ private:
std::string _focus;
// actual scenegraph
SceneGraphNode* _root;
std::vector<SceneGraphNode*> _nodes;
std::map<std::string, SceneGraphNode*> _allNodes;
SceneGraph _graph;
//SceneGraphNode* _root;
//std::vector<SceneGraphNode*> _nodes;
//std::map<std::string, SceneGraphNode*> _allNodes;
std::string _sceneGraphToLoad;
@@ -143,4 +145,4 @@ private:
} // namespace openspace
#endif // __SCENEGRAPH_H__
#endif // __SCENE_H__
+74
View File
@@ -0,0 +1,74 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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 __SCENEGRAPH_H__
#define __SCENEGRAPH_H__
#include <ghoul/misc/dictionary.h>
#include <unordered_map>
#include <vector>
namespace openspace {
class SceneGraphNode;
class SceneGraph {
public:
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();
SceneGraphNode* rootNode() const;
SceneGraphNode* sceneGraphNode(const std::string& name) const;
private:
struct SceneGraphNodeInternal {
SceneGraphNode* node;
// 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 sortTopologially();
SceneGraphNodeInternal* nodeByName(const std::string& name);
SceneGraphNode* _rootNode;
std::vector<SceneGraphNodeInternal*> _nodes;
std::vector<SceneGraphNode*> _topologicalSortedNodes;
};
} // namespace openspace
#endif // __SCENEGRAPH_H__
@@ -27,10 +27,10 @@
// open space includes
#include <openspace/rendering/renderable.h>
#include <openspace/scenegraph/ephemeris.h>
#include <openspace/scene/ephemeris.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/scene/scene.h>
#include <ghoul/misc/dictionary.h>
#include <openspace/util/updatestructures.h>
@@ -65,9 +65,11 @@ public:
void render(const RenderData& data);
void updateCamera(Camera* camera) const;
void addNode(SceneGraphNode* child);
//void addNode(SceneGraphNode* child);
void setParent(SceneGraphNode* parent);
//bool abandonChild(SceneGraphNode* child);
const psc& position() const;
psc worldPosition() const;
@@ -25,7 +25,7 @@
#ifndef __SPICEEPHEMERIS_H__
#define __SPICEEPHEMERIS_H__
#include <openspace/scenegraph/ephemeris.h>
#include <openspace/scene/ephemeris.h>
#include <openspace/util/powerscaledcoordinate.h>
@@ -42,6 +42,8 @@ private:
std::string _originName;
psc _position;
bool _kernelsLoadedSuccessfully;
std::string _ghosting;
std::string _name;
};
} // namespace openspace
-122
View File
@@ -1,122 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/scenegraph/scenegraph.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/time.h>
#include <openspace/util/spice.h>
#include <openspace/util/factorymanager.h>
class SceneGraphTest : public testing::Test {
protected:
SceneGraphTest() {
_scenegraph = new openspace::SceneGraph;
}
~SceneGraphTest() {
_scenegraph = new openspace::SceneGraph;
}
void reset() {
delete _scenegraph;
_scenegraph = new openspace::SceneGraph;
}
openspace::SceneGraph* _scenegraph;
};
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
}
+14
View File
@@ -72,6 +72,7 @@ namespace scenegraph {
namespace scenegraphnode {
const std::string keyName = "Name";
const std::string keyParentName = "Parent";
const std::string keyDependencies = "Dependencies";
const std::string keyRenderable = "Renderable";
const std::string keyEphemeris = "Ephemeris";
} // namespace scenegraphnode
@@ -88,6 +89,15 @@ namespace renderablemodel {
const std::string keyGeometry = "Geometry";
} // namespace renderablemodel
namespace renderableplaneprojection {
const std::string keySpacecraft = "Spacecraft";
const std::string keyInstrument = "Instrument";
const std::string keyMoving = "Moving";
const std::string keyTexture = "Texture";
const std::string keyName = "Name";
const std::string galacticFrame = "GALACTIC";
} // namespace renderableplaneprojection
namespace renderablestars {
const std::string keyFile = "File";
const std::string keyTexture = "Texture";
@@ -121,6 +131,10 @@ namespace staticephemeris {
const std::string keyPosition = "Position";
} // namespace staticephemeris
namespace dynamicephemeris {
const std::string keyPosition = "Position";
} // namespace dynamicephemeris
namespace spiceephemeris {
const std::string keyBody = "Body";
const std::string keyOrigin = "Observer";
+133 -40
View File
@@ -36,6 +36,19 @@
#include <openspace/util/sequenceparser.h>
namespace openspace {
/**
* The ImageSequencer singleton main function is to manage the timekeeping and
* distribution of large image data-sets across all openspace renderable instances,
* both for past and future unmanned-spacecraft missions. To load the instance with
* data the client must provide a parser inherited from the abstract base class
* SequenceParser. Hence, there is no restriction imposed on data input, whether its
* data in the form of existing images or in the form of a planned observation schedule.
* Notably, in order for the sequencer to function the client must provide or write a
* parser that fills the ImageSequencers private members.
* \see SequenceParser
* \see ImageSequencer2::runSequenceParser(SequenceParser* parser)
* std::map<std::string, bool>
*/
class ImageSequencer2 {
public:
ImageSequencer2();
@@ -43,65 +56,145 @@ public:
* Singelton instantiation
*/
static ImageSequencer2* _instance;
/**
* Returns the reference to the singleton ImageSequencer object that must have been
* initialized by a call to the initialize method earlier.
* \return The ImageSequencer singleton
*/
static ImageSequencer2& ref();
/**
* Initializer that initializes the static member.
*/
static void initialize();
/**
* Deinitializes that deinitializes the static member.
*/
static void deinitialize();
/**
* Returns true if sequencer has been loaded with data.
*/
bool isReady();
//provides the sequencer with current time
/**
* Updates sequencer with current <code>time</code>. This is used internally for keeping
* track of both current simulation time and the time of the previously rendered frame.
*/
void updateSequencer(double time);
/**
* Runs parser and recieves the datastructures filled by it.
* \see SequenceParser
*/
void runSequenceParser(SequenceParser* parser);
//translates playbook ambiguous namesetting to spice calls, augments each observation with targets and
//stores all images in its own subset (see _subsetMap member)
bool parsePlaybookFile(const std::string& fileName,
std::string spacecraft,
std::map<std::string, std::vector<std::string>> acronymDictionary,
std::vector<std::string> potentialTargets);
// returns upcoming target
/**
* Retrieves the next upcoming target in time.
*/
std::pair<double, std::string> getNextTarget();
// returns next target
/**
* Retrieves the most current target in time.
*/
std::pair<double, std::string> getCurrentTarget();
// returns current target and (in the list) adjacent targets, the number to retrieve is user set
/**
* Retrieves current target and (in the list) adjacent targets, the number to retrieve is user set
*/
std::pair<double, std::vector<std::string>> getIncidentTargetList(int range = 2);
/**
* Retrieves the next upcoming time of image capture.
*/
double getNextCaptureTime();
/**
* Retrieves the time interval length between the current time and an upcoming capture.
*/
double getIntervalLength();
std::vector<std::pair<std::string, bool>> getActiveInstruments();
bool ImageSequencer2::getImagePaths(std::vector<std::pair<double, std::string>>& captures, std::string projectee, std::string instrumentID);
bool ImageSequencer2::getImagePaths(std::vector<std::pair<double, std::string>>& captures, std::string projectee);
/*
* Returns a map with key instrument names whose value indicate whether
* an instrument is active or not.
*/
std::map<std::string, bool> getActiveInstruments();
/*
* Retrieves the relevant data from a specific subset based on the what instance
* makes the request. If an instance is not registered in the class then the singleton
* returns false and no projections will occur.
*/
bool ImageSequencer2::getImagePaths(std::vector<Image>& captures,
std::string projectee,
std::string instrumentID);
bool ImageSequencer2::getImagePaths(std::vector<Image>& captures,
std::string projectee);
/*
* returns true if instrumentID is within a capture range.
*/
bool instumentActive(std::string instrumentID);
const Image* findLatestImageInSubset( ImageSubset& subset);
/*
* returns latest captured image
*/
const Image* getLatestImageForInstrument(const std::string _instrumentID);
private:
//default comparison function
bool imageComparer(const Image &a, const Image &b);
//binary find O(log n) always
std::vector<Image>::iterator binary_find(std::vector<Image>::iterator begin,
std::vector<Image>::iterator end,
const Image &val,
bool(*imageComparer)(const Image &a, const Image &b));
//var
double _currentTime;
double _previousTime;
double _intervalLength;
double _nextCapture;
std::string _defaultCaptureImage;
std::vector<std::pair<std::string, bool>> _instrumentOnOff;
std::map<std::string, ImageSubset> _subsetMap;
std::vector<std::pair<double, std::string>> _targetTimes;
std::vector<std::pair<std::string, TimeRange>> _instrumentTimes;
std::vector<double> _captureProgression;
void sortData();
/*
* _fileTranslation handles any types of ambiguities between the data and
* spice/openspace -calls. This map is composed of a key that is a string in
* the data to be translated and a Decoder that holds the corresponding
* translation provided through a modfile.
* \see Decoder
* \see (projection mod files)
*/
std::map<std::string, Decoder*> _fileTranslation;
/*
* This is the main container of image data. The key is the target name,
* the value is a subset of images.
* \see SequenceParser
*/
std::map<std::string, ImageSubset> _subsetMap;
/*
* In order for the simulation to know when to turn on/off any instrument within
* all instruments in the spacecraft payload, the key is the data-file given
* instrument name.
*/
std::map<std::string, bool> _switchingMap;
/*
* This datastructure holds the specific times when the spacecraft switches from
* observing one inertial body to the next. This happens a lot in such missions
* and the coupling of target with specific time is usually therefore not 1:1.
*/
std::vector<std::pair<double, std::string>> _targetTimes;
/*
* Holds the time ranges of each instruments on and off periods. An instrument
* rendering class may ask the ImageSequencer whether or not it
*/
std::vector<std::pair<std::string, TimeRange>> _instrumentTimes;
/*
* Each consecutive images capture time, for easier traversal.
*/
std::vector<double> _captureProgression;
// current simulation time
double _currentTime;
// simulation time of previous frame
double _previousTime;
// time between current simulation time and an upcoming capture
double _intervalLength;
// next consecutive capture in time
double _nextCapture;
// default capture image
std::string _defaultCaptureImage;
Image* _latestImage;
// if no data, no run
bool _hasData;
};
@@ -36,8 +36,10 @@ public:
InstrumentDecoder(const ghoul::Dictionary& dictionary);
virtual std::string getDecoderType();
virtual std::vector<std::string> getTranslation();
std::string getStopCommand();
private:
std::string _type;
std::string _stopCommand;
std::vector<std::string> _spiceIDs;
};
+44 -33
View File
@@ -33,44 +33,55 @@
#include <vector>
namespace openspace {
class LabelParser : public SequenceParser{
public:
LabelParser();
LabelParser(const std::string& fileName,
ghoul::Dictionary translationDictionary);
virtual void create();
virtual std::map<std::string, ImageSubset> getSubsetMap();
virtual std::vector<std::pair<std::string, TimeRange>> getIstrumentTimes();
virtual std::vector<std::pair<double, std::string>> getTargetTimes();
class LabelParser : public SequenceParser{
public:
LabelParser();
LabelParser(const std::string& fileName,
ghoul::Dictionary translationDictionary);
virtual void create();
virtual std::map<std::string, ImageSubset> getSubsetMap();
virtual std::vector<std::pair<std::string, TimeRange>> getIstrumentTimes();
virtual std::vector<std::pair<double, std::string>> getTargetTimes();
// temporary need to figure this out
std::map<std::string, Decoder*> getTranslation(){ return _fileTranslation; };
virtual std::vector<double> getCaptureProgression(){ return _captureProgression; };
// temporary need to figure this out
std::map<std::string, Decoder*> getTranslation(){ return _fileTranslation; };
virtual std::vector<double> getCaptureProgression(){ return _captureProgression; };
private:
void createImage(Image& image,
double startTime,
double stopTime,
std::vector<std::string> instr,
std::string targ,
std::string pot);
private:
void createImage(Image& image,
double startTime,
double stopTime,
std::vector<std::string> instr,
std::string targ,
std::string path);
bool augmentWithSpice(Image& image,
std::string spacecraft,
std::vector<std::string> payload,
std::vector<std::string> potentialTargets);
std::string decode(std::string line);
std::string encode(std::string line);
bool augmentWithSpice(Image& image,
std::string spacecraft,
std::vector<std::string> payload,
std::vector<std::string> potentialTargets);
std::string _fileName;
std::string _spacecraft;
std::map<std::string, Decoder*> _fileTranslation;
std::vector<std::string> _specsOfInterest;
std::string _fileName;
std::string _spacecraft;
std::map<std::string, Decoder*> _fileTranslation;
std::vector<std::string> _specsOfInterest;
//returnable
std::map<std::string, ImageSubset> _subsetMap;
std::vector<std::pair<std::string, TimeRange>> _instrumentTimes;
std::vector<std::pair<double, std::string>> _targetTimes;
std::vector<double> _captureProgression;
};
//returnable
std::map<std::string, ImageSubset> _subsetMap;
std::vector<std::pair<std::string, TimeRange>> _instrumentTimes;
std::vector<std::pair<double, std::string>> _targetTimes;
std::vector<double> _captureProgression;
std::string _target;
std::string _instrumentID;
std::string _instrumentHostID;
std::string _detectorType;
std::string _sequenceID;
double _startTime;
double _stopTime;
};
}
#endif //__LABELPARSER_H__
@@ -29,6 +29,7 @@
#include <ghoul/opengl/ghoul_gl.h>
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/powerscaledscalar.h>
#include <openspace/properties/vectorproperty.h>
namespace openspace {
@@ -37,6 +38,9 @@ public:
// initializers
PowerScaledSphere(const PowerScaledScalar& radius,
int segments = 8);
PowerScaledSphere(properties::Vec4Property &radius,
int segments, std::string planetName);
~PowerScaledSphere();
PowerScaledSphere(const PowerScaledSphere& cpy);
+3
View File
@@ -35,8 +35,11 @@ public:
ScannerDecoder(const ghoul::Dictionary& dictionary);
virtual std::string getDecoderType();
virtual std::vector<std::string> getSpiceIDs();
std::string getStopCommand();
void setStopCommand(std::string stopCommand);
private:
std::string _type;
std::string _abort;
std::vector<std::string> _spiceIDs;
};
+1 -1
View File
@@ -37,7 +37,7 @@ namespace openspace {
double startTime;
double stopTime;
std::string path;
std::vector<std::string> activeInstruments;
std::vector<std::string> activeInstruments;
std::string target;
bool projected;
};
+140 -109
View File
@@ -38,6 +38,7 @@
#include <map>
#include <string>
#include <vector>
#include <set>
namespace openspace {
@@ -76,15 +77,51 @@ public:
*/
KernelIdentifier loadKernel(const std::string& filePath);
/**
* Function to find and store the intervals covered by a ck file, this is done
* by using mainly the <code>ckcov_c</code> and <code>ckobj_c</code> functions.
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckobj_c.html ,
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckcov_c.html
* \param filePath The path to the kernel that should be examined
* \return true if the operation was successful
*/
bool findCkCoverage(std::string& path);
/**
* Unloads a SPICE kernel identified by the <code>kernelId</code> which was returned
* by the loading call to loadKernel. The unloading is done by calling the
* <code>unload_c</code> function.
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/unload_c.html
* \param kernelId The unique identifier that was returned from the call to
* loadKernel which loaded the kernel
* Function to find and store the intervals covered by a spk file, this is done
* by using mainly the <code>spkcov_c</code> and <code>spkobj_c</code> functions.
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkobj_c.html ,
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkcov_c.html
* \param filePath The path to the kernel that should be examined
* \return true if the operation was successful
*/
bool findSpkCoverage(std::string& path);
/**
* \return true if SPK kernels have been loaded to cover <code>target</code>
* for time <code>et</code>
* \param target, the body to be examined
* \param et, the time when body is possibly covered
*/
bool hasSpkCoverage(std::string target, double& et) const;
/**
* \return true if CK kernels have been loaded to cover <code>frame</code>
* for time <code>et</code>
* \param frame, the frame to be examined
* \param et, the time when frame is possibly covered
*/
bool hasCkCoverage(std::string frame, double& et) const;
/**
* Unloads a SPICE kernel identified by the <code>kernelId</code> which was returned
* by the loading call to loadKernel. The unloading is done by calling the
* <code>unload_c</code> function.
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/unload_c.html.
* \param kernelId The unique identifier that was returned from the call to
* loadKernel which loaded the kernel
*/
void unloadKernel(KernelIdentifier kernelId);
/**
@@ -134,6 +171,19 @@ public:
*/
bool getNaifId(const std::string& body, int& id) const;
/**
* Returns the NAIF ID for a specific frame using namfrm_c(), see
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/namfrm_c.html.
* The <code>id</code> will only be set if the retrieval was successful,
* otherwise it will remain unchanged.
* \param frame The frame name that should be retrieved
* \param id The ID of the <code>frame</code> will be stored in this variable. The
* value will only be changed if the retrieval was successful
* \return <code>true</code> if the <code>frame</code> was found, <code>false</code>
* otherwise
*/
bool getFrameId(const std::string& frame, int& id) const;
/**
* Retrieves a single <code>value</code> for a certain <code>body</code>. This method
* succeeds iff <code>body</code> is the name of a valid body, <code>value</code>
@@ -252,26 +302,8 @@ public:
* \return <code>true</code> if the conversion succeeded, <code>false</code> otherwise
*/
bool getDateFromET(double ephemerisTime, std::string& date,
const std::string& format = "YYYY MON DDTHR:MN:SC.### ::RND");
const std::string& format = "YYYY MON DDTHR:MN:SC.### ::RND") const;
/**
* This helper method converts a 3 dimensional vector from one reference frame to another.
* \param v The vector to be converted
* \param from The frame to be converted from
* \param to The frame to be converted to
* \param ephemerisTime Time at which to get rotational matrix that transforms vector
* \return <code>true</code> if the conversion succeeded, <code>false</code> otherwise
*/
bool frameConversion(glm::dvec3& v, const std::string& from, const std::string& to, double ephemerisTime) const;
/**
* Finds the projection of one vector onto another vector.
* All vectors are 3-dimensional.
* \param v1 The vector to be projected.
* \param v2 The vector onto which v1 is to be projected.
* \return The projection of v1 onto v2.
*/
glm::dvec3 orthogonalProjection(glm::dvec3& v1, glm::dvec3& v2);
/**
* Returns the <code>position</code> of a <code>target</code> body relative to an
@@ -313,6 +345,39 @@ public:
psc& position,
double& lightTime) const;
/**
* If a position is requested for an uncovered time in the SPK kernels,
* this function will insert a position in <code>modelPosition</code>.
* If the coverage has not yet started, the first position will be retrieved,
* If the coverage has ended, the last position will be retrieved
* If <code>time</code> is in a coverage gap, the position will be interpolated
* \param time, for which an estimated position is desirable
* \param target, the body which is missing SPK data for this time
* \param origin, the observer, the position will be retrieved in relation to this body
* \param modelPosition, the position of the body, passed by reference
* \return true if an estimated position is found
*/
bool getEstimatedPosition(const double time, const std::string target, const std::string origin, psc& modelPosition) const;
/**
* This helper method converts a 3 dimensional vector from one reference frame to another.
* \param v The vector to be converted
* \param from The frame to be converted from
* \param to The frame to be converted to
* \param ephemerisTime Time at which to get rotational matrix that transforms vector
* \return <code>true</code> if the conversion succeeded, <code>false</code> otherwise
*/
bool frameConversion(glm::dvec3& v, const std::string& from, const std::string& to, double ephemerisTime) const;
/**
* Finds the projection of one vector onto another vector.
* All vectors are 3-dimensional.
* \param v1 The vector to be projected.
* \param v2 The vector onto which v1 is to be projected.
* \return The projection of v1 onto v2.
*/
glm::dvec3 orthogonalProjection(glm::dvec3& v1, glm::dvec3& v2);
/**
* Given an observer and a direction vector defining a ray, compute
* the surface intercept of the ray on a target body at a specified
@@ -488,11 +553,21 @@ public:
double ephemerisTimeTo,
glm::dmat3& transformationMatrix) const;
/**
* If a transform matrix is requested for an uncovered time in the CK kernels,
* this function will insert a transform matrix in <code>positionMatrix</code>.
* If the coverage has not yet started, the first transform matrix will be retrieved,
* If the coverage has ended, the last transform matrix will be retrieved
* If <code>time</code> is in a coverage gap, the transform matrix will be interpolated
* \param time, for which an estimated transform matrix is desirable
* \param fromFrame, the transform matrix will be retrieved in relation to this frame
* \param toFrame, the frame missing CK data for this time
* \param positionMatrix, the estimated transform matrix of the frame, passed by reference
* \return true if an estimated transform matrix is found
*/
bool getEstimatedTransformMatrix(const double time, const std::string fromFrame, const std::string toFrame, glm::dmat3& positionMatrix) const;
bool getPositionPrimeMeridian(const std::string& sourceFrame,
const std::string& destinationFrame,
double ephemerisTime,
glm::dmat3& transformationMatrix) const;
/**
* Applies the <code>transformationMatrix</code> retrieved from
@@ -555,88 +630,22 @@ public:
*/
bool getFieldOfView(int instrument, std::string& fovShape, std::string& frameName,
glm::dvec3& boresightVector, std::vector<glm::dvec3>& bounds) const;
/**
* Converts planeto-centric <code>latitude</code> and <code>longitude</code> of a
* surface point on a specified <code>body</code> to rectangular
* <code>coordinates</code>. For further details, refer to
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/srfrec_c.html.
* \param body The body on which the <code>longitude</code> and <code>latitude</code>
* are defined. This body needs to have a defined radius for this function to work
* \param longitude The longitude of the point on the <code>body</code> in radians
* \param latitude The latitude of the point on the <code>body</code> in radians
* \param coordinates The output containing the rectangular coordinates of the point
* defined by <code>longitude</code> and <code>latitude</code> on the
* <code>body</code>. If the method fails, the coordinate are unchanged
* \return <code>true</code> if the function was successful, <code>false</code>
* otherwise
*/
bool geographicToRectangular(const std::string& body, double longitude,
double latitude, glm::dvec3& coordinates) const;
/**
* Converts planeto-centric <code>latitude</code> and <code>longitude</code> of a
* surface point on a body with the NAIF ID of <code>id</code> to rectangular
* <code>coordinates</code>. For further details, refer to
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/srfrec_c.html.
* \param id The body on which the <code>longitude</code> and <code>latitude</code>
* are defined. This body needs to have a defined radius for this function to work
* \param longitude The longitude of the point on the <code>body</code> in radians
* \param latitude The latitude of the point on the <code>body</code> in radians
* \param coordinates The output containing the rectangular coordinates of the point
* defined by <code>longitude</code> and <code>latitude</code> on the
* <code>body</code>. If the method fails, the coordinate are unchanged
* \return <code>true</code> if the function was successful, <code>false</code>
* otherwise
*/
bool geographicToRectangular(int id, double longitude, double latitude,
glm::dvec3& coordinates) const;
* This function adds a frame to a body
* \param body - the name of the body
* \param frame - the name of the frame
* \return false if the arguments are empty
*/
bool addFrame(const std::string body, const std::string frame);
/**
* Compute the rectangular coordinates of the sub-observer point of an
* <code>observer</code> on a target <code>body</code> at a specified
* <code>ephemerisTime</code>, optionally corrected for light time and stellar
* aberration. For further details, refer to
* http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subpnt_c.html.
* Example: If the sub-observer point on Mars for MRO is requested, the
* <code>target</code> would be <code>Mars</code> and the <code>observer</code> would
* be <code>MRO</code>.
* \param target The name of the target body on which the sub-observer point lies
* \param observer The name of the ephemeris object whose sub-observer point should be
* retrieved
* \param computationMethod The computation method used for the sub-observer point.
* Must be one of <code>Near point: ellipsoid</code> or
* <code>Intercept: ellipsoid</code> and it determines the interpretation of the
* results; see http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subpnt_c.html
* for detailed description on the computation methods
* \param bodyFixedFrame The body-fixed, body-centered frame belonging to the
* <code>target</code>
* \param aberrationCorrection The aberration correction flag out of the list of
* values (<code>NONE</code>, <code>LT</code>, <code>LT+S</code>, <code>CN</code>,
* <code>CN+S</code> for the reception case or <code>XLT</code>, <code>XLT+S</code>,
* <code>XCN</code>, or <code>XCN+S</code> for the transmission case.
* \param ephemerisTime The ephemeris time for which the sub-observer point should be
* retrieved
* \param subObserverPoint The output containing the observer's sub-observer point on
* the target body. If the method fails, the value remains unchanged
* \param targetEphemerisTime The output containing the target's ephemeris time
* accounting for the aberration, if an <code>aberrationCorrection</code> value
* different from <code>NONE</code> is chosen. If the method fails, the value remains
* unchanged
* \param vectorToSurfacePoint The output containing the vector from the observer to
* the, potentially aberration corrected, sub-observer point. If the method fails the
* value remains unchanged
* \return <code>true</code> if the function was successful, <code>false</code>
* otherwise
*/
bool getSubObserverPoint(const std::string& target,
const std::string& observer,
const std::string& computationMethod,
const std::string& bodyFixedFrame,
const std::string& aberrationCorrection,
double ephemerisTime,
glm::dvec3& subObserverPoint,
double& targetEphemerisTime,
glm::dvec3& vectorToSurfacePoint) const;
* This function returns the frame of a body if defined, otherwise it returns
* IAU_ + body (most frames are known by the International Astronomical Union)
* \param body - the name of the body
* \return the frame of the body
*/
std::string frameFromBody(const std::string body) const;
/**
* This method checks if one of the previous SPICE methods has failed. If it has, the
@@ -648,6 +657,19 @@ public:
*/
static bool checkForError(std::string errorMessage);
/**
* This method uses the SPICE kernels to get the radii of bodies defined as a
* triaxial ellipsoid. The benefit of this is to be able to create more accurate
* planet shapes, which is desirable when projecting images with SPICE intersection
* methods
* \param planetName - the name of the body, should be recognizable by SPICE
* \param a - equatorial radius 1
* \param b - equatorial radius 2
* \param c - polar radius
* \return <code>true</code> if SPICE reports no errors
*/
bool getPlanetEllipsoid(std::string planetName, float &a, float &b, float &c);
private:
struct KernelInformation {
std::string path; /// The path from which the kernel was loaded
@@ -662,6 +684,15 @@ private:
/// A list of all loaded kernels
std::vector<KernelInformation> _loadedKernels;
// Map: id, vector of pairs. Pair: Start time, end time;
std::map<int, std::vector< std::pair<double, double> > > _ckIntervals;
std::map<int, std::vector< std::pair<double, double> > > _spkIntervals;
std::map<int, std::set<double> > _ckCoverageTimes;
std::map<int, std::set<double> > _spkCoverageTimes;
// Vector of pairs: Body, Frame
std::vector< std::pair<std::string, std::string> > _frameByBody;
const static bool _showErrors = false;
/// The last assigned kernel-id, used to determine the next free kernel id
KernelIdentifier _lastAssignedKernel;
@@ -671,4 +702,4 @@ private:
} // namespace openspace
#endif // __SPICEMANAGER_H__
#endif // __SPICEMANAGER_H__
+1 -1
View File
@@ -5,7 +5,7 @@ return {
SHADERS = "${BASE_PATH}/shaders",
SHADERS_GENERATED = "${SHADERS}/generated",
OPENSPACE_DATA = "${BASE_PATH}/openspace-data",
TESTDIR = "${BASE_PATH}/src/tests",
TESTDIR = "${BASE_PATH}/tests",
CONFIG = "${BASE_PATH}/config",
CACHE = "${BASE_PATH}/cache",
FONTS = "${OPENSPACE_DATA}/fonts",
+14
View File
@@ -36,5 +36,19 @@ openspace.bindKey("j", "local b = openspace.getPropertyValue('PlutoText.renderab
openspace.bindKey("l", "local b = openspace.getPropertyValue('Labels.renderable.performFading'); openspace.setPropertyValue('Labels.renderable.performFading', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_LORRI.renderable.solidDraw'); openspace.setPropertyValue('NH_LORRI.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_LEISA.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_LEISA.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN1.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_PAN2.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_RED.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_BLUE.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_FT.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_METHANE.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw'); openspace.setPropertyValue('NH_RALPH_MVIC_NIR.renderable.solidDraw', not b)")
openspace.bindKey("m", "local b = openspace.getPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw'); openspace.setPropertyValue('NH_ALICE_AIRGLOW.renderable.solidDraw', not b)")
openspace.bindKey("PAUSE", "openspace.printInfo('F5: Toogle to Sun, F6: Toggle to Jupiter, F7: Toggle to Pluto'); openspace.printInfo('Bookmarks: 1: Jupter, 2-7: Pluto');")
+7 -2
View File
@@ -7,14 +7,19 @@ openspace.setInvertRoll(true);
--openspace.time.setTime("2007 FEB 27 16:30:00") -- This is the start time for a Jupiter run of New Horizons
--openspace.time.setTime("2007 FEB 28 03:45:00") -- Io Capture!
openspace.time.setDeltaTime(0) -- How many seconds pass per second of realtime, changeable in the GUI
--openspace.time.setTime("2011 AUG 6 07:15:00") -- Dawn @ Vestaprojection
--openspace.time.setTime("2014 AUG 28 03:45:00") -- Rosetta Travels 67p in triangular shape
openspace.time.setDeltaTime(10) -- How many seconds pass per second of realtime, changeable in the GUI
dofile(openspace.absPath('${SCRIPTS}/bind_keys.lua')) -- Load the default keybindings
-- openspace.time.setDeltaTime(50);
openspace.time.setTime("2015-07-14T10:10:00.00") -- PLUTO
openspace.time.setTime("2015-07-14T10:50:00.00") -- PLUTO
-- NH takes series of images from visible to dark side (across terminator)
-- Sequence lasts ~10 mins, (recommended dt = 10)
+12 -7
View File
@@ -22,15 +22,18 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version 430
#version __CONTEXT__
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform mat4 ProjectorMatrix;
uniform mat4 ModelTransform;
uniform vec2 _scaling;
uniform vec2 radius;
uniform vec4 radius;
flat in uint vs_segments;
uniform float projectionFading;
in vec4 vs_position;
uniform vec3 boresight;
@@ -38,7 +41,7 @@ out vec4 color;
#define M_PI 3.14159265358979323846
vec4 uvToModel( float u, float v, vec2 radius, float segments){
vec4 uvToModel( float u, float v, vec4 radius, float segments){
const float fj = u * segments;
const float fi = v * segments;
@@ -46,10 +49,10 @@ vec4 uvToModel( float u, float v, vec2 radius, float segments){
const float phi = fj * float(M_PI) * 2.0f / segments;
const float x = radius[0] * sin(phi) * sin(theta); //
const float y = radius[0] * cos(theta); // up
const float z = radius[0] * cos(phi) * sin(theta); //
const float y = radius[1] * cos(theta); // up
const float z = radius[2] * cos(phi) * sin(theta); //
return vec4(x, y, z, radius[1]);
return vec4(x, y, z, radius[3]);
}
#include "PowerScaling/powerScaling_vs.hglsl"
@@ -78,7 +81,9 @@ void main() {
dot(v_b, normal) < 0 ) {
color = texture(texture1, projected.xy);
}else{
color = vec4(1,1,1,0);
color = texture(texture2, uv);
color.a = projectionFading;
}
// color.a = 0.1f;//1.f - abs(uv.x - 0.55) / (0.6 - 0.5); // blending
}
+2 -1
View File
@@ -22,7 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version 430
#version __CONTEXT__
uniform mat4 ProjectorMatrix;
uniform mat4 ModelTransform;
uniform vec2 _scaling;
+13 -28
View File
@@ -31,14 +31,13 @@ uniform vec3 cam_dir; // add this for specular
uniform vec3 sun_pos;
uniform bool _performShading = true;
uniform float transparency;
uniform int shadows;
uniform float fading;
uniform float time;
uniform sampler2D texture1;
uniform sampler2D texture2;
in vec2 vs_st;
in vec4 vs_normal;
@@ -55,52 +54,38 @@ void main()
float depth = pscDepth(position);
vec4 diffuse = texture(texture1, vs_st);
vec3 normal = normalize(texture2D(texture2, vs_st).rgb * 2.0 - 1.0);
if (fading > 0 || fading < 1){
diffuse.a = fading;
}
diffuse[3] = fading;
if (_performShading) {
vec4 spec = vec4(0.0);
vec3 n = normalize(vs_normal.xyz);
//vec3 n = normalize(normal.xyz);
vec3 l_pos = vec3(sun_pos); // sun.
vec3 l_dir = normalize(l_pos-objpos.xyz);
float intensity = min(max(1*dot(n,l_dir), 0.0), 1);
float diff = max( dot(l_dir, n), 0.0 );
float shine = 100;
/*if(normal.x > 0 && normal.y > 0 && normal.z > 0){
n = normalize(normal.xyz);
}*/
vec4 specular = vec4(1.0);
vec4 ambient = diffuse*0.4;//vec4(0.0,0.0,0.0,1);
if(intensity > 0.0f){
float shine = 100;
vec4 specular = vec4(1.0);
vec4 ambient =diffuse*0.4;
ambient[3] = transparency;
if(intensity > 0.0f){
// halfway vector
vec3 h = normalize(l_dir + normalize(cam_dir));
// specular factor
float intSpec = max(dot(n,h),0.0);
spec = specular * pow(intSpec, shine);
}
diffuse = vec4(max(intensity * diffuse , ambient).xyz,1) +spec*1.5*diffuse ;
if (fading > 0 || fading < 1){
diffuse.a = fading;
}
//diffuse = vec4(1);
diffuse[3] = fading*transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
else {
diffuse[3] = fading*transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
@@ -0,0 +1,50 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform float time;
uniform sampler2D texture1;
in vec2 vs_st;
in vec4 vs_position;
#include "ABuffer/abufferStruct.hglsl"
#include "ABuffer/abufferAddToBuffer.hglsl"
#include "PowerScaling/powerScaling_fs.hglsl"
void main()
{
vec4 position = vs_position;
float depth = pscDepth(position);
vec4 diffuse;
if (gl_FrontFacing)
diffuse = texture(texture1, vs_st);
else {
diffuse = vec4(0.8);
}
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
out vec2 vs_st;
out vec4 vs_position;
out float s;
#include "PowerScaling/powerScaling_vs.hglsl"
void main()
{
vec4 tmp = in_position;
vec4 position = pscTransform(tmp, ModelTransform);
vs_position = tmp;
vs_st = in_st;
position = ViewProjection * position;
gl_Position = z_normalization(position);
}
+2 -1
View File
@@ -27,6 +27,7 @@
in vec4 vs_point_position;
in vec4 vs_point_velocity;
in float fade;
uniform float forceFade;
uniform vec3 color;
@@ -38,7 +39,7 @@ void main() {
vec4 position = vs_point_position;
float depth = pscDepth(position);
vec4 c = vec4(color, fade);
vec4 c = vec4(color, fade*forceFade);
ABufferStruct_t frag = createGeometryFragment(c, position, depth);
addToBuffer(frag);
}
+87
View File
@@ -0,0 +1,87 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform vec4 campos;
uniform vec4 objpos;
uniform vec3 sun_pos;
uniform bool _performShading = true;
uniform float transparency;
uniform int shadows;
uniform float time;
uniform sampler2D texture1;
uniform sampler2D nightTex;
in vec2 vs_st;
in vec2 vs_nightTex;
in vec4 vs_normal;
in vec4 vs_position;
#include "ABuffer/abufferStruct.hglsl"
#include "ABuffer/abufferAddToBuffer.hglsl"
#include "PowerScaling/powerScaling_fs.hglsl"
void main()
{
vec4 position = vs_position;
float depth = pscDepth(position);
vec4 diffuse = texture(texture1, vs_st);
vec4 diffuse2 = texture(nightTex, vs_st);
if (_performShading) {
// directional lighting
vec3 origin = vec3(0.0);
vec4 spec = vec4(0.0);
vec3 n = normalize(vs_normal.xyz);
//vec3 e = normalize(camdir);
vec3 l_pos = vec3(sun_pos); // sun.
vec3 l_dir = normalize(l_pos-objpos.xyz);
float intensity = min(max(5*dot(n,l_dir), 0.0), 1);
float darkSide = min(max(5*dot(n,-l_dir), 0.0), 1);
float shine = 0.0001;
vec4 specular = vec4(0.5);
vec4 ambient = vec4(0.0,0.0,0.0,transparency);
vec4 daytex = max(intensity * diffuse, ambient);
vec4 mixtex = mix(diffuse, diffuse2, (1+dot(n,-l_dir))/2);
diffuse = (daytex*2 + mixtex)/3;
diffuse[3] = transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
else {
diffuse[3] = transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
}
+57
View File
@@ -0,0 +1,57 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version __CONTEXT__
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec2 in_st;
layout(location = 2) in vec3 in_normal;
//layout(location = 3) in vec2 in_nightTex;
out vec2 vs_st;
out vec4 vs_normal;
out vec4 vs_position;
out float s;
#include "PowerScaling/powerScaling_vs.hglsl"
void main()
{
// set variables
vs_st = in_st;
vs_position = in_position;
vec4 tmp = in_position;
// this is wrong for the normal. The normal transform is the transposed inverse of the model transform
vs_normal = normalize(ModelTransform * vec4(in_normal,0));
vec4 position = pscTransform(tmp, ModelTransform);
vs_position = tmp;
position = ViewProjection * position;
gl_Position = z_normalization(position);
}
+2 -2
View File
@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version 430
#version __CONTEXT__
uniform vec4 campos;
uniform vec4 objpos;
@@ -60,7 +60,7 @@ void main()
//vec3 e = normalize(camdir);
vec3 l_pos = sun_pos; // sun.
vec3 l_dir = normalize(l_pos-objpos.xyz);
float terminatorBright = 0.4;
float terminatorBright = 0.1;
float intensity = min(max(5*dot(n,l_dir), terminatorBright), 1);
float shine = 0.0001;
+1 -1
View File
@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#version 430
#version __CONTEXT__
uniform mat4 ViewProjection;
uniform mat4 ModelTransform;
+5 -4
View File
@@ -31,7 +31,7 @@ uniform vec4 objpos;
uniform vec3 sun_pos;
uniform bool _performShading = true;
uniform float transparency;
uniform int shadows;
uniform float time;
@@ -66,7 +66,7 @@ void main()
float shine = 0.0001;
vec4 specular = vec4(0.5);
vec4 ambient = vec4(0.0,0.0,0.0,1);
vec4 ambient = vec4(0.0,0.0,0.0,transparency);
/*
if(intensity > 0.f){
// halfway vector
@@ -77,12 +77,13 @@ void main()
}
*/
diffuse = max(intensity * diffuse, ambient);
//diffuse = vec4(1);
diffuse[3] = transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
else {
diffuse[3] = transparency;
ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth);
addToBuffer(frag);
}
+23 -8
View File
@@ -110,11 +110,11 @@ file(GLOB RENDERING_MODEL_HEADER ${HEADER_ROOT_DIR}/openspace/rendering/model/*.
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${RENDERING_MODEL_HEADER})
source_group(Rendering\\Model FILES ${RENDERING_MODEL_SOURCE} ${RENDERING_MODEL_HEADER})
file(GLOB SCENEGRAPH_SOURCE ${SOURCE_ROOT_DIR}/scenegraph/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${SCENEGRAPH_SOURCE})
file(GLOB SCENEGRAPH_HEADER ${HEADER_ROOT_DIR}/openspace/scenegraph/*.h ${HEADER_ROOT_DIR}/openspace/scenegraph/*.inl)
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${SCENEGRAPH_HEADER})
source_group(SceneGraph FILES ${SCENEGRAPH_SOURCE} ${SCENEGRAPH_HEADER})
file(GLOB SCENE_SOURCE ${SOURCE_ROOT_DIR}/scene/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${SCENE_SOURCE})
file(GLOB SCENE_HEADER ${HEADER_ROOT_DIR}/openspace/scene/*.h ${HEADER_ROOT_DIR}/openspace/scene/*.inl)
set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${SCENE_HEADER})
source_group(Scene FILES ${SCENE_SOURCE} ${SCENE_HEADER})
file(GLOB SCRIPTING_SOURCE ${SOURCE_ROOT_DIR}/scripting/*.cpp)
set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${SCRIPTING_SOURCE})
@@ -156,10 +156,25 @@ include_directories("${HEADER_ROOT_DIR}")
add_executable(OpenSpace ${SOURCE_ROOT_DIR}/main.cpp ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE})
target_link_libraries(OpenSpace ${DEPENDENT_LIBS})
option(OPENSPACE_HAVE_TESTS "Activate the OpenSpace unit tests" ON)
if (OPENSPACE_HAVE_TESTS)
add_definitions(-DOPENSPACE_HAVE_TESTS)
set(OPENSPACE_TEST_DIR ${OPENSPACE_BASE_DIR}/tests)
include_directories("${GHOUL_ROOT_DIR}/ext/gtest/include")
include_directories("${GHOUL_ROOT_DIR}/include")
include_directories("${OPENSPACE_TEST_DIR}")
file(GLOB_RECURSE OPENSPACE_TEST_FILES ${OPENSPACE_BASE_DIR}/tests/*.inl)
source_group(Tests FILES ${OPENSPACE_TEST_FILES})
add_executable(OpenSpaceTest ${OPENSPACE_BASE_DIR}/tests/main.cpp ${OPENSPACE_TEST_FILES} ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE})
target_link_libraries(OpenSpaceTest gtest ${DEPENDENT_LIBS})
endif (OPENSPACE_HAVE_TESTS)
#if (NOT UNIX)
#cotire(OpenSpace)
#endif ()
GhoulCopySharedLibraries(OpenSpace)
add_subdirectory(tests)
+6 -6
View File
@@ -147,12 +147,12 @@ void ABuffer::resolve() {
// Decrease stepsize in volumes if right click is pressed
// TODO: Let the interactionhandler handle this
/*int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT);
float volumeStepFactor = (val) ? 0.2f: 1.0f;
if(volumeStepFactor != _volumeStepFactor) {
_volumeStepFactor = volumeStepFactor;
_resolveShader->setUniform("volumeStepFactor", _volumeStepFactor);
}*/
//int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT);
//float volumeStepFactor = (val) ? 0.2f: 1.0f;
//if(volumeStepFactor != _volumeStepFactor) {
// _volumeStepFactor = volumeStepFactor;
// _resolveShader->setUniform("volumeStepFactor", _volumeStepFactor);
//}
glBindVertexArray(_screenQuad);
glDrawArrays(GL_TRIANGLES, 0, 6);
+5 -7
View File
@@ -38,14 +38,13 @@
#include <openspace/network/networkengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/scene/scene.h>
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/syncbuffer.h>
#include <openspace/util/imagesequencer.h>
#include <openspace/util/imagesequencer2.h> // testing
@@ -104,7 +103,6 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName)
{
SpiceManager::initialize();
Time::initialize();
ImageSequencer::initialize();
ImageSequencer2::initialize();
FactoryManager::initialize();
ghoul::systemcapabilities::SystemCapabilities::initialize();
@@ -128,7 +126,7 @@ OpenSpaceEngine::~OpenSpaceEngine() {
}
OpenSpaceEngine& OpenSpaceEngine::ref() {
assert(_engine);
ghoul_assert(_engine, "OpenSpaceEngine not created");
return *_engine;
}
@@ -137,7 +135,7 @@ bool OpenSpaceEngine::create(
std::vector<std::string>& sgctArguments,
std::string& openGlVersion)
{
assert(_engine == nullptr);
ghoul_assert(!_engine, "OpenSpaceEngine was already created");
// Initialize the LogManager and add the console log as this will be used every time
// and we need a fall back if something goes wrong between here and when we add the
@@ -277,7 +275,7 @@ bool OpenSpaceEngine::initialize() {
// Register Lua script functions
LDEBUG("Registering Lua libraries");
_scriptEngine->addLibrary(RenderEngine::luaLibrary());
_scriptEngine->addLibrary(SceneGraph::luaLibrary());
_scriptEngine->addLibrary(Scene::luaLibrary());
_scriptEngine->addLibrary(Time::luaLibrary());
_scriptEngine->addLibrary(interaction::InteractionHandler::luaLibrary());
_scriptEngine->addLibrary(LuaConsole::luaLibrary());
@@ -308,7 +306,7 @@ bool OpenSpaceEngine::initialize() {
// Load scenegraph
SceneGraph* sceneGraph = new SceneGraph;
Scene* sceneGraph = new Scene;
_renderEngine->setSceneGraph(sceneGraph);
// initialize the RenderEngine
+2 -2
View File
@@ -26,7 +26,7 @@
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scenegraph/scenegraphnode.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/interaction/interactionhandler.h>
#include <ghoul/misc/assert.h>
#include "imgui.h"
@@ -41,7 +41,7 @@ namespace gui {
void GuiOriginComponent::render() {
const SceneGraphNode* currentFocus = OsEng.interactionHandler()->focusNode();
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->sceneGraph()->allSceneGraphNodes();
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->scene()->allSceneGraphNodes();
std::sort(nodes.begin(), nodes.end(), [](SceneGraphNode* lhs, SceneGraphNode* rhs) { return lhs->name() < rhs->name(); });
auto it = std::find(nodes.begin(), nodes.end(), currentFocus);
ghoul_assert(it != nodes.end(), "Focus node not found");
+5 -5
View File
@@ -27,8 +27,8 @@
#include <openspace/engine/openspaceengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/scenegraph/scenegraphnode.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
namespace openspace {
@@ -36,14 +36,14 @@ namespace {
const std::string _loggerCat = "Query";
}
SceneGraph* sceneGraph()
Scene* sceneGraph()
{
return OsEng.renderEngine()->sceneGraph();
return OsEng.renderEngine()->scene();
}
SceneGraphNode* sceneGraphNode(const std::string& name)
{
const SceneGraph* graph = sceneGraph();
const Scene* graph = sceneGraph();
return graph->sceneGraphNode(name);
}
+154 -10
View File
@@ -25,19 +25,23 @@
#include <openspace/rendering/model/modelgeometry.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/constants.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <fstream>
#include <openspace/rendering/model/wavefrontgeometry.h>
namespace {
const std::string _loggerCat = "ModelGeometry";
const std::string keyObjFile = "ObjFile";
const int8_t CurrentCacheVersion = 3;
const std::string keyType = "Type";
}
namespace openspace {
namespace modelgeometry {
ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dictionary)
{
ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dictionary) {
std::string geometryType;
const bool success = dictionary.getValue(
keyType, geometryType);
@@ -58,23 +62,163 @@ ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dict
return result;
}
ModelGeometry::ModelGeometry()
ModelGeometry::ModelGeometry(const ghoul::Dictionary& dictionary)
: _parent(nullptr)
, _mode(GL_TRIANGLES)
{
setName("ModelGeometry");
using constants::scenegraphnode::keyName;
std::string name;
bool success = dictionary.getValue(keyName, name);
ghoul_assert(success, "Name tag was not present");
success = dictionary.getValue(keyObjFile, _file);
if (!success) {
LERROR("WaveFrontGeometry of '" << name << "' did not provide a key '"
<< keyObjFile << "'");
}
_file = FileSys.absolutePath(_file);
if (!FileSys.fileExists(_file, true))
LERROR("Could not load OBJ file '" << _file << "': File not found");
}
ModelGeometry::~ModelGeometry()
{
ModelGeometry::~ModelGeometry() {
}
bool ModelGeometry::initialize(RenderableModel* parent){
void ModelGeometry::render() {
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glDrawElements(_mode, _indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
void ModelGeometry::changeRenderMode(const GLenum mode){
_mode = mode;
}
bool ModelGeometry::initialize(RenderableModel* parent) {
_parent = parent;
PowerScaledScalar ps = PowerScaledScalar(1.0, 0.0); // will set proper bounding soon.
_parent->setBoundingSphere(ps);
if (_vertices.empty())
return false;
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ibo);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, location)));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, tex)));
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, normal)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
return true;
}
void ModelGeometry::deinitialize()
{
void ModelGeometry::deinitialize() {
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vaoID);
glDeleteBuffers(1, &_ibo);
}
bool ModelGeometry::loadObj(const std::string& filename){
std::string cachedFile = "";
FileSys.cacheManager()->getCachedFile(filename, cachedFile, true);
bool hasCachedFile = FileSys.fileExists(cachedFile);
if (hasCachedFile) {
LINFO("Cached file '" << cachedFile << "' used for Model file '" << filename << "'");
bool success = loadCachedFile(cachedFile);
if (success)
return true;
else
FileSys.cacheManager()->removeCacheFile(filename);
// Intentional fall-through to the 'else' computation to generate the cache
// file for the next run
}
else {
LINFO("Cache for Model'" << filename << "' not found");
}
LINFO("Loading Model file '" << filename << "'");
bool success = loadModel(filename);
if (!success)
//return false;
LINFO("Saving cache");
success = saveCachedFile(cachedFile);
return success;
}
bool ModelGeometry::saveCachedFile(const std::string& filename) {
std::ofstream fileStream(filename, std::ofstream::binary);
if (fileStream.good()) {
fileStream.write(reinterpret_cast<const char*>(&CurrentCacheVersion),
sizeof(int8_t));
int64_t vSize = _vertices.size();
fileStream.write(reinterpret_cast<const char*>(&vSize), sizeof(int64_t));
int64_t iSize = _indices.size();
fileStream.write(reinterpret_cast<const char*>(&iSize), sizeof(int64_t));
fileStream.write(reinterpret_cast<const char*>(_vertices.data()), sizeof(Vertex) * vSize);
fileStream.write(reinterpret_cast<const char*>(_indices.data()), sizeof(int) * iSize);
return fileStream.good();
}
else {
LERROR("Error opening file '" << filename << "' for save cache file");
return false;
}
}
bool ModelGeometry::loadCachedFile(const std::string& filename) {
std::ifstream fileStream(filename, std::ifstream::binary);
if (fileStream.good()) {
int8_t version = 0;
fileStream.read(reinterpret_cast<char*>(&version), sizeof(int8_t));
if (version != CurrentCacheVersion) {
LINFO("The format of the cached file has changed, deleting old cache");
fileStream.close();
FileSys.deleteFile(filename);
return false;
}
int64_t vSize, iSize;
fileStream.read(reinterpret_cast<char*>(&vSize), sizeof(int64_t));
fileStream.read(reinterpret_cast<char*>(&iSize), sizeof(int64_t));
_vertices.resize(vSize);
_indices.resize(iSize);
fileStream.read(reinterpret_cast<char*>(_vertices.data()), sizeof(Vertex) * vSize);
fileStream.read(reinterpret_cast<char*>(_indices.data()), sizeof(int) * iSize);
return fileStream.good();
}
else {
LERROR("Error opening file '" << filename << "' for loading cache file");
return false;
}
}
} // namespace modelgeometry
} // namespace openspace
+73 -70
View File
@@ -37,32 +37,37 @@
#include <openspace/util/time.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/imagesequencer2.h>
#include <openspace/engine/openspaceengine.h>
#include <sgct.h>
#include "imgui.h"
namespace {
const std::string _loggerCat = "RenderableModel";
namespace {
const std::string _loggerCat = "RenderableModel";
const std::string keySource = "Rotation.Source";
const std::string keyDestination = "Rotation.Destination";
const std::string keyShading = "Shading.PerformShading";
const std::string keyFading = "Shading.Fadeable";
const std::string keyBody = "Body";
const std::string keyStart = "StartTime";
const std::string keyEnd = "EndTime";
const std::string keyFading = "Shading.Fadeable";
const std::string keyGhosting = "Shading.Ghosting";
}
namespace openspace {
RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _colorTexturePath("colorTexture", "Color Texture")
, _bumpTexturePath("bumpTexture", "Bump Texture")
, _programObject(nullptr)
, _texture(nullptr)
, _bumpMap(nullptr)
, _geometry(nullptr)
, _performShading("performShading", "Perform Shading", true)
, _fading("fading", "Fade", 0)
, _performFade("performFading", "Perform Fading", false)
RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _colorTexturePath("colorTexture", "Color Texture")
, _programObject(nullptr)
, _texture(nullptr)
, _geometry(nullptr)
, _isGhost(false)
, _performShading("performShading", "Perform Shading", true)
, _alpha(1.f)
, _fading("fading", "Fade", 0)
, _performFade("performFading", "Perform Fading", false)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
@@ -80,53 +85,43 @@ namespace openspace {
_geometry = modelgeometry::ModelGeometry::createFromDictionary(geometryDictionary);
}
addPropertySubOwner(_geometry);
std::string texturePath = "";
success = dictionary.getValue("Textures.Color", texturePath);
if (success)
_colorTexturePath = path + "/" + texturePath;
addPropertySubOwner(_geometry);
addProperty(_colorTexturePath);
_colorTexturePath.onChange(std::bind(&RenderableModel::loadTexture, this));
std::string bumpPath = "";
success = dictionary.getValue("Textures.BumpMap", bumpPath);
if (success)
_bumpTexturePath = path + "/" + bumpPath;
addProperty(_bumpTexturePath);
_colorTexturePath.onChange(std::bind(&RenderableModel::loadTexture, this));
dictionary.getValue(keySource, _source);
dictionary.getValue(keyDestination, _destination);
dictionary.getValue(keyBody, _target);
openspace::SpiceManager::ref().addFrame(_target, _source);
setBoundingSphere(pss(1.f, 9.f));
if (dictionary.hasKeyAndValue<bool>(keyShading)) {
bool shading;
dictionary.getValue(keyShading, shading);
_performShading = shading;
}
addProperty(_performShading);
if (dictionary.hasKeyAndValue<bool>(keyFading)) {
bool fading;
dictionary.getValue(keyShading, fading);
dictionary.getValue(keyFading, fading);
_performFade = fading;
}
addProperty(_performFade);
if (dictionary.hasKeyAndValue<bool>(keyGhosting)) {
bool ghosting;
dictionary.getValue(keyGhosting, ghosting);
_isGhost = ghosting;
}
}
bool RenderableModel::isReady() const {
bool ready = true;
ready &= (_programObject != nullptr);
ready &= (_texture != nullptr);
ready &= (_bumpMap != nullptr);
return ready;
}
@@ -134,12 +129,11 @@ bool RenderableModel::initialize() {
bool completeSuccess = true;
if (_programObject == nullptr)
completeSuccess
&= OsEng.ref().configurationManager()->getValue("NewHorizonsShader", _programObject);
&= OsEng.ref().configurationManager()->getValue("GenericModelShader", _programObject);
loadTexture();
completeSuccess &= (_texture != nullptr);
completeSuccess &= (_bumpMap != nullptr);
completeSuccess &= _geometry->initialize(this);
completeSuccess &= !_source.empty();
completeSuccess &= !_destination.empty();
@@ -154,17 +148,16 @@ bool RenderableModel::deinitialize() {
}
if (_texture)
delete _texture;
if (_bumpMap)
delete _bumpMap;
_geometry = nullptr;
_texture = nullptr;
_bumpMap = nullptr;
return true;
}
void RenderableModel::render(const RenderData& data) {
_programObject->activate();
double lt;
glm::mat4 transform = glm::mat4(1);
glm::mat4 tmp = glm::mat4(1);
@@ -173,28 +166,33 @@ void RenderableModel::render(const RenderData& data) {
tmp[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
transform *= tmp;
double lt;
psc tmppos;
SpiceManager::ref().getTargetPosition(_source, "SUN", "GALACTIC", "NONE", Time::ref().currentTime(), tmppos, lt);
double time = openspace::Time::ref().currentTime();
bool targetPositionCoverage = openspace::SpiceManager::ref().hasSpkCoverage(_target, time);
if (!targetPositionCoverage){
int frame = ImGui::GetFrameCount() % 180;
float fadingFactor = sin((frame * pi_c()) / 180);
_alpha = 0.5f + fadingFactor*0.5f;
//_texture = "";
}
else
_alpha = 1.0f;
psc tmppos;
SpiceManager::ref().getTargetPosition(_target, "SUN", "GALACTIC", "NONE", time, tmppos, lt);
glm::vec3 cam_dir = glm::normalize(data.camera.position().vec3() - tmppos.vec3());
//std::cout << cam_dir << std::endl;
_programObject->setUniform("sun_pos", _sunPosition.vec3());
_programObject->setUniform("cam_dir", cam_dir);
_programObject->setUniform("transparency", _alpha);
_programObject->setUniform("sun_pos", _sunPosition.vec3());
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject, &data.camera, data.position);
_programObject->setUniform("_performShading", _performShading);
if (_performFade && _fading > 0.f){
_fading = _fading - 0.01f;
}
else if (!_performFade && _fading < 1.f){
_fading = _fading + 0.01f;
@@ -203,19 +201,12 @@ void RenderableModel::render(const RenderData& data) {
_programObject->setUniform("fading", _fading);
// Bind texture
ghoul::opengl::TextureUnit unit;
unit.activate();
_texture->bind();
_programObject->setUniform("texture1", unit);
ghoul::opengl::TextureUnit unitBump;
unitBump.activate();
_bumpMap->bind();
//_programObject->setUniform("texture2", unitBump);
_geometry->render();
// disable shader
@@ -223,12 +214,34 @@ void RenderableModel::render(const RenderData& data) {
}
void RenderableModel::update(const UpdateData& data) {
double _time = data.time;
double futureTime;
if (_isGhost){
futureTime = openspace::ImageSequencer2::ref().getNextCaptureTime();
double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - data.time;
double interval = openspace::ImageSequencer2::ref().getIntervalLength();
double t = 1.f - remaining / openspace::ImageSequencer2::ref().getIntervalLength();
if (interval > 60){
if (t < 0.8){
_fading = t;
}
else if (t >= 0.95f){
_fading = _fading - 0.5f;
}
}
else{
_fading = 0.0f;
}
_time = futureTime;
}
// set spice-orientation in accordance to timestamp
if (!_source.empty())
openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _destination, data.time, _stateMatrix);
openspace::SpiceManager::ref().getPositionTransformMatrix(_source, _destination, _time, _stateMatrix);
double lt;
openspace::SpiceManager::ref().getTargetPosition("SUN", _source, "GALACTIC", "NONE", data.time, _sunPosition, lt);
openspace::SpiceManager::ref().getTargetPosition("SUN", _target, "GALACTIC", "NONE", _time, _sunPosition, lt);
}
void RenderableModel::loadTexture() {
@@ -241,16 +254,6 @@ void RenderableModel::loadTexture() {
_texture->uploadTexture();
}
}
delete _bumpMap;
_bumpMap = nullptr;
if (_bumpTexturePath.value() != "") {
_bumpMap = ghoul::io::TextureReader::ref().loadTexture(absPath(_bumpTexturePath));
if (_bumpMap) {
LDEBUG("Loaded texture from '" << absPath(_bumpTexturePath) << "'");
_bumpMap->uploadTexture();
}
}
}
} // namespace openspace
+9 -186
View File
@@ -25,20 +25,12 @@
#include <openspace/rendering/model/wavefrontgeometry.h>
#include <openspace/util/constants.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include "ghoul/logging/logmanager.h"
#include <fstream>
#include <numeric>
#include <tiny_obj_loader.h>
namespace {
const std::string _loggerCat = "WavefrontGeometry";
const std::string keyEnabled = "StartsEnabled";
const std::string keyObjFile = "ObjFile";
const int8_t CurrentCacheVersion = 3;
}
@@ -46,104 +38,18 @@ namespace openspace {
namespace modelgeometry {
WavefrontGeometry::WavefrontGeometry(const ghoul::Dictionary& dictionary)
: ModelGeometry()
: ModelGeometry(dictionary)
{
using constants::scenegraphnode::keyName;
std::string name;
bool success = dictionary.getValue(keyName, name);
ghoul_assert(success, "Name tag was not present");
std::string file;
success = dictionary.getValue(keyObjFile, file);
if (!success) {
LERROR("WaveFrontGeometry of '" << name << "' did not provide a key '"
<< keyObjFile << "'");
}
file = FileSys.absolutePath(file);
if (FileSys.fileExists(file, true))
loadObj(file);
else
LERROR("Could not load OBJ file '" << file << "': File not found");
}
bool WavefrontGeometry::loadObj(const std::string& filename){
std::string cachedFile = "";
FileSys.cacheManager()->getCachedFile(filename, cachedFile, true);
bool hasCachedFile = FileSys.fileExists(cachedFile);
if (hasCachedFile) {
LINFO("Cached file '" << cachedFile << "' used for Model file '" << filename << "'");
bool success = loadCachedFile(cachedFile);
if (success)
return true;
else
FileSys.cacheManager()->removeCacheFile(filename);
// Intentional fall-through to the 'else' computation to generate the cache
// file for the next run
}
else {
LINFO("Cache for Model'" << filename << "' not found");
}
LINFO("Loading OBJ file '" << filename << "'");
bool success = loadModel(filename);
if (!success)
return false;
LINFO("Saving cache");
success = saveCachedFile(cachedFile);
return success;
loadObj(_file);
}
bool WavefrontGeometry::initialize(RenderableModel* parent) {
bool success = ModelGeometry::initialize(parent);
PowerScaledScalar ps = PowerScaledScalar(1.0, 0.0); // will set proper bounding soon.
_parent->setBoundingSphere(ps);
if (_vertices.empty())
return false;
glGenVertexArrays(1, &_vaoID);
glGenBuffers(1, &_vbo);
glGenBuffers(1, &_ibo);
glBindVertexArray(_vaoID);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, location)));
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, tex)));
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
reinterpret_cast<const GLvoid*>(offsetof(Vertex, normal)));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices.size() * sizeof(int), _indices.data(), GL_STATIC_DRAW);
glBindVertexArray(0);
return success;
}
void WavefrontGeometry::deinitialize() {
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vaoID);
glDeleteBuffers(1, &_ibo);
}
void WavefrontGeometry::render() {
glBindVertexArray(_vaoID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
ModelGeometry::deinitialize();
}
bool WavefrontGeometry::loadModel(const std::string& filename) {
@@ -188,15 +94,16 @@ bool WavefrontGeometry::loadModel(const std::string& filename) {
_vertices[j + currentPosition].location[0] = shapes[i].mesh.positions[3 * j + 0];
_vertices[j + currentPosition].location[1] = shapes[i].mesh.positions[3 * j + 1];
_vertices[j + currentPosition].location[2] = shapes[i].mesh.positions[3 * j + 2];
_vertices[j + currentPosition].location[3] = 5;
_vertices[j + currentPosition].location[3] = 5; // Temp size for the power scale coordinate.
// Could be defined per object as a dictionary key.
_vertices[j + currentPosition].normal[0] = shapes[i].mesh.normals[3 * j + 0];
_vertices[j + currentPosition].normal[1] = shapes[i].mesh.normals[3 * j + 1];
_vertices[j + currentPosition].normal[2] = shapes[i].mesh.normals[3 * j + 2];
if (2 * j + 1 < shapes[i].mesh.texcoords.size()) {
_vertices[j + currentPosition].tex[0] = shapes[0].mesh.texcoords[2 * j + 0];
_vertices[j + currentPosition].tex[1] = shapes[0].mesh.texcoords[2 * j + 1];
_vertices[j + currentPosition].tex[0] = shapes[i].mesh.texcoords[2 * j + 0];
_vertices[j + currentPosition].tex[1] = shapes[i].mesh.texcoords[2 * j + 1];
}
}
@@ -209,94 +116,10 @@ bool WavefrontGeometry::loadModel(const std::string& filename) {
);
p += shapes[i].mesh.indices.size();
}
/*
std::cout << _vertices.size() << " " << shapes[0].mesh.texcoords.size() << std::endl;
const size_t face_count = shapes[0].mesh.indices.size() / 3;
for (size_t f = 0; f < face_count; f++)
{
int vertex_index_list[3];
vertex_index_list[0] = shapes[0].mesh.indices[f * 3 + 0];
vertex_index_list[1] = shapes[0].mesh.indices[f * 3 + 1];
vertex_index_list[2] = shapes[0].mesh.indices[f * 3 + 2];
const int face[] = {
vertex_index_list[0],
vertex_index_list[1],
vertex_index_list[2]
};
if (!shapes[0].mesh.texcoords.empty())
{
for (int k = 0; k < 3; k++)
{
const int vi = face[k];
if (vi*2+1 < shapes[0].mesh.texcoords.size()){
_vertices[vi].tex[0] = shapes[0].mesh.texcoords[2 * vi + 0];
_vertices[vi].tex[1] = shapes[0].mesh.texcoords[2 * vi + 1];
}
}
}
}
*/
return true;
return true;
}
bool WavefrontGeometry::saveCachedFile(const std::string& filename) {
std::ofstream fileStream(filename, std::ofstream::binary);
if (fileStream.good()) {
fileStream.write(reinterpret_cast<const char*>(&CurrentCacheVersion),
sizeof(int8_t));
int64_t vSize = _vertices.size();
fileStream.write(reinterpret_cast<const char*>(&vSize), sizeof(int64_t));
int64_t iSize = _indices.size();
fileStream.write(reinterpret_cast<const char*>(&iSize), sizeof(int64_t));
fileStream.write(reinterpret_cast<const char*>(_vertices.data()), sizeof(Vertex) * vSize);
fileStream.write(reinterpret_cast<const char*>(_indices.data()), sizeof(int) * iSize);
return fileStream.good();
}
else {
LERROR("Error opening file '" << filename << "' for save cache file");
return false;
}
}
bool WavefrontGeometry::loadCachedFile(const std::string& filename) {
std::ifstream fileStream(filename, std::ifstream::binary);
if (fileStream.good()) {
int8_t version = 0;
fileStream.read(reinterpret_cast<char*>(&version), sizeof(int8_t));
if (version != CurrentCacheVersion) {
LINFO("The format of the cached file has changed, deleting old cache");
fileStream.close();
FileSys.deleteFile(filename);
return false;
}
int64_t vSize, iSize;
fileStream.read(reinterpret_cast<char*>(&vSize), sizeof(int64_t));
fileStream.read(reinterpret_cast<char*>(&iSize), sizeof(int64_t));
_vertices.resize(vSize);
_indices.resize(iSize);
fileStream.read(reinterpret_cast<char*>(_vertices.data()), sizeof(Vertex) * vSize);
fileStream.read(reinterpret_cast<char*>(_indices.data()), sizeof(int) * iSize);
return fileStream.good();
}
else {
LERROR("Error opening file '" << filename << "' for loading cache file");
return false;
}
}
} // namespace modelgeometry
} // namespace openspace
+62 -23
View File
@@ -56,20 +56,25 @@ namespace openspace {
RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _colorTexturePath("colorTexture", "Color Texture")
, _nightTexturePath("")
, _programObject(nullptr)
, _texture(nullptr)
, _nightTexture(nullptr)
, _geometry(nullptr)
, _performShading("performShading", "Perform Shading", true)
, _rotation("rotation", "Rotation", 0, 0, 360)
, _hasNightTexture(false)
, _alpha(1.f)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
ghoul_assert(success,
"RenderablePlanet need the '" <<constants::scenegraphnode::keyName<<"' be specified");
std::string path;
success = dictionary.getValue(constants::scenegraph::keyPathModule, path);
ghoul_assert(success,
"RenderablePlanet need the '"<<constants::scenegraph::keyPathModule<<"' be specified");
std::string path;
success = dictionary.getValue(constants::scenegraph::keyPathModule, path);
//ghoul_assert(success,
// "RenderablePlanet need the '"<<constants::scenegraph::keyPathModule<<"' be specified");
ghoul::Dictionary geometryDictionary;
success = dictionary.getValue(keyGeometry, geometryDictionary);
@@ -80,9 +85,9 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
}
dictionary.getValue(keyFrame, _frame);
dictionary.getValue(keyBody, _target);
//assert(b1 == true);
if (_target != "")
setBody(_target);
// TODO: textures need to be replaced by a good system similar to the geometry as soon
// as the requirements are fixed (ab)
@@ -90,7 +95,16 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
success = dictionary.getValue("Textures.Color", texturePath);
_colorTexturePath = absPath(texturePath);
if (success)
_colorTexturePath = path + "/" + texturePath;
_colorTexturePath = path + "/" + texturePath;
std::string nightTexturePath = "";
dictionary.getValue("Textures.Night", nightTexturePath);
if (nightTexturePath != ""){
_hasNightTexture = true;
_nightTexturePath = absPath(nightTexturePath);
_nightTexturePath = path + "/" + nightTexturePath;
}
addPropertySubOwner(_geometry);
@@ -104,14 +118,18 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
}
addProperty(_performShading);
// Mainly for debugging purposes @AA
addProperty(_rotation);
}
RenderablePlanet::~RenderablePlanet() {
}
bool RenderablePlanet::initialize() {
if (_programObject == nullptr)
OsEng.ref().configurationManager()->getValue("pscShader", _programObject);
if (_programObject == nullptr && _hasNightTexture)
OsEng.ref().configurationManager()->getValue("nightTextureProgram", _programObject);
else if (_programObject == nullptr)
OsEng.ref().configurationManager()->getValue("pscShader", _programObject);
loadTexture();
_geometry->initialize(this);
@@ -124,11 +142,14 @@ bool RenderablePlanet::deinitialize() {
_geometry->deinitialize();
delete _geometry;
}
if(_texture)
if (_texture)
delete _texture;
if (_nightTexture)
delete _nightTexture;
_geometry = nullptr;
_texture = nullptr;
_nightTexture = nullptr;
return true;
}
@@ -150,17 +171,15 @@ void RenderablePlanet::render(const RenderData& data)
//earth needs to be rotated for that to work.
glm::mat4 rot = glm::rotate(transform, 90.f, glm::vec3(1, 0, 0));
glm::mat4 roty = glm::rotate(transform, 90.f, glm::vec3(0, -1, 0));
glm::mat4 rotProp = glm::rotate(transform, static_cast<float>(_rotation), glm::vec3(0, 1, 0));
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
transform[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
transform = transform* rot;
if (_frame == "IAU_JUPITER"){ //x = 0.935126
transform *= glm::scale(glm::mat4(1), glm::vec3(1, 0.93513, 1));
}
transform = transform * rot * roty * rotProp;
//glm::mat4 modelview = data.camera.viewMatrix()*data.camera.modelMatrix();
//glm::vec3 camSpaceEye = (-(modelview*data.position.vec4())).xyz;
@@ -171,6 +190,7 @@ void RenderablePlanet::render(const RenderData& data)
// setup the data to the shader
// _programObject->setUniform("camdir", camSpaceEye);
_programObject->setUniform("transparency", _alpha);
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject, &data.camera, data.position);
@@ -178,11 +198,18 @@ void RenderablePlanet::render(const RenderData& data)
_programObject->setUniform("_performShading", _performShading);
// Bind texture
ghoul::opengl::TextureUnit unit;
unit.activate();
ghoul::opengl::TextureUnit dayUnit;
dayUnit.activate();
_texture->bind();
_programObject->setUniform("texture1", unit);
_programObject->setUniform("texture1", dayUnit);
// Bind possible night texture
if (_hasNightTexture) {
ghoul::opengl::TextureUnit nightUnit;
nightUnit.activate();
_nightTexture->bind();
_programObject->setUniform("nightTex", nightUnit);
}
// render
_geometry->render();
@@ -199,16 +226,28 @@ void RenderablePlanet::update(const UpdateData& data){
void RenderablePlanet::loadTexture() {
delete _texture;
_texture = nullptr;
if (_colorTexturePath.value() != "") {
_texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath));
if (_texture) {
LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'");
if (_colorTexturePath.value() != "") {
_texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath));
if (_texture) {
LDEBUG("Loaded texture from '" << _colorTexturePath << "'");
_texture->uploadTexture();
// Textures of planets looks much smoother with AnisotropicMipMap rather than linear
_texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
}
}
if (_hasNightTexture) {
delete _nightTexture;
_nightTexture = nullptr;
if (_nightTexturePath != "") {
_nightTexture = ghoul::io::TextureReader::ref().loadTexture(absPath(_nightTexturePath));
if (_nightTexture) {
LDEBUG("Loaded texture from '" << _nightTexturePath << "'");
_nightTexture->uploadTexture();
_nightTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
}
}
}
}
} // namespace openspace
@@ -85,14 +85,14 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
: Renderable(dictionary)
, _colorTexturePath("planetTexture", "RGB Texture")
, _projectionTexturePath("projectionTexture", "RGB Texture")
, _imageTrigger("clearProjections", "Clear Projections")
//, _sequencer(nullptr)
, _fadeProjection("fadeProjections", "Image Fading Factor", 0.f, 0.f, 1.f)
, _programObject(nullptr)
, _fboProgramObject(nullptr)
, _texture(nullptr)
, _textureProj(nullptr)
, _textureOriginal(nullptr)
, _geometry(nullptr)
, _sequenceID(-1)
, _rotation("rotation", "Rotation", 0, 0, 360)
, _once(false)
{
std::string name;
@@ -114,11 +114,14 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
_geometry = planetgeometryprojection::PlanetGeometryProjection::createFromDictionary(geometryDictionary);
}
dictionary.getValue(keyFrame, _target);
dictionary.getValue(keyFrame, _frame);
dictionary.getValue(keyBody, _target);
if (_target != "")
setBody(_target);
bool b1 = dictionary.getValue(keyInstrument, _instrumentID);
bool b2 = dictionary.getValue(keyProjObserver, _projectorID);
bool b3 = dictionary.getValue(keyProjTarget, _projecteeID);
bool b1 = dictionary.getValue(keyInstrument, _instrumentID);
bool b2 = dictionary.getValue(keyProjObserver, _projectorID);
bool b3 = dictionary.getValue(keyProjTarget, _projecteeID);
bool b4 = dictionary.getValue(keyProjAberration, _aberration);
bool b5 = dictionary.getValue(keyInstrumentFovy, _fovy);
bool b6 = dictionary.getValue(keyInstrumentAspect, _aspectRatio);
@@ -158,9 +161,8 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
_projectionTexturePath = path + "/" + texturePath;
}
addPropertySubOwner(_geometry);
addProperty(_imageTrigger);
_imageTrigger.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this));
addProperty(_rotation);
addProperty(_fadeProjection);
addProperty(_colorTexturePath);
_colorTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this));
@@ -181,34 +183,22 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary&
//get translation dictionary
dictionary.getValue(keyTranslation, translationDictionary);
if (_sequenceType == sequenceTypePlaybook){
// eeh to many inputs, bit ugly. beautify later.
parser = new HongKangParser(_sequenceSource,
"NEW HORIZONS",
translationDictionary,
_potentialTargets);
openspace::ImageSequencer2::ref().runSequenceParser(parser);
}
/*else if (_sequenceType == sequenceTypeImage){
else if (_sequenceType == sequenceTypeImage){
parser = new LabelParser(_sequenceSource, translationDictionary);
}*/
openspace::ImageSequencer2::ref().runSequenceParser(parser);
}
}
else{
LWARNING("No playbook translation provided, please make sure all spice calls match playbook!");
}
/*if (_sequenceType == sequenceTypeImage) {
LWARNING("LOADING STUFF FOR JUPITER!");
//openspace::ImageSequencer::ref().loadSequence(_sequenceSource, _sequenceID);
// SequenceParser *parser = new LabelParser(_sequenceSource,
//"NEW HORIZONS",
//_fileTranslation,
//_potentialTargets);
//openspace::ImageSequencer2::ref().runSequenceParser(parser);
}*/
/*else*/ if (_sequenceType == sequenceTypePlaybook) {
openspace::ImageSequencer2::ref().runSequenceParser(parser);
}
}
}
@@ -311,6 +301,13 @@ void RenderablePlanetProjection::imageProjectGPU(){
unitFbo.activate();
_textureProj->bind();
_fboProgramObject->setUniform("texture1" , unitFbo);
ghoul::opengl::TextureUnit unitFbo2;
unitFbo2.activate();
_textureOriginal->bind();
_fboProgramObject->setUniform("texture2", unitFbo2);
_fboProgramObject->setUniform("projectionFading", _fadeProjection);
_fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix);
_fboProgramObject->setUniform("ModelTransform" , _transform);
_fboProgramObject->setUniform("_scaling" , _camScaling);
@@ -318,8 +315,8 @@ void RenderablePlanetProjection::imageProjectGPU(){
if (_geometry->hasProperty("radius")){
boost::any r = _geometry->property("radius")->get();
if (glm::vec2* radius = boost::any_cast<glm::vec2>(&r)){
_fboProgramObject->setUniform("radius", radius[0]);
if (glm::vec4* radius = boost::any_cast<glm::vec4>(&r)){
_fboProgramObject->setUniform("radius", radius);
}
}else{
LERROR("Geometry object needs to provide radius");
@@ -344,7 +341,7 @@ void RenderablePlanetProjection::imageProjectGPU(){
m_viewport[2], m_viewport[3]);
}
#include <math.h>
glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc, glm::dvec3 aim, const glm::vec3 up){
//rotate boresight into correct alignment
_boresight = _instrumentMatrix*aim;
@@ -370,21 +367,22 @@ glm::mat4 RenderablePlanetProjection::computeProjectorMatrix(const glm::vec3 loc
void RenderablePlanetProjection::attitudeParameters(double time){
// precomputations for shader
openspace::SpiceManager::ref().getPositionTransformMatrix(_target, _mainFrame, time, _stateMatrix);
openspace::SpiceManager::ref().getPositionTransformMatrix(_frame, _mainFrame, time, _stateMatrix);
openspace::SpiceManager::ref().getPositionTransformMatrix(_instrumentID, _mainFrame, time, _instrumentMatrix);
_transform = glm::mat4(1);
//90 deg rotation w.r.t spice req.
glm::mat4 rot = glm::rotate(_transform, 90.f, glm::vec3(1, 0, 0));
glm::mat4 roty = glm::rotate(_transform, 90.f, glm::vec3(0, -1, 0));
glm::mat4 rotProp = glm::rotate(_transform, static_cast<float>(_rotation), glm::vec3(0, 1, 0));
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
_transform[i][j] = _stateMatrix[i][j];
_transform[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
_transform = _transform* rot;
if (_target == "IAU_JUPITER"){ // tmp solution scale of jupiterX = 0.935126
_transform *= glm::scale(glm::mat4(1), glm::vec3(1, 0.935126, 1));
}
_transform = _transform * rot * roty * rotProp;
std::string shape, instrument;
std::vector<glm::dvec3> bounds;
glm::dvec3 bs;
@@ -395,7 +393,6 @@ void RenderablePlanetProjection::attitudeParameters(double time){
psc position; //observer target
found = SpiceManager::ref().getTargetPosition(_projectorID, _projecteeID, _mainFrame, _aberration, time, position, lightTime);
//if (!found) LERROR("Could not locate target position");
//change to KM and add psc camera scaling.
position[3] += (3 + _camScaling[1]);
@@ -414,9 +411,9 @@ void RenderablePlanetProjection::render(const RenderData& data){
#ifdef GPU_PROJ
if (_capture){
for (auto imgSubset : _imageTimes){
attitudeParameters(imgSubset.first); // projector viewmatrix
_projectionTexturePath = imgSubset.second; // path to current images
for (auto img : _imageTimes){
attitudeParameters(img.startTime); // compute projector viewmatrix
_projectionTexturePath = img.path; // path to current images
imageProjectGPU(); //fbopass
}
_capture = false;
@@ -438,7 +435,7 @@ void RenderablePlanetProjection::render(const RenderData& data){
_programObject->setUniform("ModelTransform" , _transform);
_programObject->setUniform("boresight" , _boresight);
setPscUniforms(_programObject, &data.camera, data.position);
// Bind texture
ghoul::opengl::TextureUnit unit[2];
unit[0].activate();
@@ -447,6 +444,7 @@ void RenderablePlanetProjection::render(const RenderData& data){
unit[1].activate();
_textureProj->bind();
_programObject->setUniform("texture2", unit[1]);
// render geometry
_geometry->render();
// disable shader
@@ -457,13 +455,13 @@ void RenderablePlanetProjection::update(const UpdateData& data){
// set spice-orientation in accordance to timestamp
_time = data.time;
_capture = false;
if (openspace::ImageSequencer2::ref().isReady()){
openspace::ImageSequencer2::ref().updateSequencer(_time);
_capture = openspace::ImageSequencer2::ref().getImagePaths(_imageTimes, _projecteeID, _instrumentID);
}
//floor fading to decimal
//_fadeProjection = floorf(_fadeProjection * 10) / 10;
}
void RenderablePlanetProjection::loadProjectionTexture(){
@@ -477,7 +475,6 @@ void RenderablePlanetProjection::loadProjectionTexture(){
_textureProj->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder);
}
}
//_sequencer->sequenceReset();
}
void RenderablePlanetProjection::loadTexture(){
@@ -490,5 +487,14 @@ void RenderablePlanetProjection::loadTexture(){
_texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
}
}
delete _textureOriginal;
_textureOriginal = nullptr;
if (_colorTexturePath.value() != "") {
_textureOriginal = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath));
if (_textureOriginal) {
_textureOriginal->uploadTexture();
_textureOriginal->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
}
}
}
} // namespace openspace
+23 -16
View File
@@ -43,8 +43,8 @@ namespace planetgeometry {
SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary)
: PlanetGeometry()
, _radius("radius", "Radius", glm::vec2(1.f, 0.f), glm::vec2(-10.f, -20.f),
glm::vec2(10.f, 20.f))
, _realRadius("radius", "Radius", glm::vec4(1.f, 1.f, 1.f, 0.f), glm::vec4(-10.f, -10.f, -10.f, -20.f),
glm::vec4(10.f, 10.f, 10.f, 20.f))
, _segments("segments", "Segments", 20, 1, 50)
, _sphere(nullptr)
{
@@ -53,30 +53,37 @@ SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary)
using constants::simplespheregeometry::keySegments;
// The name is passed down from the SceneGraphNode
std::string name;
bool success = dictionary.getValue(keyName, name);
bool success = dictionary.getValue(keyName, _name);
assert(success);
glm::vec2 radius;
success = dictionary.getValue(keyRadius, radius);
glm::vec4 radius;
success = dictionary.getValue(keyRadius, _modRadius);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keyRadius << "'");
}
else
_radius = radius;
else {
radius[0] = _modRadius[0];
radius[1] = _modRadius[0];
radius[2] = _modRadius[0];
radius[3] = _modRadius[1];
_realRadius = radius; // In case the kernels does not supply a real
}
double segments;
success = dictionary.getValue(keySegments, segments);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keySegments << "'");
}
else
_segments = static_cast<int>(segments);
addProperty(_radius);
_radius.onChange(std::bind(&SimpleSphereGeometry::createSphere, this));
// The shader need the radii values but they are not changeable runtime
// TODO: Possibly add a scaling property @AA
addProperty(_realRadius);
// Changing the radius/scaling should affect the shader but not the geometry? @AA
//_radius.onChange(std::bind(&SimpleSphereGeometry::createSphere, this));
addProperty(_segments);
_segments.onChange(std::bind(&SimpleSphereGeometry::createSphere, this));
}
@@ -107,13 +114,13 @@ void SimpleSphereGeometry::render()
void SimpleSphereGeometry::createSphere(){
//create the power scaled scalar
PowerScaledScalar planetSize(_radius);
PowerScaledScalar planetSize(_modRadius);
_parent->setBoundingSphere(planetSize);
if(_sphere)
delete _sphere;
_sphere = new PowerScaledSphere(planetSize, _segments);
//_sphere = new PowerScaledSphere(planetSize, _segments);
_sphere = new PowerScaledSphere(_realRadius, _segments, _name);
_sphere->initialize();
}
@@ -42,8 +42,8 @@ namespace planetgeometryprojection {
SimpleSphereGeometryProjection::SimpleSphereGeometryProjection(const ghoul::Dictionary& dictionary)
: PlanetGeometryProjection()
, _radius("radius", "Radius", glm::vec2(1.f, 0.f), glm::vec2(-10.f, -20.f),
glm::vec2(10.f, 20.f))
, _realRadius("radius", "Radius", glm::vec4(1.f, 1.f, 1.f, 0.f), glm::vec4(-10.f, -10.f, -10.f, -20.f),
glm::vec4(10.f, 10.f, 10.f, 20.f))
, _segments("segments", "Segments", 20, 1, 1000)
, _vaoID("vaoID", "Vao", 1, 1, 1)
, _vBufferID("vboID", "Vbo", 1, 1, 1)
@@ -55,30 +55,37 @@ SimpleSphereGeometryProjection::SimpleSphereGeometryProjection(const ghoul::Dict
using constants::simplespheregeometryprojection::keySegments;
// The name is passed down from the SceneGraphNode
std::string name;
bool success = dictionary.getValue(keyName, name);
bool success = dictionary.getValue(keyName, _name);
assert(success);
glm::vec2 radius;
success = dictionary.getValue(keyRadius, radius);
// removing "Projection"-suffix from name for SPICE compability, TODO: better solution @AA
if(_name.find("Projection"))
_name = _name.substr(0, _name.size() - 10);
glm::vec4 radius;
success = dictionary.getValue(keyRadius, _modRadius);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keyRadius << "'");
}
else
_radius = radius;
else {
radius[0] = _modRadius[0];
radius[1] = _modRadius[0];
radius[2] = _modRadius[0];
radius[3] = _modRadius[1];
_realRadius = radius;
}
double segments;
success = dictionary.getValue(keySegments, segments);
if (!success) {
LERROR("SimpleSphereGeometry of '" << name << "' did not provide a key '"
LERROR("SimpleSphereGeometry of '" << _name << "' did not provide a key '"
<< keySegments << "'");
}
else
_segments = static_cast<int>(segments);
addProperty(_radius);
_radius.onChange(std::bind(&SimpleSphereGeometryProjection::createSphere, this));
addProperty(_realRadius);
//_realRadius.onChange(std::bind(&SimpleSphereGeometryProjection::createSphere, this));
addProperty(_segments);
_segments.onChange(std::bind(&SimpleSphereGeometryProjection::createSphere, this));
}
@@ -117,12 +124,12 @@ void SimpleSphereGeometryProjection::createSphere()
{
//create the power scaled scalar
PowerScaledScalar planetSize(_radius);
PowerScaledScalar planetSize(_modRadius);
_parent->setBoundingSphere(planetSize);
delete _planet;
_planet = new PowerScaledSphere(planetSize, _segments);
_planet->initialize();
_planet = new PowerScaledSphere(_realRadius, _segments, _name);
_planet->initialize();
}
} // namespace planetgeometry
+48 -1
View File
@@ -27,6 +27,7 @@
#include <openspace/util/constants.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/updatestructures.h>
#include <openspace/util/spicemanager.h>
// ghoul
#include <ghoul/misc/dictionary.h>
@@ -36,6 +37,9 @@
namespace {
const std::string _loggerCat = "Renderable";
const std::string keyBody = "Body";
const std::string keyStart = "StartTime";
const std::string keyEnd = "EndTime";
}
namespace openspace {
@@ -67,7 +71,12 @@ Renderable* Renderable::createFromDictionary(const ghoul::Dictionary& dictionary
}
Renderable::Renderable(const ghoul::Dictionary& dictionary)
: _enabled("enabled", "Is Enabled", true)
: _enabled("enabled", "Is Enabled", true),
_hasTimeInterval(false),
_startTime(""),
_endTime(""),
_targetBody(""),
_hasBody(false)
{
setName("renderable");
#ifndef NDEBUG
@@ -86,6 +95,12 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
if (success)
_relativePath += ghoul::filesystem::FileSystem::PathSeparator;
dictionary.getValue(keyStart, _startTime);
dictionary.getValue(keyEnd, _endTime);
if (_startTime != "" && _endTime != "")
_hasTimeInterval = true;
addProperty(_enabled);
}
@@ -135,6 +150,38 @@ bool Renderable::isVisible() const {
return _enabled;
}
bool Renderable::hasTimeInterval() {
return _hasTimeInterval;
}
bool Renderable::hasBody() {
return _hasBody;
}
bool Renderable::getInterval(double& start, double& end) {
if (_startTime != "" && _endTime != "") {
bool successStart = openspace::SpiceManager::ref().getETfromDate(_startTime, start);
bool successEnd = openspace::SpiceManager::ref().getETfromDate(_endTime, end);
return successStart && successEnd;
}
else
return false;
}
bool Renderable::getBody(std::string& body) {
if (_hasBody) {
body = _targetBody;
return true;
}
else
return false;
}
void Renderable::setBody(std::string& body) {
_targetBody = body;
_hasBody = true;
}
bool Renderable::isReady() const {
return true;
}
+38 -15
View File
@@ -29,7 +29,6 @@
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/imagesequencer.h>
#include <openspace/util/imagesequencer2.h> // testing
#include <openspace/util/time.h>
@@ -72,6 +71,7 @@ namespace openspace{
, _lineWidth("lineWidth", "Line Width", 1.f, 1.f, 20.f)
, _programObject(nullptr)
, _texture(nullptr)
, _drawSolid("solidDraw", "Draw as Quads", false)
, _mode(GL_LINES){
bool success = dictionary.getValue(keyBody, _spacecraft);
@@ -101,6 +101,7 @@ namespace openspace{
}
addProperty(_lineWidth);
addProperty(_drawSolid);
}
void RenderableFov::allocateData(){
@@ -123,7 +124,7 @@ void RenderableFov::allocateData(){
_vtotal[0] = static_cast<int>(_vsize[0] / _stride[0]);
// allocate second vbo data
int cornerPoints = 6;
int cornerPoints = 12;
_isize[1] = cornerPoints;
_iarray1[1] = new int[_isize[1]];
for (int i = 0; i < _isize[1]; i++){
@@ -293,8 +294,8 @@ void RenderableFov::fovProjection(bool H[], std::vector<glm::dvec3> bounds){
glm::dvec3 next;
glm::vec4 tmp(1);
if (bounds.size() > 1){
for (int i = 0; i < 4; i++){
int k = (i + 1 > 4 - 1) ? 0 : i + 1;
for (int i = 0; i < bounds.size(); i++){
int k = (i + 1 > bounds.size() - 1) ? 0 : i + 1;
current = bounds[i];
next = bounds[k];
@@ -306,8 +307,6 @@ void RenderableFov::fovProjection(bool H[], std::vector<glm::dvec3> bounds){
mid = bisection(current, next, tolerance);
for (int j = 1; j <= _isteps; j++){
t = ((double)j / _isteps);
// TODO: change the interpolate scheme to place points not on a straight line but instead
// using either slerp or some other viable method (goal: eliminate checkForIntercept -method)
interpolated = interpolate(current, mid, t);
_interceptVector = (j < _isteps) ? checkForIntercept(interpolated) : orthogonalProjection(interpolated);
insertPoint(_varray2, _interceptVector, col_sq);
@@ -334,7 +333,8 @@ void RenderableFov::fovProjection(bool H[], std::vector<glm::dvec3> bounds){
}
if (_nrInserted == 0){
_rebuild = false;
}else{
}
else {
_rebuild = true;
//update size etc;
_vtotal[1] = _nrInserted;
@@ -383,7 +383,7 @@ void RenderableFov::computeColors(){
c_project = glm::vec4(0.0, 1.0, 0.00,1);
col_end = glm::vec4(1.00, 0.29, 0.00, 1);
blue = glm::vec4(0, 0.5, 0.7, 1);
col_gray = glm::vec4(0.5, 0.5, 0.5, 0.5);
col_gray = glm::vec4(0.7);
col_start = glm::vec4(1.00, 0.89, 0.00, 1);
col_sq = glm::vec4(1.00, 0.29, 0.00, 1);
@@ -416,18 +416,18 @@ void RenderableFov::render(const RenderData& data){
spacecraftRot[i][j] = _stateMatrix[i][j];
}
}
bool drawFOV = false;
// setup the data to the shader
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
setPscUniforms(_programObject, &data.camera, data.position);
bool drawFOV = false;
if (openspace::ImageSequencer2::ref().isReady()){
drawFOV = ImageSequencer2::ref().instumentActive(_instrumentID);
}
if (drawFOV){
// update only when time progresses.
if (_oldTime != _time){
@@ -465,8 +465,9 @@ void RenderableFov::render(const RenderData& data){
double targetEpoch;
// for each FOV vector
for (int i = 0; i <= bounds.size(); i++){
// compute surface intercept
int r = (i == bounds.size()) ? 0 : i;
// compute surface intercept
openspace::SpiceManager::ref().getSurfaceIntercept(_fovTarget, _spacecraft, _instrumentID,
_frame, _method, _aberrationCorrection,
_time, targetEpoch, bounds[r], ipoint, ivec, _interceptTag[r]);
@@ -513,15 +514,38 @@ void RenderableFov::render(const RenderData& data){
}
}
_interceptTag[4] = _interceptTag[0];
fovProjection(_interceptTag, bounds);
_interceptTag[bounds.size()] = _interceptTag[0];
if (!(_instrumentID == "NH_LORRI")) // image plane replaces fov square
fovProjection(_interceptTag, bounds);
updateData();
glm::vec3 aim = (spacecraftRot * glm::vec4(boresight, 1)).xyz;
psc position;
double lt;
SpiceManager::ref().getTargetPosition(_fovTarget,
_spacecraft,
_frame,
_aberrationCorrection,
_time,
position,
lt);
//if aimed 80 deg away from target, dont draw white square
if (glm::dot(glm::normalize(aim), glm::normalize(position.vec3())) < 0.2){
drawFOV = false;
}
}
_oldTime = _time;
if (!_drawSolid) _mode = GL_LINES;
else _mode = GL_TRIANGLE_STRIP;
glLineWidth(_lineWidth);
glBindVertexArray(_vaoID[0]);
glDrawArrays(GL_LINES, 0, _vtotal[0]);
glDrawArrays(_mode, 0, _vtotal[0]);
glBindVertexArray(0);
glLineWidth(_lineWidth);
@@ -529,7 +553,6 @@ void RenderableFov::render(const RenderData& data){
glDrawArrays(GL_LINES, 0, _vtotal[0]);
glBindVertexArray(0);
//second vbo
if (drawFOV){
glLineWidth(1.f);
glBindVertexArray(_vaoID[1]);
+3 -3
View File
@@ -83,7 +83,7 @@ bool RenderablePath::fullYearSweep(){
double lightTime = 0.0;
SpiceManager::ref().getETfromDate("2006 jan 20 19:00:00", _time);
std::cout << _time << std::endl;
//std::cout << _time << std::endl;
// -------------------------------------- ^ this has to be simulation start-time, not passed in here though --
//SpiceManager::ref().getETfromDate("2008 apr 01 00:00:00", et2);
@@ -100,7 +100,7 @@ bool RenderablePath::fullYearSweep(){
int indx = 0;
for (int i = 0; i < segments + 1; i++){
std::cout << i << std::endl;
//std::cout << i << std::endl;
bool gotData = SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "LT+S", et, _pscpos, lightTime);
#ifndef NDEBUG
@@ -249,7 +249,7 @@ void RenderablePath::update(const UpdateData& data){
_time = data.time;
_delta = static_cast<int>(data.delta);
SpiceManager::ref().getTargetState(_target, _observer, _frame, "LT+S", data.time, _pscpos, _pscvel, lightTime);
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", data.time, _pscpos, lightTime);
}
+5 -9
View File
@@ -22,6 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/configurationmanager.h>
#include <openspace/rendering/renderableplane.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/powerscaledcoordinate.h>
@@ -125,14 +126,10 @@ bool RenderablePlane::initialize() {
glGenBuffers(1, &_vertexPositionBuffer); // generate buffer
createPlane();
// Plane program
_shader = ghoul::opengl::ProgramObject::Build("Plane",
"${SHADERS}/modules/plane/plane_vs.glsl",
"${SHADERS}/modules/plane/plane_fs.glsl");
if (!_shader)
return false;
_shader->setProgramObjectCallback([&](ghoul::opengl::ProgramObject*){ _programIsDirty = true; });
if (_shader == nullptr)
OsEng.ref().configurationManager()->getValue("planeProgram", _shader);
_shader->setProgramObjectCallback([&](ghoul::opengl::ProgramObject*){ _programIsDirty = true; });
loadTexture();
return isReady();
@@ -144,7 +141,6 @@ bool RenderablePlane::deinitialize() {
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
delete _texture;
delete _shader;
return true;
}
+328
View File
@@ -0,0 +1,328 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/rendering/renderableplaneprojection.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/configurationmanager.h>
#include <openspace/util/constants.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/spicemanager.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/staticephemeris.h>
#include <openspace/scene/dynamicephemeris.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
#include <openspace/util/time.h>
namespace {
const std::string _loggerCat = "RenderablePlaneProjection";
}
namespace openspace {
using namespace constants::renderableplaneprojection;
RenderablePlaneProjection::RenderablePlaneProjection(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _shader(nullptr)
, _programIsDirty(false)
, _texture(nullptr)
, _textureIsDirty(false)
, _quad(0)
, _vertexPositionBuffer(0)
, _name("ImagePlane")
, _texturePath("")
, _planeIsDirty(false)
{
dictionary.getValue(keySpacecraft, _spacecraft);
dictionary.getValue(keyInstrument, _instrument);
dictionary.getValue(keyMoving, _moving);
dictionary.getValue(keyName, _name);
std::string texturePath = "";
bool success = dictionary.getValue(keyTexture, _texturePath);
if (success) {
_texturePath = findPath(_texturePath);
_textureFile = new ghoul::filesystem::File(_texturePath);
}
loadTexture();
}
RenderablePlaneProjection::~RenderablePlaneProjection() {
delete _textureFile;
}
bool RenderablePlaneProjection::isReady() const {
bool ready = true;
if (!_shader)
ready &= false;
if (!_texture)
ready &= false;
return ready;
}
bool RenderablePlaneProjection::initialize() {
glGenVertexArrays(1, &_quad); // generate array
glGenBuffers(1, &_vertexPositionBuffer); // generate buffer
// Plane program
if (_shader == nullptr)
OsEng.ref().configurationManager()->getValue("imagePlaneProgram", _shader);
setTarget("JUPITER");
loadTexture();
return isReady();
}
bool RenderablePlaneProjection::deinitialize() {
glDeleteVertexArrays(1, &_quad);
_quad = 0;
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
delete _texture;
return true;
}
void RenderablePlaneProjection::render(const RenderData& data) {
glm::mat4 transform = glm::mat4(1.0);
for (int i = 0; i < 3; i++){
for (int j = 0; j < 3; j++){
transform[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
// Activate shader
_shader->activate();
_shader->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_shader->setUniform("ModelTransform", transform);
setPscUniforms(_shader, &data.camera, data.position);
data.position;
ghoul::opengl::TextureUnit unit;
unit.activate();
_texture->bind();
_shader->setUniform("texture1", unit);
glBindVertexArray(_quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
_shader->deactivate();
}
void RenderablePlaneProjection::update(const UpdateData& data) {
double time = data.time;
const Image* img = openspace::ImageSequencer2::ref().getLatestImageForInstrument(_instrument);
openspace::SpiceManager::ref().getPositionTransformMatrix(_target.frame, galacticFrame, time, _stateMatrix);
std::string tex = _texturePath;
if (_moving || _planeIsDirty)
updatePlane(img, time);
else if (img != nullptr && img->path != tex) {
time = img->startTime;
updatePlane(img, time);
}
if (_programIsDirty) {
_shader->rebuildFromFile();
_programIsDirty = false;
}
if (_textureIsDirty) {
loadTexture();
_textureIsDirty = false;
}
}
void RenderablePlaneProjection::loadTexture() {
if (_texturePath != "") {
ghoul::opengl::Texture* texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath));
if (texture) {
texture->uploadTexture();
texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap);
if (_texture)
delete _texture;
_texture = texture;
delete _textureFile;
_textureFile = new ghoul::filesystem::File(_texturePath);
_textureFile->setCallback([&](const ghoul::filesystem::File&) { _textureIsDirty = true; });
}
}
}
void RenderablePlaneProjection::updatePlane(const Image* img, double currentTime) {
std::string shape, frame;
std::vector<glm::dvec3> bounds;
glm::dvec3 boresight;
std::string target = "JUPITER"; //default
if (!_moving) {
// target = findClosestTarget(currentTime);
}
if (img != nullptr)
target = img->target;
setTarget(target);
bool found = openspace::SpiceManager::ref().getFieldOfView(_instrument, shape, frame, boresight, bounds);
if (!found) {
LERROR("Could not locate instrument");
return;
}
glm::dvec3 vecToTarget;
double lt;
psc projection[4];
SpiceManager::ref().getTargetPosition(_target.body, _spacecraft, galacticFrame, "CN+S", currentTime, vecToTarget, lt);
// The apparent position, CN+S, makes image align best with target
for (int j = 0; j < bounds.size(); ++j) {
openspace::SpiceManager::ref().frameConversion(bounds[j], frame, galacticFrame, currentTime);
glm::dvec3 cornerPosition = openspace::SpiceManager::ref().orthogonalProjection(vecToTarget, bounds[j]);
if (!_moving) {
cornerPosition -= vecToTarget;
}
openspace::SpiceManager::ref().frameConversion(cornerPosition, galacticFrame, _target.frame, currentTime);
projection[j] = PowerScaledCoordinate::CreatePowerScaledCoordinate(cornerPosition[0], cornerPosition[1], cornerPosition[2]);
projection[j][3] += 3;
}
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);
}
const GLfloat vertex_data[] = { // square of two triangles drawn within fov in target coordinates
// x y z w s t
projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 1
projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper right 2
projection[2][0], projection[2][1], projection[2][2], projection[2][3], 0, 0, // Upper left 3
projection[1][0], projection[1][1], projection[1][2], projection[1][3], 0, 1, // Lower left 4 = 1
projection[0][0], projection[0][1], projection[0][2], projection[0][3], 1, 1, // Lower right 5
projection[3][0], projection[3][1], projection[3][2], projection[3][3], 1, 0, // Upper left 6 = 2
};
glBindVertexArray(_quad); // bind array
glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast<void*>(sizeof(GLfloat) * 4));
if (!_moving && img != nullptr) {
_texturePath = img->path;
loadTexture();
}
}
void RenderablePlaneProjection::setTarget(std::string body) {
if (body == "")
return;
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->scene()->allSceneGraphNodes();
Renderable* possibleTarget;
bool hasBody, found = false;
std::string targetBody;
for (auto node : nodes)
{
possibleTarget = node->renderable();
if (possibleTarget != nullptr) {
hasBody = possibleTarget->hasBody();
if (hasBody && possibleTarget->getBody(targetBody) && (targetBody == body)) {
_target.node = node->name(); // get name from propertyOwner
found = true;
break;
}
}
}
if (found) {
_target.body = body;
_target.frame = openspace::SpiceManager::ref().frameFromBody(body);
}
}
std::string RenderablePlaneProjection::findClosestTarget(double currentTime) {
std::vector<std::string> targets;
std::vector<SceneGraphNode*> nodes = OsEng.renderEngine()->scene()->allSceneGraphNodes();
Renderable* possibleTarget;
std::string targetBody;
bool hasBody, found = false;
PowerScaledScalar min = PowerScaledScalar::CreatePSS(9999999999999);
PowerScaledScalar distance = PowerScaledScalar::CreatePSS(0.0);
std::string closestTarget = "";
psc spacecraftPos;
double lt;
SpiceManager::ref().getTargetPosition(_spacecraft, "SSB", galacticFrame, "NONE", currentTime, spacecraftPos, lt);
for (auto node : nodes)
{
possibleTarget = node->renderable();
if (possibleTarget != nullptr) {
hasBody = possibleTarget->hasBody();
if (hasBody && possibleTarget->getBody(targetBody)) {
openspace::SpiceManager::ref().targetWithinFieldOfView(_instrument, targetBody, _spacecraft, "ELLIPSOID", "NONE", currentTime, found);
if (found){
targets.push_back(node->name()); // get name from propertyOwner
distance = (node->worldPosition() - spacecraftPos).length();
if (distance < min)
closestTarget = targetBody;
}
}
}
}
return closestTarget;
}
} // namespace openspace
+71 -12
View File
@@ -30,6 +30,9 @@
#include <openspace/util/updatestructures.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/misc/highresclock.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/interactionhandler.h>
/* TODO for this class:
* In order to add geometry shader (for pretty-draw),
@@ -40,6 +43,7 @@
namespace {
const std::string _loggerCat = "RenderableTrail";
//constants
const std::string keyName = "Name";
const std::string keyBody = "Body";
const std::string keyObserver = "Observer";
const std::string keyFrame = "Frame";
@@ -48,6 +52,7 @@ namespace {
const std::string keyTropicalOrbitPeriod = "TropicalOrbitPeriod";
const std::string keyEarthOrbitRatio = "EarthOrbitRatio";
const std::string keyDayLength = "DayLength";
const std::string keyStamps = "Timestamps";
}
namespace openspace {
@@ -56,7 +61,7 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _lineColor("lineColor", "Line Color")
, _lineFade("lineFade", "Line Fade", 0.75f, 0.f, 5.f)
, _lineWidth("lineWidth", "Line Width", 1.f, 1.f, 20.f)
, _lineWidth("lineWidth", "Line Width", 2.f, 1.f, 20.f)
, _programObject(nullptr)
, _programIsDirty(true)
, _vaoID(0)
@@ -64,6 +69,7 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
, _oldTime(std::numeric_limits<float>::max())
, _successfullDictionaryFetch(true)
, _needsSweep(true)
, _showTimestamps("timestamps", "Show Timestamps", false)
{
_successfullDictionaryFetch &= dictionary.getValue(keyBody, _target);
_successfullDictionaryFetch &= dictionary.getValue(keyObserver, _observer);
@@ -80,12 +86,17 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
dictionary.getValue(keyColor, color);
_lineColor = color;
if (dictionary.hasKeyAndValue<bool>(keyStamps))
dictionary.getValue(keyStamps, _showTimestamps);
addProperty(_showTimestamps);
_lineColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(_lineColor);
addProperty(_lineFade);
addProperty(_lineWidth);
_distanceFade = 1.0;
}
bool RenderableTrail::initialize() {
@@ -139,6 +150,19 @@ void RenderableTrail::render(const RenderData& data) {
_programObject->setUniform("nVertices", static_cast<unsigned int>(_vertexArray.size()));
_programObject->setUniform("lineFade", _lineFade);
const psc& position = data.camera.position();
const psc& origin = openspace::OpenSpaceEngine::ref().interactionHandler()->focusNode()->worldPosition();
const PowerScaledScalar& pssl = (position - origin).length();
if (pssl[0] < 0.000001){
if (_distanceFade > 0.0f) _distanceFade -= 0.05f;
_programObject->setUniform("forceFade", _distanceFade);
}
else{
if (_distanceFade < 1.0f) _distanceFade += 0.05f;
_programObject->setUniform("forceFade", _distanceFade);
}
glLineWidth(_lineWidth);
glBindVertexArray(_vaoID);
@@ -147,11 +171,18 @@ void RenderableTrail::render(const RenderData& data) {
glLineWidth(1.f);
if (_showTimestamps){
glPointSize(5.f);
glBindVertexArray(_vaoID);
glDrawArrays(GL_POINTS, 0, _vertexArray.size());
glBindVertexArray(0);
}
_programObject->deactivate();
}
void RenderableTrail::update(const UpdateData& data) {
if (data.isTimeJump)
if (data.isTimeJump)
_needsSweep = true;
if (_needsSweep) {
@@ -166,7 +197,14 @@ void RenderableTrail::update(const UpdateData& data) {
_programIsDirty = false;
}
double lightTime = 0.0;
psc pscPos, pscVel;
psc pscPos;
bool intervalSet = hasTimeInterval();
double start = DBL_MIN;
double end = DBL_MAX;
if (intervalSet) {
getInterval(start, end);
}
// Points in the vertex array should always have a fixed distance. For this reason we
// keep the first entry in the array floating and always pointing to the current date
@@ -176,9 +214,13 @@ void RenderableTrail::update(const UpdateData& data) {
int nValues = floor(deltaTime / _increment);
// Update the floating current time
// Is 'CN+S' correct? It has to be chosen to be the same as in SpiceEphemeris, but
// unsure if it is correct ---abock
SpiceManager::ref().getTargetState(_target, _observer, _frame, "NONE", data.time, pscPos, pscVel, lightTime);
if (start > data.time)
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", start, pscPos, lightTime);
else if (end < data.time)
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", end, pscPos, lightTime);
else
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", data.time, pscPos, lightTime);
pscPos[3] += 3; // KM to M
_vertexArray[0] = { pscPos[0], pscPos[1], pscPos[2], pscPos[3] };
@@ -193,8 +235,12 @@ void RenderableTrail::update(const UpdateData& data) {
for (int i = nValues; i > 0; --i) {
double et = _oldTime + i * _increment;
SpiceManager::ref().getTargetState(_target, _observer, _frame, "CN+S", et, pscPos, pscVel, lightTime);
pscPos[3] += 3;
if (start > et)
et = start;
else if (end < et)
et = end;
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", et, pscPos, lightTime);
pscPos[3] += 3;
_vertexArray[i] = { pscPos[0], pscPos[1], pscPos[2], pscPos[3] };
}
@@ -222,15 +268,28 @@ void RenderableTrail::fullYearSweep(double time) {
float planetYear = SecondsPerEarthYear * _ratio;
int segments = static_cast<int>(_tropic);
bool intervalSet = hasTimeInterval();
double start = DBL_MIN;
double end = DBL_MAX;
if (intervalSet) {
getInterval(start, end);
}
_increment = planetYear / _tropic;
_oldTime = time;
psc pscPos, pscVel;
psc pscPos;
bool validPosition = true;
_vertexArray.resize(segments+2);
for (int i = 0; i < segments+2; i++){
SpiceManager::ref().getTargetState(_target, _observer, _frame, "CN+S", time, pscPos, pscVel, lightTime);
pscPos[3] += 3;
for (int i = 0; i < segments+2; i++) {
if (start > time)
time = start;
else if (end < time)
time = end;
SpiceManager::ref().getTargetPosition(_target, _observer, _frame, "NONE", time, pscPos, lightTime);
pscPos[3] += 3;
_vertexArray[i] = {pscPos[0], pscPos[1], pscPos[2], pscPos[3]};
time -= _increment;
+333 -182
View File
@@ -22,9 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/util/imagesequencer.h>
#include <openspace/util/imagesequencer2.h>
@@ -36,7 +35,7 @@
#include <openspace/abuffer/abufferdynamic.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/interaction/interactionhandler.h>
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/scene/scene.h>
#include <openspace/util/camera.h>
#include <openspace/util/constants.h>
#include <openspace/util/time.h>
@@ -61,8 +60,8 @@
#include <sgct.h>
// These are temporary ---abock
#include <openspace/scenegraph/spiceephemeris.h>
#include <openspace/scenegraph/staticephemeris.h>
#include <openspace/scene/spiceephemeris.h>
#include <openspace/scene/staticephemeris.h>
// ABuffer defines
#define ABUFFER_FRAMEBUFFER 0
@@ -433,7 +432,6 @@ namespace openspace {
Time::ref().deltaTime(),
_doPerformanceMeasurements
});
ImageSequencer::ref().update(Time::ref().currentTime());
_sceneGraph->evaluate(_mainCamera);
// clear the abuffer before rendering the scene
@@ -509,60 +507,6 @@ namespace openspace {
sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize);
int startY = ySize - 2 * font_size_mono;
double currentTime = Time::ref().currentTime();
double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - currentTime;
double t = 1.f - remaining / openspace::ImageSequencer::ref().getIntervalLength();
std::string progress = "|";
int g = ((t)* 20) + 1;
for (int i = 0; i < g; i++) progress.append("-"); progress.append(">");
for (int i = 0; i < 21 - g; i++) progress.append(" ");
std::string str = "";
openspace::SpiceManager::ref().getDateFromET(openspace::ImageSequencer::ref().getNextCaptureTime(), str);
Freetype::print(font,
_onScreenInformation._position.x * xSize,
_onScreenInformation._position.y * ySize,
"Date: %s",
Time::ref().currentTimeUTC().c_str()
);
progress.append("|");
if (remaining > 0){
glm::vec4 g1(0, t, 0, 1);
glm::vec4 g2(1 - t);
Freetype::print(font,
_onScreenInformation._position.x * xSize,
_onScreenInformation._position.y * ySize - font_size_mono * 2,
g1 + g2,
"Next projection in | %.0f seconds",
remaining
);
Freetype::print(font,
_onScreenInformation._position.x * xSize,
_onScreenInformation._position.y * ySize - font_size_mono * 2 * 2,
g1 + g2,
"%s %.1f %%",
progress.c_str(), t * 100
);
}
/*std::vector<std::string> instrVec = ImageSequencer2::ref().getActiveInstruments();
std::string active ="";
for (int i = 0; i < instrVec.size(); i++){
active.append(instrVec[i]);
active.append(" ");
}
Freetype::print(font,
_onScreenInformation._position.x * xSize,
_onScreenInformation._position.y * ySize - font_size_mono * 3 * 2,
glm::vec4(0.3, 0.6, 1, 1),
"Active Instrument : %s",
active.c_str()
);*/
}
}
@@ -593,19 +537,21 @@ namespace openspace {
// Using a macro to shorten line length and increase readability
int i = 0;
PrintText(i++, "Date: %s", Time::ref().currentTimeUTC().c_str());
/*
PrintText(i++, "Avg. Frametime: %.5f", sgct::Engine::instance()->getAvgDt());
PrintText(i++, "Drawtime: %.5f", sgct::Engine::instance()->getDrawTime());
PrintText(i++, "Frametime: %.5f", sgct::Engine::instance()->getDt());
/*
PrintText(i++, "Origin: (% .5f, % .5f, % .5f, % .5f)", origin[0], origin[1], origin[2], origin[3]);
PrintText(i++, "Cam pos: (% .5f, % .5f, % .5f, % .5f)", position[0], position[1], position[2], position[3]);
PrintText(i++, "View dir: (% .5f, % .5f, % .5f)", viewdirection[0], viewdirection[1], viewdirection[2]);
PrintText(i++, "Cam->origin: (% .15f, % .4f)", pssl[0], pssl[1]);
PrintText(i++, "Scaling: (% .5f, % .5f)", scaling[0], scaling[1]);
*/
if (openspace::ImageSequencer2::ref().isReady()){
if (openspace::ImageSequencer2::ref().isReady()) {
double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - currentTime;
double t = 1.f - remaining / openspace::ImageSequencer2::ref().getIntervalLength();
std::string progress = "|";
@@ -625,75 +571,65 @@ namespace openspace {
}
glm::vec4 w(1);
PrintColorText(i++, "Ucoming capture : %s", 10, w, str.c_str());
std::pair<double, std::string> nextTarget = ImageSequencer2::ref().getNextTarget();
std::pair<double, std::string> currentTarget = ImageSequencer2::ref().getCurrentTarget();
std::pair<double, std::string> currentTarget = ImageSequencer2::ref().getCurrentTarget();
if (currentTarget.first > 0.0) {
int timeleft = nextTarget.first - currentTime;
int timeleft = nextTarget.first - currentTime;
int hour = timeleft / 3600;
int second = timeleft % 3600;
int minute = second / 60;
second = second % 60;
int hour = timeleft / 3600;
int second = timeleft % 3600;
int minute = second / 60;
second = second % 60;
std::string hh, mm, ss, coundtown;
std::string hh, mm, ss, coundtown;
if (hour < 10) hh.append("0");
if (minute < 10) mm.append("0");
if (second < 10) ss.append("0");
if (hour < 10) hh.append("0");
if (minute < 10) mm.append("0");
if (second < 10) ss.append("0");
hh.append(std::to_string(hour));
mm.append(std::to_string(minute));
ss.append(std::to_string(second));
hh.append(std::to_string(hour));
mm.append(std::to_string(minute));
ss.append(std::to_string(second));
glm::vec4 b2(1.00, 0.51, 0.00, 1);
PrintColorText(i++, "Switching observation focus in : [%s:%s:%s]", 10, b2, hh.c_str(), mm.c_str(), ss.c_str());
std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer2::ref().getIncidentTargetList(2);
std::string space;
glm::vec4 color;
int isize = incidentTargets.second.size();
for (int p = 0; p < isize; p++){
double t = (double)(p + 1) / (double)(isize + 1);
t = (p > isize / 2) ? 1 - t : t;
t += 0.3;
color = (p == isize / 2) ? glm::vec4(1.00, 0.51, 0.00, 1) : glm::vec4(t, t, t, 1);
PrintColorText(i, "%s%s", 10, color, space.c_str(), incidentTargets.second[p].c_str());
for (int k = 0; k < 10; k++){ space += " "; }
}
i++;
std::vector<std::pair<std::string, bool>> instrVec = ImageSequencer2::ref().getActiveInstruments();
glm::vec4 active(0.58, 1, 0.00, 1);
glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1);
glm::vec4 notFiring(0.5, 0.5, 0.5, 1);
double reduce = 0.01;
PrintColorText(i++, "Active Instruments : ", 10, active);
for (int k = 0; k < instrVec.size(); k++){
if (instrVec[k].second == false){
PrintColorText(i, "| |", 10, glm::vec4(0.3, 0.3, 0.3, 1));
PrintColorText(i++, " %5s", 10, glm::vec4(0.3, 0.3, 0.3, 1), instrVec[k].first.c_str());
}
else{
PrintColorText(i, "|", 10, glm::vec4(0.3, 0.3, 0.3, 1));
if (instrVec[k].first == "NH_LORRI"){
PrintColorText(i, " + ", 10, firing);
}
PrintColorText(i, " |", 10, glm::vec4(0.3, 0.3, 0.3, 1));
PrintColorText(i++, " %5s", 10, active, instrVec[k].first.c_str());
}
}
glm::vec4 b2(1.00, 0.51, 0.00, 1);
PrintColorText(i++, "Switching observation focus in : [%s:%s:%s]", 10, b2, hh.c_str(), mm.c_str(), ss.c_str());
std::pair<double, std::vector<std::string>> incidentTargets = ImageSequencer2::ref().getIncidentTargetList(2);
std::string space;
glm::vec4 color;
int isize = incidentTargets.second.size();
for (int p = 0; p < isize; p++){
double t = (double)(p + 1) / (double)(isize+1);
t = (p > isize / 2) ? 1-t : t;
t += 0.3;
color = (p == isize / 2) ? glm::vec4(1.00, 0.51, 0.00, 1) : glm::vec4(t, t, t, 1);
PrintColorText(i, "%s%s", 10, color, space.c_str(), incidentTargets.second[p].c_str());
for (int k = 0; k < 10; k++){ space += " "; }
}
i++;
std::map<std::string, bool> activeMap = ImageSequencer2::ref().getActiveInstruments();
glm::vec4 active(0.58, 1, 0.00, 1);
glm::vec4 firing(0.58-t, 1-t, 1-t, 1);
glm::vec4 notFiring(0.5, 0.5, 0.5, 1);
PrintColorText(i++, "Active Instruments : ", 10, active);
for (auto t : activeMap){
if (t.second == false){
PrintColorText(i, "| |", 10, glm::vec4(0.3, 0.3, 0.3, 1));
PrintColorText(i++, " %5s", 10, glm::vec4(0.3, 0.3, 0.3, 1), t.first.c_str());
}
else{
PrintColorText(i, "|", 10, glm::vec4(0.3, 0.3, 0.3, 1));
if (t.first == "NH_LORRI"){
PrintColorText(i, " + ", 10, firing);
}
PrintColorText(i, " |", 10, glm::vec4(0.3, 0.3, 0.3, 1));
PrintColorText(i++, " %5s", 10, active, t.first.c_str());
}
}
}
}
@@ -800,14 +736,14 @@ namespace openspace {
_showInfo = b;
}
SceneGraph* RenderEngine::sceneGraph()
Scene* RenderEngine::scene()
{
// TODO custom assert (ticket #5)
assert(_sceneGraph);
return _sceneGraph;
}
void RenderEngine::setSceneGraph(SceneGraph* sceneGraph)
void RenderEngine::setSceneGraph(Scene* sceneGraph)
{
_sceneGraph = sceneGraph;
}
@@ -984,7 +920,7 @@ namespace openspace {
PerformanceLayoutEntry entries[maxValues];
};
const int nNodes = static_cast<int>(sceneGraph()->allSceneGraphNodes().size());
const int nNodes = static_cast<int>(scene()->allSceneGraphNodes().size());
if (!_performanceMemory) {
// Compute the total size
@@ -1005,7 +941,7 @@ namespace openspace {
memset(layout->entries, 0, maxValues * sizeof(PerformanceLayout::PerformanceLayoutEntry));
for (int i = 0; i < nNodes; ++i) {
SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i];
SceneGraphNode* node = scene()->allSceneGraphNodes()[i];
memset(layout->entries[i].name, 0, lengthName);
strcpy(layout->entries[i].name, node->name().c_str());
@@ -1019,7 +955,7 @@ namespace openspace {
PerformanceLayout* layout = reinterpret_cast<PerformanceLayout*>(_performanceMemory->pointer());
_performanceMemory->acquireLock();
for (int i = 0; i < nNodes; ++i) {
SceneGraphNode* node = sceneGraph()->allSceneGraphNodes()[i];
SceneGraphNode* node = scene()->allSceneGraphNodes()[i];
SceneGraphNode::PerformanceRecord r = node->performanceRecord();
PerformanceLayout::PerformanceLayoutEntry& entry = layout->entries[i];
@@ -1036,38 +972,56 @@ namespace openspace {
// This method is temporary and will be removed once the scalegraph is in effect ---abock
void RenderEngine::changeViewPoint(std::string origin) {
SceneGraphNode* solarSystemBarycenterNode = sceneGraph()->sceneGraphNode("SolarSystemBarycenter");
SceneGraphNode* plutoBarycenterNode = sceneGraph()->sceneGraphNode("PlutoBarycenter");
SceneGraphNode* newHorizonsNode = sceneGraph()->sceneGraphNode("NewHorizons");
SceneGraphNode* jupiterBarycenterNode = sceneGraph()->sceneGraphNode("JupiterBarycenter");
SceneGraphNode* solarSystemBarycenterNode = scene()->sceneGraphNode("SolarSystemBarycenter");
SceneGraphNode* plutoBarycenterNode = scene()->sceneGraphNode("PlutoBarycenter");
SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons");
SceneGraphNode* newHorizonsTrailNode = scene()->sceneGraphNode("NewHorizonsTrail");
if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr) {
LERROR("WTF");
return;
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 ||
newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr
//|| dawnNode == nullptr
//|| vestaNode == nullptr
) {
LERROR("Necessary nodes does not exist");
return;
}
if (origin == "Pluto") {
ghoul::Dictionary solarDictionary =
{
{ std::string("Type"), std::string("Spice") },
{ std::string("Body") , std::string("SUN") },
{ std::string("Reference"), std::string("ECLIPJ2000") },
{ std::string("Observer") , std::string("PLUTO BARYCENTER") },
{ std::string("Kernels") , ghoul::Dictionary() }
};
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("ECLIPJ2000") },
{ std::string("Observer"), std::string("SUN") },
{ 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));
plutoBarycenterNode->setEphemeris(new StaticEphemeris);
ghoul::Dictionary newHorizonsDictionary =
{
{ std::string("Type"), std::string("Spice") },
@@ -1076,16 +1030,64 @@ void RenderEngine::changeViewPoint(std::string origin) {
{ std::string("Observer"), std::string("PLUTO BARYCENTER") },
{ std::string("Kernels"), ghoul::Dictionary() }
};
newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
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"));
plutoBarycenterNode->setParent(solarSystemBarycenterNode);
jupiterBarycenterNode->setParent(solarSystemBarycenterNode);
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("ECLIPJ2000") },
{ std::string("Reference"), std::string("GALACTIC") },
{ std::string("Observer"), std::string("SUN") },
{ std::string("Kernels"), ghoul::Dictionary() }
};
@@ -1093,7 +1095,7 @@ void RenderEngine::changeViewPoint(std::string origin) {
{
{ std::string("Type"), std::string("Spice") },
{ std::string("Body"), std::string("JUPITER BARYCENTER") },
{ std::string("Reference"), std::string("ECLIPJ2000") },
{ std::string("Reference"), std::string("GALACTIC") },
{ std::string("Observer"), std::string("SUN") },
{ std::string("Kernels"), ghoul::Dictionary() }
};
@@ -1107,45 +1109,194 @@ void RenderEngine::changeViewPoint(std::string origin) {
{ 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("Observer"), std::string("SUN") },
{ std::string("Kernels"), ghoul::Dictionary() }
};
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") {
ghoul::Dictionary plutoDictionary =
{
{ std::string("Type"), std::string("Spice") },
{ std::string("Body"), std::string("PLUTO BARYCENTER") },
{ std::string("Reference"), std::string("ECLIPJ2000") },
{ std::string("Observer"), std::string("JUPITER BARYCENTER") },
{ 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("ECLIPJ2000") },
{ std::string("Observer"), std::string("JUPITER BARYCENTER") },
{ std::string("Kernels"), ghoul::Dictionary() }
};
solarSystemBarycenterNode->setEphemeris(new SpiceEphemeris(solarDictionary));
plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary));
jupiterBarycenterNode->setEphemeris(new StaticEphemeris);
jupiterBarycenterNode->setParent(scene()->sceneGraphNode("SolarSystem"));
jupiterBarycenterNode->setEphemeris(new StaticEphemeris);
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() }
};
newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
solarSystemBarycenterNode->setParent(jupiterBarycenterNode);
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));
plutoBarycenterNode->setEphemeris(new SpiceEphemeris(plutoDictionary));
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;
//}
ghoul_assert(false, "This function is being misused");
}
+58
View File
@@ -0,0 +1,58 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/dynamicephemeris.h>
#include <openspace/util/constants.h>
namespace openspace {
using namespace constants::dynamicephemeris;
DynamicEphemeris::DynamicEphemeris(const ghoul::Dictionary& dictionary)
: _position(0.f, 0.f, 0.f, 0.f)
{
const bool hasPosition = dictionary.hasKeyAndValue<glm::vec4>(keyPosition);
if (hasPosition) {
glm::vec4 tmp;
dictionary.getValue(keyPosition, tmp);
_position = tmp;
}
}
DynamicEphemeris::~DynamicEphemeris() {}
const psc& DynamicEphemeris::position() const {
return _position;
}
void DynamicEphemeris::setPosition(psc pos) {
_position = pos;
}
void DynamicEphemeris::update(const UpdateData&) {
}
} // namespace openspace
@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scenegraph/ephemeris.h>
#include <openspace/scene/ephemeris.h>
#include <openspace/util/constants.h>
#include <openspace/util/factorymanager.h>
@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scenegraph/scenegraph.h>
#include <openspace/scene/scene.h>
#include <openspace/abuffer/abuffer.h>
#include <openspace/engine/configurationmanager.h>
@@ -31,12 +31,14 @@
#include <openspace/interaction/interactionhandler.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scenegraph/scenegraphnode.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/scripting/script_helper.h>
#include <openspace/util/constants.h>
#include <openspace/util/time.h>
#include <boost/algorithm/string.hpp>
#include <ghoul/filesystem/filesystem.h>
#include "ghoul/io/texture/texturereader.h"
#include <ghoul/misc/dictionary.h>
@@ -138,26 +140,23 @@ int loadScene(lua_State* L) {
std::string sceneFile = luaL_checkstring(L, -1);
OsEng.renderEngine()->sceneGraph()->scheduleLoadSceneFile(sceneFile);
OsEng.renderEngine()->scene()->scheduleLoadSceneFile(sceneFile);
return 0;
}
} // namespace luascriptfunctions
SceneGraph::SceneGraph()
Scene::Scene()
: _focus(SceneGraphNode::RootNodeName)
, _root(nullptr)
{
}
SceneGraph::~SceneGraph()
{
Scene::~Scene() {
deinitialize();
}
bool SceneGraph::initialize()
{
bool Scene::initialize() {
LDEBUG("Initializing SceneGraph");
using ghoul::opengl::ShaderObject;
@@ -184,6 +183,7 @@ bool SceneGraph::initialize()
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("fboPassProgram", tmpProgram);
// projection program
tmpProgram = ProgramObject::Build("projectiveProgram",
"${SHADERS}/projectiveTexture_vs.glsl",
@@ -199,21 +199,29 @@ bool SceneGraph::initialize()
"${SHADERS}/pscstandard_fs.glsl");
if( ! tmpProgram) return false;
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("pscShader", tmpProgram);
// NH shader
tmpProgram = ProgramObject::Build("NHProgram",
"${SHADERS}/nh_vs.glsl",
"${SHADERS}/nh_fs.glsl");
tmpProgram = ProgramObject::Build("ModelProgram",
"${SHADERS}/model_vs.glsl",
"${SHADERS}/model_fs.glsl");
if (!tmpProgram) return false;
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("NewHorizonsShader", tmpProgram);
OsEng.ref().configurationManager()->setValue("GenericModelShader", tmpProgram);
// fovProgram
// Night texture program
tmpProgram = ProgramObject::Build("nightTextureProgram",
"${SHADERS}/nighttexture_vs.glsl",
"${SHADERS}/nighttexture_fs.glsl");
if (!tmpProgram) return false;
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("nightTextureProgram", tmpProgram);
// Fov Program
tmpProgram = ProgramObject::Build("FovProgram",
"${SHADERS}/fov_vs.glsl",
"${SHADERS}/fov_fs.glsl");
@@ -222,6 +230,24 @@ bool SceneGraph::initialize()
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("FovProgram", tmpProgram);
// Plane Program
tmpProgram = ProgramObject::Build("planeProgram",
"${SHADERS}/modules/plane/plane_vs.glsl",
"${SHADERS}/modules/plane/plane_fs.glsl");
if (!tmpProgram) return false;
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("planeProgram", tmpProgram);
// Image Plane Program
tmpProgram = ProgramObject::Build("imagePlaneProgram",
"${SHADERS}/modules/imageplane/imageplane_vs.glsl",
"${SHADERS}/modules/imageplane/imageplane_fs.glsl");
if (!tmpProgram) return false;
tmpProgram->setProgramObjectCallback(cb);
_programs.push_back(tmpProgram);
OsEng.ref().configurationManager()->setValue("imagePlaneProgram", tmpProgram);
// RaycastProgram
tmpProgram = ProgramObject::Build("RaycastProgram",
"${SHADERS}/exitpoints.vert",
@@ -248,8 +274,7 @@ bool SceneGraph::initialize()
return true;
}
bool SceneGraph::deinitialize()
{
bool Scene::deinitialize() {
clearSceneGraph();
// clean up all programs
@@ -260,10 +285,9 @@ bool SceneGraph::deinitialize()
return true;
}
void SceneGraph::update(const UpdateData& data)
{
void Scene::update(const UpdateData& data) {
if (!_sceneGraphToLoad.empty()) {
OsEng.renderEngine()->sceneGraph()->clearSceneGraph();
OsEng.renderEngine()->scene()->clearSceneGraph();
bool success = loadSceneInternal(_sceneGraphToLoad);
_sceneGraphToLoad = "";
if (!success)
@@ -272,18 +296,17 @@ void SceneGraph::update(const UpdateData& data)
OsEng.renderEngine()->abuffer()->invalidateABuffer();
#endif
}
for (SceneGraphNode* node : _nodes)
for (SceneGraphNode* node : _graph.nodes())
node->update(data);
}
void SceneGraph::evaluate(Camera* camera)
{
if (_root)
_root->evaluate(camera);
void Scene::evaluate(Camera* camera) {
for (SceneGraphNode* node : _graph.nodes())
node->evaluate(camera);
//_root->evaluate(camera);
}
void SceneGraph::render(const RenderData& data)
{
void Scene::render(const RenderData& data) {
bool emptyProgramsToUpdate = _programsToUpdate.empty();
_programUpdateLock.lock();
@@ -301,92 +324,106 @@ void SceneGraph::render(const RenderData& data)
program->setIgnoreSubroutineUniformLocationError(true);
}
if (_root)
_root->render(data);
for (SceneGraphNode* node : _graph.nodes())
node->render(data);
//if (_root)
// _root->render(data);
}
void SceneGraph::scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath) {
void Scene::scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath) {
_sceneGraphToLoad = sceneDescriptionFilePath;
}
void SceneGraph::clearSceneGraph() {
void Scene::clearSceneGraph() {
// deallocate the scene graph. Recursive deallocation will occur
if (_root) {
_root->deinitialize();
delete _root;
_root = nullptr;
}
_graph.clear();
//if (_root) {
// _root->deinitialize();
// delete _root;
// _root = nullptr;
//}
_nodes.erase(_nodes.begin(), _nodes.end());
_allNodes.erase(_allNodes.begin(), _allNodes.end());
// _nodes.erase(_nodes.begin(), _nodes.end());
// _allNodes.erase(_allNodes.begin(), _allNodes.end());
_focus.clear();
}
bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
{
using ghoul::Dictionary;
using ghoul::lua::loadDictionaryFromFile;
bool Scene::loadSceneInternal(const std::string& sceneDescriptionFilePath) {
// using ghoul::Dictionary;
// using ghoul::lua::loadDictionaryFromFile;
if (!FileSys.fileExists(sceneDescriptionFilePath)) {
LFATAL("Scene description file '" << sceneDescriptionFilePath << "' not found");
return false;
}
//if (!FileSys.fileExists(sceneDescriptionFilePath)) {
// LFATAL("Scene description file '" << sceneDescriptionFilePath << "' not found");
// return false;
//}
LDEBUG("Loading scenegraph nodes");
if (_root != nullptr) {
LFATAL("Scenegraph already loaded");
return false;
}
// LDEBUG("Loading scenegraph nodes");
// if (_root != nullptr) {
// LFATAL("Scenegraph already loaded");
// return false;
// }
OsEng.disableBarrier();
// OsEng.disableBarrier();
// initialize the root node
_root = new SceneGraphNode();
_root->setName(SceneGraphNode::RootNodeName);
_nodes.push_back(_root);
_allNodes.emplace(SceneGraphNode::RootNodeName, _root);
_focus = SceneGraphNode::RootNodeName;
// _root = new SceneGraphNode();
// _root->setName(SceneGraphNode::RootNodeName);
// _nodes.push_back(_root);
// _allNodes.emplace(SceneGraphNode::RootNodeName, _root);
// _focus = SceneGraphNode::RootNodeName;
Dictionary dictionary;
//load default.scene
loadDictionaryFromFile(sceneDescriptionFilePath, dictionary);
// bool success = SceneGraphLoader::load(sceneDescriptionFilePath, _nodes);
std::string&& sceneDescriptionDirectory =
ghoul::filesystem::File(sceneDescriptionFilePath).directoryName();
std::string moduleDirectory(".");
dictionary.getValue(constants::scenegraph::keyPathScene, moduleDirectory);
// The scene path could either be an absolute or relative path to the description
// paths directory
std::string&& relativeCandidate = sceneDescriptionDirectory +
ghoul::filesystem::FileSystem::PathSeparator + moduleDirectory;
std::string&& absoluteCandidate = absPath(moduleDirectory);
ghoul::Dictionary dictionary;
////load default.scene
ghoul::lua::loadDictionaryFromFile(sceneDescriptionFilePath, dictionary);
if (FileSys.directoryExists(relativeCandidate))
moduleDirectory = relativeCandidate;
else if (FileSys.directoryExists(absoluteCandidate))
moduleDirectory = absoluteCandidate;
else {
LFATAL("The '" << constants::scenegraph::keyPathScene << "' pointed to a "
"path '" << moduleDirectory << "' that did not exist");
OsEng.enableBarrier();
return false;
}
//std::string&& sceneDescriptionDirectory =
// ghoul::filesystem::File(sceneDescriptionFilePath).directoryName();
//std::string moduleDirectory(".");
//dictionary.getValue(constants::scenegraph::keyPathScene, moduleDirectory);
// Load the modules/scenegraph nodes
loadModules(moduleDirectory, dictionary);
//// The scene path could either be an absolute or relative path to the description
//// paths directory
//std::string&& relativeCandidate = sceneDescriptionDirectory +
// ghoul::filesystem::FileSystem::PathSeparator + moduleDirectory;
//std::string&& absoluteCandidate = absPath(moduleDirectory);
//if (FileSys.directoryExists(relativeCandidate))
// moduleDirectory = relativeCandidate;
//else if (FileSys.directoryExists(absoluteCandidate))
// moduleDirectory = absoluteCandidate;
//else {
// LFATAL("The '" << constants::scenegraph::keyPathScene << "' pointed to a "
// "path '" << moduleDirectory << "' that did not exist");
// OsEng.enableBarrier();
// return false;
//}
//// Load the modules/scenegraph nodes
//loadModules(moduleDirectory, dictionary);
_graph.loadFromFile(sceneDescriptionFilePath);
// TODO: Make it less hard-coded and more flexible when nodes are not found
Dictionary cameraDictionary;
ghoul::Dictionary cameraDictionary;
if (dictionary.getValue(constants::scenegraph::keyCamera, cameraDictionary)) {
LDEBUG("Camera dictionary found");
std::string focus;
if (cameraDictionary.hasKey(constants::scenegraph::keyFocusObject)
&& cameraDictionary.getValue(constants::scenegraph::keyFocusObject, focus)) {
auto focusIterator = _allNodes.find(focus);
if (focusIterator != _allNodes.end()) {
&& cameraDictionary.getValue(constants::scenegraph::keyFocusObject, focus))
{
auto focusIterator = std::find_if(
_graph.nodes().begin(),
_graph.nodes().end(),
[focus](SceneGraphNode* node) {
return node->name() == focus;
}
);
if (focusIterator != _graph.nodes().end()) {
_focus = focus;
LDEBUG("Setting camera focus to '" << _focus << "'");
}
@@ -396,7 +433,7 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
}
// Initialize all nodes
for (SceneGraphNode* node : _nodes) {
for (SceneGraphNode* node : _graph.nodes()) {
bool success = node->initialize();
if (success)
LDEBUG(node->name() << " initialized successfully!");
@@ -406,24 +443,36 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
// update the position of all nodes
// TODO need to check this; unnecessary? (ab)
for (SceneGraphNode* node : _nodes)
for (SceneGraphNode* node : _graph.nodes()) {
node->update({ Time::ref().currentTime() });
}
for (auto it = _graph.nodes().rbegin(); it != _graph.nodes().rend(); ++it)
(*it)->calculateBoundingSphere();
// Calculate the bounding sphere for the scenegraph
_root->calculateBoundingSphere();
//_root->calculateBoundingSphere();
// set the camera position
Camera* c = OsEng.ref().renderEngine()->camera();
auto focusIterator = _allNodes.find(_focus);
//auto focusIterator = _allNodes.find(_focus);
auto focusIterator = std::find_if(
_graph.nodes().begin(),
_graph.nodes().end(),
[&](SceneGraphNode* node) {
return node->name() == _focus;
}
);
glm::vec2 cameraScaling(1);
psc cameraPosition(0,0,1,0);
glm::vec3 cameraDirection = glm::vec3(0, 0, -1);
if (focusIterator != _allNodes.end()) {
//if (_focus->)
if (focusIterator != _graph.nodes().end()) {
LDEBUG("Camera focus is '" << _focus << "'");
SceneGraphNode* focusNode = focusIterator->second;
SceneGraphNode* focusNode = *focusIterator;
//Camera* c = OsEng.interactionHandler().getCamera();
// TODO: Make distance depend on radius
@@ -456,6 +505,8 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
// Set the focus node for the interactionhandler
OsEng.interactionHandler()->setFocusNode(focusNode);
}
else
OsEng.interactionHandler()->setFocusNode(_graph.rootNode());
glm::vec4 position;
if (cameraDictionary.hasKey(constants::scenegraph::keyPositionObject)
@@ -490,7 +541,7 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
}
for (SceneGraphNode* node : _nodes) {
for (SceneGraphNode* node : _graph.nodes()) {
std::vector<properties::Property*> properties = node->propertiesRecursive();
for (properties::Property* p : properties) {
OsEng.gui()->_property.registerProperty(p);
@@ -520,172 +571,166 @@ bool SceneGraph::loadSceneInternal(const std::string& sceneDescriptionFilePath)
return true;
}
void SceneGraph::loadModules(
const std::string& directory,
const ghoul::Dictionary& dictionary)
{
// Struct containing dependencies and nodes
LoadMaps m;
//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!");
// }
//}
// Get the common directory
std::string commonDirectory(_defaultCommonDirectory);
dictionary.getValue(constants::scenegraph::keyCommonFolder, commonDirectory);
FileSys.registerPathToken(_commonModuleToken, commonDirectory);
//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);
//}
lua_State* state = ghoul::lua::createNewLuaState();
OsEng.scriptEngine()->initializeLuaState(state);
//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);
// }
//}
LDEBUG("Loading common module folder '" << commonDirectory << "'");
// Load common modules into LoadMaps struct
loadModule(m, FileSys.pathByAppendingComponent(directory, commonDirectory), state);
//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);
//}
// 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 SceneGraph::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 SceneGraph::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 SceneGraph::loadNode(const ghoul::Dictionary& dictionary) {
SceneGraphNode* node = SceneGraphNode::createFromDictionary(dictionary);
if(node) {
_allNodes.emplace(node->name(), node);
_nodes.push_back(node);
}
}
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);
}
SceneGraphNode* SceneGraph::root() const
{
return _root;
SceneGraphNode* Scene::root() const {
return _graph.rootNode();
}
SceneGraphNode* SceneGraph::sceneGraphNode(const std::string& name) const {
auto it = _allNodes.find(name);
if (it == _allNodes.end())
return nullptr;
else
return it->second;
SceneGraphNode* Scene::sceneGraphNode(const std::string& name) const {
return _graph.sceneGraphNode(name);
}
std::vector<SceneGraphNode*> SceneGraph::allSceneGraphNodes() const {
return _nodes;
std::vector<SceneGraphNode*> Scene::allSceneGraphNodes() {
return _graph.nodes();
}
void SceneGraph::writePropertyDocumentation(const std::string& filename, const std::string& type) {
void Scene::writePropertyDocumentation(const std::string& filename, const std::string& type) {
if (type == "text") {
LDEBUG("Writing documentation for properties");
std::ofstream file(filename);
@@ -695,7 +740,7 @@ void SceneGraph::writePropertyDocumentation(const std::string& filename, const s
}
using properties::Property;
for (SceneGraphNode* node : _nodes) {
for (SceneGraphNode* node : _graph.nodes()) {
std::vector<Property*> properties = node->propertiesRecursive();
if (!properties.empty()) {
file << node->name() << std::endl;
@@ -712,7 +757,7 @@ void SceneGraph::writePropertyDocumentation(const std::string& filename, const s
LERROR("Undefined type '" << type << "' for Property documentation");
}
scripting::ScriptEngine::LuaLibrary SceneGraph::luaLibrary() {
scripting::ScriptEngine::LuaLibrary Scene::luaLibrary() {
return {
"",
{
+367
View File
@@ -0,0 +1,367 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2015 *
* *
* 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/util/constants.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/lua/lua_helper.h>
#include <stack>
namespace {
const std::string _loggerCat = "SceneGraph";
const std::string _moduleExtension = ".mod";
const std::string _defaultCommonDirectory = "common";
const std::string _commonModuleToken = "${COMMON_MODULE}";
}
namespace openspace {
SceneGraph::SceneGraph() {
}
void SceneGraph::clear() {
// Untested ---abock
for (SceneGraphNodeInternal* n : _nodes) {
delete n->node;
delete n;
}
_nodes.clear();
}
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
if (!FileSys.fileExists(absSceneFile, true)) {
LERROR("Could not load scene file '" << absSceneFile << "'. " <<
"File not found");
return false;
}
LINFO("Loading SceneGraph from file '" << absSceneFile << "'");
// Load dictionary
ghoul::Dictionary sceneDictionary;
bool success = ghoul::lua::loadDictionaryFromFile(absSceneFile, sceneDictionary);
if (!success)
return false;
std::string sceneDescriptionDirectory =
ghoul::filesystem::File(absSceneFile, true).directoryName();
std::string sceneDirectory(".");
sceneDictionary.getValue(constants::scenegraph::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 '" << constants::scenegraph::keyPathScene << "' pointed to a "
"path '" << sceneDirectory << "' that did not exist");
return false;
}
using constants::scenegraph::keyModules;
ghoul::Dictionary moduleDictionary;
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);
// Get the common directory
using constants::scenegraph::keyCommonFolder;
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);
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 moduleName = moduleDictionary.value<std::string>(key);
std::string modulePath = FileSys.pathByAppendingComponent(sceneDirectory, moduleName);
if (!FileSys.directoryExists(modulePath)) {
LERROR("Could not load module '" << moduleName << "'. Directory did not exist");
continue;
}
std::string moduleFile = FileSys.pathByAppendingComponent(
modulePath,
moduleName + _moduleExtension
);
if (!FileSys.fileExists(moduleFile)) {
LERROR("Could not load module file '" << moduleFile << "'. File did not exist");
continue;
}
ghoul::Dictionary moduleDictionary;
bool s = ghoul::lua::loadDictionaryFromFile(moduleFile, moduleDictionary, state);
if (!s)
continue;
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(constants::scenegraph::keyPathModule, modulePath);
element.getValue(constants::scenegraphnode::keyName, nodeName);
element.getValue(constants::scenegraphnode::keyParentName, parentName);
FileSys.setCurrentDirectory(modulePath);
SceneGraphNode* node = SceneGraphNode::createFromDictionary(element);
if (node == nullptr) {
LERROR("Error loading SceneGraphNode '" << nodeName << "' in module '" << moduleName << "'");
clear();
return false;
}
dependencies[nodeName].push_back(parentName);
parents[nodeName] = parentName;
// Also include loaded dependencies
using constants::scenegraphnode::keyDependencies;
if (element.hasKey(keyDependencies)) {
if (element.hasValue<ghoul::Dictionary>(keyDependencies)) {
ghoul::Dictionary nodeDependencies;
element.getValue(constants::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);
}
}
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() << "'");
}
node->node->setParent(parentNode);
}
// 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);
}
}
for (SceneGraphNodeInternal* node : _nodes) {
if (!nodeIsDependentOnRoot(node)) {
LERROR("Node '" << node->node->name() << "' has no direct connection to Root.");
//clear();
return false;
}
}
bool s = sortTopologially();
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::sortTopologially() {
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) {
return true;
}
bool SceneGraph::removeSceneGraphNode(SceneGraphNode* node) {
// How to handle orphaned nodes? (reparent to root?) --- abock
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() {
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
@@ -23,7 +23,7 @@
****************************************************************************************/
// open space includes
#include <openspace/scenegraph/scenegraphnode.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/query/query.h>
#include <openspace/util/constants.h>
@@ -36,7 +36,7 @@
#include <ghoul/opengl/shaderobject.h>
#include <ghoul/misc/highresclock.h>
#include <openspace/scenegraph/staticephemeris.h>
#include <openspace/scene/staticephemeris.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/factorymanager.h>
@@ -109,14 +109,14 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di
parentName = "Root";
}
SceneGraphNode* parentNode = sceneGraphNode(parentName);
if (parentNode == nullptr) {
LFATAL("Could not find parent named '"
<< parentName << "' for '" << result->name() << "'."
<< " Check module definition order. Skipping module.");
}
//SceneGraphNode* parentNode = sceneGraphNode(parentName);
//if (parentNode == nullptr) {
// LFATAL("Could not find parent named '"
// << parentName << "' for '" << result->name() << "'."
// << " Check module definition order. Skipping module.");
//}
parentNode->addNode(result);
//parentNode->addNode(result);
LDEBUG("Successfully created SceneGraphNode '"
<< result->name() << "'");
@@ -247,12 +247,12 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) {
}
// evaluate all the children, tail-recursive function(?)
for (SceneGraphNode* child : _children)
child->evaluate(camera, psc());
//for (SceneGraphNode* child : _children)
// child->evaluate(camera, psc());
}
void SceneGraphNode::render(const RenderData& data) {
const psc thisPosition = data.position + _ephemeris->position();
const psc thisPosition = worldPosition();
RenderData newData = {data.camera, thisPosition, data.doPerformanceMeasurement};
@@ -274,23 +274,35 @@ void SceneGraphNode::render(const RenderData& data) {
// evaluate all the children, tail-recursive function(?)
for (SceneGraphNode* child : _children)
child->render(newData);
//for (SceneGraphNode* child : _children)
// child->render(newData);
}
// set & get
void SceneGraphNode::addNode(SceneGraphNode* child)
{
// add a child node and set this node to be the parent
child->setParent(this);
_children.push_back(child);
}
// not used anymore @AA
//void SceneGraphNode::addNode(SceneGraphNode* child)
//{
// // add a child node and set this node to be the parent
// child->setParent(this);
// _children.push_back(child);
//}
void SceneGraphNode::setParent(SceneGraphNode* parent)
{
_parent = parent;
}
//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 psc& SceneGraphNode::position() const
{
return _ephemeris->position();
@@ -22,14 +22,16 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scenegraph/spiceephemeris.h>
#include <openspace/scene/spiceephemeris.h>
#include <openspace/util/constants.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/time.h>
#include <openspace/util/imagesequencer2.h>
namespace {
const std::string _loggerCat = "SpiceEphemeris";
const std::string keyGhosting = "EphmerisGhosting";
}
namespace openspace {
@@ -50,6 +52,8 @@ SpiceEphemeris::SpiceEphemeris(const ghoul::Dictionary& dictionary)
if (!hasObserver)
LERROR("SpiceEphemeris does not contain the key '" << keyOrigin << "'");
dictionary.getValue(keyGhosting, _ghosting);
ghoul::Dictionary kernels;
dictionary.getValue(keyKernels, kernels);
for (size_t i = 1; i <= kernels.size(); ++i) {
@@ -73,15 +77,14 @@ void SpiceEphemeris::update(const UpdateData& data) {
glm::dvec3 position(0,0,0);
double lightTime = 0.0;
SpiceManager::ref().getTargetPosition(_targetName, _originName,
"GALACTIC", "NONE", data.time, position, lightTime);
if (_targetName == "NEW HORIZONS"){
// In order to properly draw the viewfrustrum, the craft might have to be
// positioned using the X-variations of aberration methods (ongoing investigation).
double interval = openspace::ImageSequencer2::ref().getIntervalLength();
if (_ghosting == "TRUE" && interval > 60){
double _time = openspace::ImageSequencer2::ref().getNextCaptureTime();
SpiceManager::ref().getTargetPosition(_targetName, _originName,
"GALACTIC", "NONE", data.time, position, lightTime);
"GALACTIC", "NONE", _time, position, lightTime);
}
_position = psc::CreatePowerScaledCoordinate(position.x, position.y, position.z);
@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/scenegraph/staticephemeris.h>
#include <openspace/scene/staticephemeris.h>
#include <openspace/util/constants.h>
@@ -1,11 +0,0 @@
{
-- Solar System module
{
Name = "SolarSystem",
Parent = "Root",
Position = {
Type = "static",
Position = { 0, 0, 0, 0}
}
},
}
-12
View File
@@ -1,12 +0,0 @@
{
Camera = {
Focus = "Earth",
Position = "Earth"
},
Modules = {
"common",
"earth"
}
}
-83
View File
@@ -1,83 +0,0 @@
{
-- Earth barycenter module
{
Name = "EarthBarycenter",
Parent = "SolarSystem",
Static = "true",
Position = {
Type = "Kepler",
Inclination = 0.00041,
AscendingNode = 349.2,
Perihelion = 102.8517,
SemiMajorAxis = 1.00002,
DailyMotion = 0.9855796,
Eccentricity = 0.0166967,
MeanLongitude = 328.40353
}
},
-- dummy earth module
--[[
{
Name = "DummyEarth",
Parent = "Root",
Renderable = {
Type = "RenderablePlanet",
Geometry = {
Type = "SimpleSphere",
--Radius = { 1.0, 1 } -- not sure if correct; supposed 6371km in meters in pss
Radius = { 1.0, 1} -- not sure if correct; supposed 6371km in meters in pss
},
Textures = {
Type = "simple",
Color = "textures/earth_nasa_lowres.png",
Depth = "textures/earth_depth.png"
},
},
Position = {
Type = "Static",
Position = { 0, 0, -1, 1}
}
},
]]--
-- Earth module
{
Name = "Earth",
Parent = "EarthBarycenter",
Renderable = {
Type = "RenderablePlanet",
Geometry = {
Type = "SimpleSphere",
--Radius = { 6.371, 6 },
Radius = { 1.0, 1},
Segments = 10
},
Textures = {
Type = "simple",
Color = "textures/earth_nasa_lowres.png",
Depth = "textures/earth_depth.png"
},
Atmosphere = {
Type = "Nishita", -- for example, values missing etc etc
MieFactor = 1.0,
MieColor = {1.0, 1.0, 1.0}
}
},
Position = {
Type = "Spice",
Body = "EARTH",
Reference = "ECLIPJ2000",
Observer = "EARTH BARYCENTER",
Kernels = {
"kernels/earth.bsp"
}
},
Rotation = {
Type = "Spice",
Frame = "IAU_EARTH",
Reference = "ECLIPJ2000"
},
GuiName = "/Solar/Planets/Earth"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 734 KiB

+7 -2
View File
@@ -37,14 +37,16 @@
#include <openspace/rendering/planets/renderableplanet.h>
#include <openspace/rendering/planets/simplespheregeometry.h>
#include <openspace/rendering/renderableplane.h>
#include <openspace/rendering/renderableplaneprojection.h>
#include <openspace/rendering/renderablevolumegl.h>
#include <openspace/rendering/planets/simplespheregeometry.h>
#include <openspace/rendering/model/modelgeometry.h>
#include <openspace/rendering/model/wavefrontgeometry.h>
// positioninformation
#include <openspace/scenegraph/staticephemeris.h>
#include <openspace/scenegraph/spiceephemeris.h>
#include <openspace/scene/staticephemeris.h>
#include <openspace/scene/dynamicephemeris.h>
#include <openspace/scene/spiceephemeris.h>
// projection
#include <openspace/rendering/planets/renderableplanetprojection.h>
@@ -93,6 +95,8 @@ void FactoryManager::initialize()
"RenderableModel");
_manager->factory<Renderable>()->registerClass<RenderablePlane>(
"RenderablePlane");
_manager->factory<Renderable>()->registerClass<RenderablePlaneProjection>(
"RenderablePlaneProjection");
_manager->factory<Renderable>()->registerClass<RenderableVolumeGL>(
"RenderableVolumeGL");
_manager->factory<Renderable>()->registerClass<RenderableFieldlines>(
@@ -101,6 +105,7 @@ void FactoryManager::initialize()
// Add Ephimerides
_manager->addFactory(new ghoul::TemplateFactory<Ephemeris>);
_manager->factory<Ephemeris>()->registerClass<StaticEphemeris>("Static");
_manager->factory<Ephemeris>()->registerClass<StaticEphemeris>("Dynamic");
_manager->factory<Ephemeris>()->registerClass<SpiceEphemeris>("Spice");
_manager->addFactory(new ghoul::TemplateFactory<Decoder>);
+56 -15
View File
@@ -34,8 +34,9 @@
#include <iterator>
#include <iomanip>
#include <limits>
#include <openspace/util/hongkangparser.h>
#include <openspace/util/instrumentdecoder.h>
namespace {
const std::string _loggerCat = "HongKangParser";
@@ -65,9 +66,10 @@ namespace openspace {
translationDictionary.getValue(decoders[i], typeDictionary);
//for each playbook call -> create a Decoder object
const std::vector<std::string>& keys = typeDictionary.keys();
//std::string abort = decoders[i] + "." + keyStopCommand;
for (int j = 0; j < keys.size(); j++){
std::string currentKey = decoders[i] + "." + keys[j];
ghoul::Dictionary decoderDictionary;
translationDictionary.getValue(currentKey, decoderDictionary);
@@ -105,7 +107,7 @@ void HongKangParser::create(){
if (extension == "txt"){// Hong Kang. pre-parsed playbook
LINFO("Using Preparsed Playbook V9H");
std::ifstream file(_fileName);
std::ifstream file(_fileName , std::ios::binary);
if (!file.good()) LERROR("Failed to open txt file '" << _fileName << "'");
std::string line = "";
@@ -130,18 +132,22 @@ void HongKangParser::create(){
std::string cameraTarget = "VOID";
std::string scannerTarget = "VOID";
do{
std::getline(file, line);
int counter = 0;
while (!file.eof()){//only while inte do, FIX
std::getline(file, line);
std::string event = line.substr(0, line.find_first_of(" "));
auto it = _fileTranslation.find(event);
bool foundEvent = (it != _fileTranslation.end());
std::string met = line.substr(25, 9);
double time = getETfromMet(met);
Image image;
if (foundEvent){
//store the time, this is used for getNextCaptureTime()
_captureProgression.push_back(time);
@@ -171,13 +177,48 @@ void HongKangParser::create(){
//compute and store the range for each subset
_subsetMap[image.target]._range.setRange(time);
}
if (scan_start == -1 && it->second->getDecoderType() == "SCANNER"){
//scanner works like state-machine -only store start time now
if (it->second->getDecoderType() == "SCANNER"){ // SCANNER START
scan_start = time;
InstrumentDecoder* scanner = static_cast<InstrumentDecoder*>(it->second);
std::string endNominal = scanner->getStopCommand();
// store current position in file
int len = file.tellg();
std::string linePeek;
bool foundstop = false;
while (!file.eof() && !foundstop){
//continue grabbing next line until we find what we need
getline(file, linePeek);
if (linePeek.find(endNominal) != std::string::npos){
foundstop = true;
met = linePeek.substr(25, 9);
scan_stop = getETfromMet(met);
findPlaybookSpecifiedTarget(line, scannerTarget);
scannerSpiceID = it->second->getTranslation();
scanRange._min = scan_start;
scanRange._max = scan_stop;
_instrumentTimes.push_back(std::make_pair(it->first, scanRange));
//store individual image
createImage(image, scan_start, scan_stop, scannerSpiceID, scannerTarget, _defaultCaptureImage);
_subsetMap[image.target]._subset.push_back(image);
_subsetMap[image.target]._range.setRange(scan_start);
}
}
//go back to stored position in file
file.seekg(len, std::ios_base::beg);
/*//scanner works like state-machine -only store start time now
scan_start = time;
previousScanner = it->first;
//store scanning instrument - store image once stopTime is found!
findPlaybookSpecifiedTarget(line, scannerTarget);
scannerSpiceID = it->second->getTranslation();
scannerSpiceID = it->second->getTranslation();*/
}
}
else{ // we have reached the end of a scan or consecutive capture sequence!
@@ -190,7 +231,7 @@ void HongKangParser::create(){
capture_start = -1;
}
if (line.find("END_NOM") != std::string::npos){
/*if (line.find("END_NOM") != std::string::npos){
assert(scan_start != -1, "SCAN end occured before SCAN call!");
//end of scan, store end time of this scan + store the scan image
scan_stop = time;
@@ -205,9 +246,9 @@ void HongKangParser::create(){
_subsetMap[image.target]._range.setRange(scan_start);
scan_start = -1;
}
}*/
}
} while (!file.eof());
}
}
}
}
@@ -279,10 +320,10 @@ bool HongKangParser::augmentWithSpice(Image& image,
return false;
}
void HongKangParser::createImage(Image& image, double startTime, double stopTime, std::vector<std::string> instr, std::string targ, std::string pot) {
void HongKangParser::createImage(Image& image, double startTime, double stopTime, std::vector<std::string> instr, std::string targ, std::string path) {
image.startTime = startTime;
image.stopTime = stopTime;
image.path = pot;
image.path = path;
for (int i = 0; i < instr.size(); i++){
image.activeInstruments.push_back(instr[i]);
}
+123 -74
View File
@@ -46,10 +46,10 @@ ImageSequencer2* ImageSequencer2::_instance = nullptr;
ImageSequencer2::ImageSequencer2() :
_hasData(false),
_latestImage(nullptr),
_defaultCaptureImage(absPath("${OPENSPACE_DATA}/scene/common/textures/placeholder_blank.png"))
{}
ImageSequencer2& ImageSequencer2::ref() {
assert(_instance != nullptr);
return *_instance;
@@ -68,22 +68,6 @@ bool ImageSequencer2::isReady(){
return _hasData;
}
bool ImageSequencer2::imageComparer(const Image &a, const Image &b){
return a.startTime < b.startTime;
};
std::vector<Image>::iterator ImageSequencer2::binary_find(std::vector<Image>::iterator begin,
std::vector<Image>::iterator end,
const Image &val,
bool(*compareFunc)(const Image &a, const Image &b)){
// Finds the lower bound in at most log(last - first) + 1 comparisons
std::vector<Image>::iterator it = std::lower_bound(begin, end, val, compareFunc);
if (it != begin && it != end){
return it;
}
return end;
}
void ImageSequencer2::updateSequencer(double time){
if (_currentTime != time){
_previousTime = _currentTime;
@@ -92,7 +76,6 @@ void ImageSequencer2::updateSequencer(double time){
}
std::pair<double, std::string> ImageSequencer2::getNextTarget(){
// make into template func
auto compareTime = [](const std::pair<double, std::string> &a,
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
@@ -101,15 +84,14 @@ std::pair<double, std::string> ImageSequencer2::getNextTarget(){
findEqualToThis.first = _currentTime;
auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime);
if (it != _targetTimes.end()){
if (it != _targetTimes.end() && it != _targetTimes.begin()){
return (*it);
}
}
std::pair<double, std::string> ImageSequencer2::getCurrentTarget(){
// make into template func
auto compareTime = [](const std::pair<double, std::string> &a,
const std::pair<double, std::string> &b)->bool{
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
};
std::pair<double, std::string> findEqualToThis;
@@ -127,21 +109,26 @@ std::pair<double, std::vector<std::string>> ImageSequencer2::getIncidentTargetLi
std::pair<double, std::vector<std::string>> incidentTargets;
auto compareTime = [](const std::pair<double, std::string> &a,
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
};
// what to look for
std::pair<double, std::string> findEqualToThis;
findEqualToThis.first = _currentTime;
auto it = std::lower_bound(_targetTimes.begin(), _targetTimes.end(), findEqualToThis, compareTime);
std::advance(it, -(range+1));
if (it != _targetTimes.end() && it != _targetTimes.begin()){
// move the iterator to the first element of the range
std::advance(it, -(range + 1));
for (int i = 0; i < 2*range+1; i++){
incidentTargets.first = it->first;
incidentTargets.second.push_back(it->second);
it++;
if (it == _targetTimes.end())
break;
// now extract incident range
for (int i = 0; i < 2 * range + 1; i++){
incidentTargets.first = it->first;
incidentTargets.second.push_back(it->second);
it++;
if (it == _targetTimes.end())
break;
}
}
return incidentTargets;
@@ -167,30 +154,41 @@ double ImageSequencer2::getNextCaptureTime(){
return nextCaptureTime;
}
const Image* ImageSequencer2::getLatestImageForInstrument(const std::string _instrumentID){
std::vector<std::pair<std::string, bool>> ImageSequencer2::getActiveInstruments(){
for (int i = 0; i < _instrumentOnOff.size(); i++){
_instrumentOnOff[i].second = false;
}
return _latestImage;
}
std::map<std::string, bool> ImageSequencer2::getActiveInstruments(){
// first set all instruments to off
for (auto i : _switchingMap)
_switchingMap[i.first] = false;
// go over the filetranslation map
for (auto key : _fileTranslation){
// for each spice-instrument
for (auto instrumentID : key.second->getTranslation()){
// check if the spice-instrument is active
if (instumentActive(instrumentID)){
for (int i = 0; i < _instrumentOnOff.size(); i++){
if (instrumentID == _instrumentOnOff[i].first){
_instrumentOnOff[i].second = true;
// go over switching map
for (auto instrument : _switchingMap){
// if instrument is present in switching map
if (instrumentID == instrument.first){
// set as active
_switchingMap[instrumentID] = true;
}
}
}
}
}
return _instrumentOnOff;
// return entire map, seen in GUI.
return _switchingMap;
}
bool ImageSequencer2::instumentActive(std::string instrumentID){
bool ImageSequencer2::instumentActive(std::string instrumentID){
for (auto i : _instrumentTimes){
//check if this instrument is in range
if (i.second.inRange(_currentTime)){
//if so, then get the corresponding spiceIDs
std::vector < std::string> spiceIDs = _fileTranslation[i.first]->getTranslation();
if (i.second.inRange(_currentTime)){
//if so, then get the corresponding spiceID
std::vector<std::string> spiceIDs = _fileTranslation[i.first]->getTranslation();
//check which specific subinstrument is firing
for (auto s : spiceIDs){
if (s == instrumentID){
@@ -201,65 +199,116 @@ bool ImageSequencer2::instumentActive(std::string instrumentID){
}
return false;
}
bool ImageSequencer2::getImagePaths(std::vector<std::pair<double, std::string>>& captures, std::string projectee, std::string instrumentID){
bool ImageSequencer2::getImagePaths(std::vector<Image>& captures,
std::string projectee,
std::string instrumentID){
if (!instumentActive(instrumentID) && !Time::ref().timeJumped()) return false;
return (instrumentID == "NH_LORRI") ? getImagePaths(captures, projectee) : false;
// dev. note: this is only due to LORRI being the only instrument implemented so far.
return getImagePaths(captures, projectee);
}
bool ImageSequencer2::getImagePaths(std::vector<std::pair<double, std::string>>& captures,
bool ImageSequencer2::getImagePaths(std::vector<Image>& captures,
std::string projectee){
// check if this instance is either in range or
// a valid candidate to recieve data
//if (!Time::ref().timeJumped() && projectee == getCurrentTarget().second)
if (_subsetMap[projectee]._range.inRange(_currentTime) ||
_subsetMap[projectee]._range.inRange(_previousTime)){
auto compareTime = [](const Image &a,
const Image &b)->bool{
const Image &b)->bool{
return a.startTime < b.startTime;
};
auto begin = _subsetMap[projectee]._subset.begin();
auto end = _subsetMap[projectee]._subset.end();
std::vector<std::pair<double, std::string>> captureTimes;
Image findPrevious;
// for readability we store the iterators
auto begin = _subsetMap[projectee]._subset.begin();
auto end = _subsetMap[projectee]._subset.end();
// create temporary storage
std::vector<Image> captureTimes;
// what to look for
Image findPrevious, findCurrent;
findPrevious.startTime = _previousTime;
Image findCurrent;
findCurrent.startTime = _currentTime;
findCurrent.startTime = _currentTime;
// find the two iterators that correspond to the latest time jump
auto curr = std::lower_bound(begin, end, findCurrent, compareTime);
auto prev = std::lower_bound(begin, end, findPrevious, compareTime);
if (curr != begin && curr != end && prev != begin && prev != end && prev < curr){
std::transform(prev, curr, std::back_inserter(captureTimes),
[](const Image& i) {
return std::make_pair(i.startTime, i.path);
});
std::reverse(captureTimes.begin(), captureTimes.end());
captures = captureTimes;
return true;
if (curr->startTime >= prev->startTime){
std::transform(prev, curr, std::back_inserter(captureTimes),
[](const Image& i) {
return i;
});
std::reverse(captureTimes.begin(), captureTimes.end());
captures = captureTimes;
if (!captures.empty())
_latestImage = &captures.back();
return true;
}
}
}
return false;
}
void ImageSequencer2::sortData(){
auto targetComparer = [](const std::pair<double, std::string> &a,
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
};
auto imageComparer = [](const Image &a, const Image &b)->bool{
return a.startTime < b.startTime;
};
std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer);
std::stable_sort(_captureProgression.begin(), _captureProgression.end());
for (auto sub : _subsetMap){
std::sort(_subsetMap[sub.first]._subset.begin(),
_subsetMap[sub.first]._subset.end(), imageComparer);
}
}
void ImageSequencer2::runSequenceParser(SequenceParser* parser){
parser->create();
_fileTranslation = parser->getTranslation(); // should perhaps be named 'instrumentTranslation'
_subsetMap = parser->getSubsetMap();
_instrumentTimes = parser->getIstrumentTimes();
_targetTimes = parser->getTargetTimes();
_captureProgression = parser->getCaptureProgression();
// get new data
std::map<std::string, Decoder*> in1 = parser->getTranslation();
std::map<std::string, ImageSubset> in2 = parser->getSubsetMap();
std::vector<std::pair<std::string, TimeRange>> in3 = parser->getIstrumentTimes();
std::vector<std::pair<double, std::string>> in4 = parser->getTargetTimes();
std::vector<double> in5 = parser->getCaptureProgression();
// check for sanity
assert(in1.size() > 0, "Sequencer failed to load Translation" );
assert(in2.size() > 0, "Sequencer failed to load Image data" );
assert(in3.size() > 0, "Sequencer failed to load Instrument Switching schedule");
assert(in4.size() > 0, "Sequencer failed to load Target Switching schedule" );
assert(in5.size() > 0, "Sequencer failed to load Capture progression" );
//copy payload from _fileTranslation
// append data
_fileTranslation.insert ( in1.begin(), in1.end());
_subsetMap.insert ( in2.begin(), in2.end());
_instrumentTimes.insert ( _instrumentTimes.end(), in3.begin(), in3.end());
_targetTimes.insert ( _targetTimes.end(), in4.begin(), in4.end());
_captureProgression.insert(_captureProgression.end(), in5.begin(), in5.end());
// sorting of data _not_ optional
sortData();
// extract payload from _fileTranslation
for (auto t : _fileTranslation){
std::vector<std::string> spiceIDs = t.second->getTranslation();
for (auto id : spiceIDs){
_instrumentOnOff.push_back(std::make_pair(id, false));
if (t.second->getDecoderType() == "CAMERA" ||
t.second->getDecoderType() == "SCANNER" ){
std::vector<std::string> spiceIDs = t.second->getTranslation();
for (auto id : spiceIDs){
_switchingMap[id] = false;
}
}
}
_instrumentOnOff.erase(std::unique(_instrumentOnOff.begin(),
_instrumentOnOff.end()),
_instrumentOnOff.end());
_hasData = true;
}
} // namespace openspace
+11
View File
@@ -28,6 +28,7 @@ namespace {
const std::string _loggerCat = "InstrumentDecoder";
const std::string keyDetector = "DetectorType";
const std::string keySpice = "Spice";
const std::string keyStopCommand = "StopCommand";
}
namespace openspace {
@@ -38,6 +39,12 @@ InstrumentDecoder::InstrumentDecoder(const ghoul::Dictionary& dictionary)
ghoul_assert(success, "Instrument has not provided detector type");
for_each(_type.begin(), _type.end(), [](char& in){ in = ::toupper(in); });
if (!dictionary.hasKeyAndValue<std::string>(keyStopCommand) && _type == "SCANNER"){
LWARNING("Scanner must provide stop command, please check mod file.");
}else{
dictionary.getValue(keyStopCommand, _stopCommand);
}
std::vector<std::string> spice;
ghoul::Dictionary spiceDictionary;
success = dictionary.getValue(keySpice, spiceDictionary);
@@ -52,6 +59,10 @@ InstrumentDecoder::InstrumentDecoder(const ghoul::Dictionary& dictionary)
}
}
std::string InstrumentDecoder::getStopCommand(){
return _stopCommand;
}
std::string InstrumentDecoder::getDecoderType(){
return _type;
}
+149 -36
View File
@@ -45,9 +45,7 @@ namespace openspace {
LabelParser::LabelParser(const std::string& fileName,
ghoul::Dictionary translationDictionary)
{
_fileName = fileName;
//_fileTranslation = fileTranslation;
_fileName = fileName;
//get the different instrument types
const std::vector<std::string>& decoders = translationDictionary.keys();
//for each decoder (assuming might have more if hong makes changes)
@@ -76,10 +74,10 @@ LabelParser::LabelParser(const std::string& fileName,
typeDictionary.getValue(keySpecs, specsOfInterestDictionary);
_specsOfInterest.resize(specsOfInterestDictionary.size());
for (int i = 0; i < _specsOfInterest.size(); ++i) {
for (int n = 0; n < _specsOfInterest.size(); ++n) {
std::string readMe;
specsOfInterestDictionary.getValue(std::to_string(i + 1), readMe);
_specsOfInterest[i] = readMe;
specsOfInterestDictionary.getValue(std::to_string(n + 1), readMe);
_specsOfInterest[n] = readMe;
}
ghoul::Dictionary convertDictionary;
typeDictionary.getValue(keyConvert, convertDictionary);
@@ -95,70 +93,185 @@ LabelParser::LabelParser(const std::string& fileName,
};
}
}
for (auto t : _fileTranslation){
std::cout << t.first << std::endl;
for (auto b : t.second->getTranslation()){
std::cout << " " << b << std::endl;
}
std::string LabelParser::decode(std::string line){
for (auto key : _fileTranslation){
std::size_t value = line.find(key.first);
if (value != std::string::npos){
std::string toTranslate = line.substr(value);
return _fileTranslation[toTranslate]->getTranslation()[0]; //lbls always 1:1 -> single value return.
}
}
return "";
}
std::string LabelParser::encode(std::string line) {
for (auto key : _fileTranslation) {
std::size_t value = line.find(key.first);
if (value != std::string::npos) {
//std::cout << line.substr(value) << std::endl;
return line.substr(value);
}
}
return "";
}
void LabelParser::create(){
std::vector<Image> tmp;
auto imageComparer = [](const Image &a, const Image &b)->bool{
return a.startTime < b.startTime;
};
auto targetComparer = [](const std::pair<double, std::string> &a,
const std::pair<double, std::string> &b)->bool{
return a.first < b.first;
};
std::string previousTarget;
std::string lblName = "";
ghoul::filesystem::Directory sequenceDir(_fileName, true);
std::vector<std::string> sequencePaths = sequenceDir.read(true, false); // check inputs
for (auto path : sequencePaths){
//std::cout << path << std::endl;
if (size_t position = path.find_last_of(".") + 1){
if (position != std::string::npos){
ghoul::filesystem::File currentFile(path);
std::string extension = currentFile.fileExtension();
if (extension == "lbl"){ // discovered header file
if (extension == "lbl" || extension == "LBL"){ // discovered header file
std::ifstream file(currentFile.path());
if (!file.good()) LERROR("Failed to open label file '" << currentFile.path() << "'");
int count = 0;
// open up label files
std::string line = "";
double timestamp = 0.0;
bool found = false;
std::string previousSequence;
TimeRange instrumentRange;
do {
std::getline(file, line);
for (auto spec : _specsOfInterest){
auto pos = line.find(spec);
if (pos != std::string::npos){
if (line.substr(0, line.find_first_of(" ")) == "TARGET_NAME"){
/* std::string target = line.substr(line.find("=") + 2, line.find(" "));
target.erase(std::remove(target.begin(), target.end(), '"'), target.end());
for (auto t : _fileTranslation[target]->getTranslation()){
std::cout << t << std::endl;
}*/
}
std::string read = line.substr(0, line.find_first_of(" "));
line.erase(std::remove(line.begin(), line.end(), '"'), line.end());
line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
/* Add more */
if (read == "TARGET_NAME"){
_target = decode(line);
count++;
}
if (read == "INSTRUMENT_HOST_NAME"){
_instrumentHostID = decode(line);
count++;
}
if (read == "INSTRUMENT_ID"){
_instrumentID = decode(line);
lblName = encode(line);
count++;
}
if (read == "DETECTOR_TYPE"){
_detectorType = decode(line);
count++;
}
if (read == "START_TIME"){
std::string start = line.substr(line.find("=") + 2);
start.erase(std::remove(start.begin(), start.end(), ' '), start.end());
openspace::SpiceManager::ref().getETfromDate(start, _startTime);
count++;
getline(file, line);
read = line.substr(0, line.find_first_of(" "));
if (read == "STOP_TIME"){
std::string stop = line.substr(line.find("=") + 2);
stop.erase(std::remove(stop.begin(), stop.end(), ' '), stop.end());
openspace::SpiceManager::ref().getETfromDate(stop, _stopTime);
count++;
}
/*if (timestamp != 0.0){
found = true;
else{
LERROR("Label file " + _fileName + " deviates from generic standard!");
LINFO("Please make sure input data adheres to format https://pds.jpl.nasa.gov/documents/qs/labels.html");
}
}
if (count == _specsOfInterest.size()){
count = 0;
std::string ext = "jpg";
path.replace(path.begin() + position, path.end(), ext);
bool fileExists = FileSys.fileExists(path);
if (fileExists) {
// createImage(tmp, timestamp, "NH_LORRI", "", path); /// fix active instrument!
// std::sort(tmp.begin(), tmp.end(), imageComparer);
if (!fileExists) {
ext = "JPG";
path.replace(path.begin() + position, path.end(), ext);
fileExists = FileSys.fileExists(path);
}
}*/
if (fileExists) {
Image image;
std::vector<std::string> spiceInstrument;
spiceInstrument.push_back(_instrumentID);
createImage(image, _startTime, _startTime, spiceInstrument, _target, path);
_subsetMap[image.target]._subset.push_back(image);
_subsetMap[image.target]._range.setRange(_startTime);
_captureProgression.push_back(_startTime);
std::stable_sort(_captureProgression.begin(), _captureProgression.end());
}
}
} while (!file.eof() && found == false);
} while (!file.eof());
}
}
}
}
int pause;
std::cin >> pause;
std::vector<Image> tmp;
for (auto key : _subsetMap){
for (auto image : key.second._subset){
tmp.push_back(image);
}
}
std::sort(tmp.begin(), tmp.end(), imageComparer);
for (auto image : tmp){
if (previousTarget != image.target){
previousTarget = image.target;
std::pair<double, std::string> v_target = std::make_pair(image.startTime, image.target);
_targetTimes.push_back(v_target);
std::sort(_targetTimes.begin(), _targetTimes.end(), targetComparer);
}
}
std::ofstream myfile;
myfile.open("LabelFileOutput.txt");
//print all
for (auto target : _subsetMap){
_instrumentTimes.push_back(std::make_pair(lblName, _subsetMap[target.first]._range));
std::string min, max;
SpiceManager::ref().getDateFromET(target.second._range._min, min);
SpiceManager::ref().getDateFromET(target.second._range._max, max);
myfile << std::endl;
for (auto image : target.second._subset){
std::string time_beg;
std::string time_end;
SpiceManager::ref().getDateFromET(image.startTime, time_beg);
SpiceManager::ref().getDateFromET(image.stopTime, time_end);
myfile << std::fixed
<< " " << time_beg
<< "-->" << time_end
<< " [ " << image.startTime
<< " ] " << image.target << std::setw(10);
for (auto instrument : image.activeInstruments){
myfile << " " << instrument;
}
myfile << std::endl;
}
}
myfile.close();
}
void LabelParser::createImage(Image& image, double startTime, double stopTime, std::vector<std::string> instr, std::string targ, std::string pot) {
+98 -1
View File
@@ -24,7 +24,7 @@
// open space includes
#include <openspace/util/powerscaledsphere.h>
#include <openspace/util/spicemanager.h>
#include <ghoul/logging/logmanager.h>
#define _USE_MATH_DEFINES
@@ -125,6 +125,103 @@ PowerScaledSphere::PowerScaledSphere(const PowerScaledScalar& radius, int segmen
}
}
// Alternative Constructor for using accurate triaxial ellipsoid
PowerScaledSphere::PowerScaledSphere(properties::Vec4Property &radius, int segments, std::string planetName)
: _vaoID(0)
, _vBufferID(0)
, _iBufferID(0)
, _isize(6 * segments * segments)
, _vsize((segments + 1) * (segments + 1))
, _varray(new Vertex[_vsize])
, _iarray(new int[_isize])
{
static_assert(sizeof(Vertex) == 64,
"The size of the Vertex needs to be 64 for performance");
float a, b, c, powerscale;
bool accutareRadius = SpiceManager::ref().getPlanetEllipsoid(planetName, a, b, c);
if (accutareRadius) {
PowerScaledCoordinate powerScaledRadii = psc::CreatePowerScaledCoordinate(a, b, c);
powerScaledRadii[3] += 3; // SPICE returns radii in km
std::swap(powerScaledRadii[1], powerScaledRadii[2]); // c is equivalent to y in our coordinate system
radius.set(powerScaledRadii.vec4());
a = powerScaledRadii[0];
b = powerScaledRadii[1];
c = powerScaledRadii[2];
powerscale = powerScaledRadii[3];
}
else {
boost::any r = radius.get();
glm::vec4 modRadius = boost::any_cast<glm::vec4>(r);
a = modRadius[0];
b = modRadius[1];
c = modRadius[2];
powerscale = modRadius[3];
}
int nr = 0;
const float fsegments = static_cast<float>(segments);
for (int i = 0; i <= segments; i++) {
// define an extra vertex around the y-axis due to texture mapping
for (int j = 0; j <= segments; j++) {
const float fi = static_cast<float>(i);
const float fj = static_cast<float>(j);
// inclination angle (north to south)
const float theta = fi * float(M_PI) / fsegments; // 0 -> PI
// azimuth angle (east to west)
const float phi = fj * float(M_PI) * 2.0f / fsegments; // 0 -> 2*PI
const float x = a * sin(phi) * sin(theta); //
const float y = b * cos(theta); // up
const float z = c * cos(phi) * sin(theta); //
_varray[nr].location[0] = x;
_varray[nr].location[1] = y;
_varray[nr].location[2] = z;
_varray[nr].location[3] = powerscale;
glm::vec3 normal = glm::vec3(x, y, z);
if (!(x == 0.f && y == 0.f && z == 0.f))
normal = glm::normalize(normal);
_varray[nr].normal[0] = normal[0];
_varray[nr].normal[1] = normal[1];
_varray[nr].normal[2] = normal[2];
const float t1 = fj / fsegments;
const float t2 = fi / fsegments;
_varray[nr].tex[0] = t1;
_varray[nr].tex[1] = t2;
++nr;
}
}
nr = 0;
// define indices for all triangles
for (int i = 1; i <= segments; ++i) {
for (int j = 0; j < segments; ++j) {
const int t = segments + 1;
_iarray[nr] = t * (i - 1) + j + 0; //1
++nr;
_iarray[nr] = t * (i + 0) + j + 0; //2
++nr;
_iarray[nr] = t * (i + 0) + j + 1; //3
++nr;
_iarray[nr] = t * (i - 1) + j + 0; //4
++nr;
_iarray[nr] = t * (i + 0) + j + 1; //5
++nr;
_iarray[nr] = t * (i - 1) + j + 1; //6
++nr;
}
}
}
PowerScaledSphere::PowerScaledSphere(const PowerScaledSphere& cpy)
: _vaoID(cpy._vaoID)
, _vBufferID(cpy._vBufferID)
+4
View File
@@ -46,4 +46,8 @@ std::vector<std::string> ScannerDecoder::getSpiceIDs(){
return _spiceIDs;
}
void ScannerDecoder::setStopCommand(std::string stopCommand){
_abort = stopCommand;
}
} // namespace openspace
+399 -159
View File
@@ -31,6 +31,8 @@
#include <algorithm>
#define MAXOBJ 1000
#define WINSIZ 10000
namespace {
const std::string _loggerCat = "SpiceManager";
@@ -75,6 +77,7 @@ SpiceManager::KernelIdentifier SpiceManager::loadKernel(const std::string& fileP
}
std::string&& path = absPath(filePath);
if (!FileSys.fileExists(path)) {
LERROR("Kernel file '" << path << "' does not exist");
return KernelFailed;
@@ -112,7 +115,16 @@ SpiceManager::KernelIdentifier SpiceManager::loadKernel(const std::string& fileP
LINFO("Loading SPICE kernel '" << path << "'");
// Load the kernel
furnsh_c(path.c_str());
std::string fileExtension = path.substr(path.size() - 3);
if (fileExtension == ".bc" || fileExtension == ".BC") { // binary ck kernel
findCkCoverage(path);
}
else if (fileExtension == "bsp" || fileExtension == "BSP") { // binary spk kernel
findSpkCoverage(path);
}
// Reset the current directory to the previous one
FileSys.setCurrentDirectory(currentDirectory);
int failed = failed_c();
@@ -135,6 +147,111 @@ SpiceManager::KernelIdentifier SpiceManager::loadKernel(const std::string& fileP
}
}
bool SpiceManager::findCkCoverage(std::string& path) {
SpiceInt frame, numberOfIntervals;
SpiceDouble b, e;
std::pair <double, double> tempInterval;
SPICEINT_CELL(ids, MAXOBJ);
SPICEDOUBLE_CELL(cover, WINSIZ);
ckobj_c(path.c_str(), &ids);
for (SpiceInt i = 0; i < card_c(&ids); ++i) {
frame = SPICE_CELL_ELEM_I(&ids, i);
scard_c(0, &cover);
ckcov_c(path.c_str(), frame, SPICEFALSE, "SEGMENT", 0.0, "TDB", &cover);
//Get the number of intervals in the coverage window.
numberOfIntervals = wncard_c(&cover);
for (SpiceInt j = 0; j < numberOfIntervals; ++j) {
//Get the endpoints of the jth interval.
wnfetd_c(&cover, j, &b, &e);
tempInterval = std::make_pair(b, e);
_ckCoverageTimes[frame].insert(e);
_ckCoverageTimes[frame].insert(b);
_ckIntervals[frame].push_back(tempInterval);
}
}
return true;
}
bool SpiceManager::findSpkCoverage(std::string& path) {
SpiceInt obj, numberOfIntervals;
SpiceDouble b, e;
std::pair <double, double> tempInterval;
SPICEINT_CELL(ids, MAXOBJ);
SPICEDOUBLE_CELL(cover, WINSIZ);
spkobj_c(path.c_str(), &ids);
for (SpiceInt i = 0; i < card_c(&ids); ++i) {
obj = SPICE_CELL_ELEM_I(&ids, i);
scard_c(0, &cover);
spkcov_c(path.c_str(), obj, &cover);
//Get the number of intervals in the coverage window.
numberOfIntervals = wncard_c(&cover);
for (SpiceInt j = 0; j < numberOfIntervals; ++j) {
//Get the endpoints of the jth interval.
wnfetd_c(&cover, j, &b, &e);
tempInterval = std::make_pair(b, e);
//insert all into coverage time set, the windows could be merged @AA
_spkCoverageTimes[obj].insert(e);
_spkCoverageTimes[obj].insert(b);
_spkIntervals[obj].push_back(tempInterval);
}
}
return true;
}
bool SpiceManager::hasSpkCoverage(std::string target, double& et) const
{
int id;
bool idSuccess = getNaifId(target, id);
bool hasCoverage = false;
std::vector< std::pair<double, double> > intervalVector;
if (_spkIntervals.find(id) == _spkIntervals.end())
return false;
else
intervalVector = _spkIntervals.find(id)->second;
for (auto vecElement : intervalVector) {
if (vecElement.first < et && vecElement.second > et) {
hasCoverage = true;
return idSuccess && hasCoverage;
}
}
return idSuccess && hasCoverage;
}
bool SpiceManager::hasCkCoverage(std::string frame, double& et) const
{
int id;
bool idSuccess = getFrameId(frame, id);
bool hasCoverage = false;
std::vector< std::pair<double, double> > intervalVector;
if (_ckIntervals.find(id) == _ckIntervals.end())
return false;
else
intervalVector = _ckIntervals.find(id)->second;
for (auto vecElement : intervalVector) {
if (vecElement.first < et && vecElement.second > et) {
hasCoverage = true;
return idSuccess && hasCoverage;
}
}
return idSuccess && hasCoverage;
}
void SpiceManager::unloadKernel(KernelIdentifier kernelId) {
auto it = std::find_if(_loadedKernels.begin(), _loadedKernels.end(),
[&kernelId](const KernelInformation& info) { return info.id == kernelId ; });
@@ -209,6 +326,20 @@ bool SpiceManager::getNaifId(const std::string& body, int& id) const {
}
}
bool SpiceManager::getFrameId(const std::string& frame, int& id) const {
if (frame.empty()) {
LERROR("No frame was provided");
return false;
}
else {
SpiceInt sid = id;
namfrm_c(frame.c_str(), &sid);
id = sid;
bool hasError = SpiceManager::checkForError("Error getting id for frame '" + frame + "'");
return !hasError;
}
}
bool getValueInternal(const std::string& body, const std::string& value, int S,
double* v)
{
@@ -294,7 +425,7 @@ bool SpiceManager::getETfromDate(const std::string& timeString,
}
bool SpiceManager::getDateFromET(double ephemerisTime, std::string& date,
const std::string& format)
const std::string& format) const
{
static const int BufferSize = 256;
@@ -322,15 +453,32 @@ bool SpiceManager::getTargetPosition(const std::string& target,
glm::dvec3& position,
double& lightTime) const
{
spkpos_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), glm::value_ptr(position),
&lightTime);
psc pscPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(position[0], position[1], position[2]);
bool hasError = checkForError("Error retrieving position of target '" + target + "'" +
" viewed from observer '" + observer + "' in reference"+
" frame '" + referenceFrame + "' at time '" +
std::to_string(ephemerisTime) + "'");
return !hasError;
bool targetHasCoverage = hasSpkCoverage(target, ephemerisTime);
bool observerHasCoverage = hasSpkCoverage(observer, ephemerisTime);
if (!targetHasCoverage && !observerHasCoverage){
return false;
}
else if (targetHasCoverage && observerHasCoverage){
spkpos_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), glm::value_ptr(position),
&lightTime);
}
else if (targetHasCoverage) {// observer has no coverage
getEstimatedPosition(ephemerisTime, observer, target, pscPosition);
pscPosition = pscPosition*(-1.f); // inverse estimated position because the observer is "target" argument in funciton
position = pscPosition.vec3();
}
else { // target has no coverage
getEstimatedPosition(ephemerisTime, target, observer, pscPosition);
position = pscPosition.vec3();
}
if (position[0] == 0.0 || position[1] == 0.0 || position[2] == 0.0)
return false;
return targetHasCoverage && observerHasCoverage;
}
bool SpiceManager::getTargetPosition(const std::string& target,
@@ -343,22 +491,103 @@ bool SpiceManager::getTargetPosition(const std::string& target,
{
double pos[3] = { 0.0, 0.0, 0.0};
spkpos_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), pos, &lightTime);
if (pos[0] == 0.0 || pos[1] == 0.0|| pos[2] == 0.0)
bool targetHasCoverage = hasSpkCoverage(target, ephemerisTime);
bool observerHasCoverage = hasSpkCoverage(observer, ephemerisTime);
if (!targetHasCoverage && !observerHasCoverage){
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(pos[0], pos[1], pos[2]);
return false;
}
else if (targetHasCoverage && observerHasCoverage){
spkpos_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), pos, &lightTime);
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(pos[0], pos[1], pos[2]);
}
else if (targetHasCoverage) {// observer has no coverage
getEstimatedPosition(ephemerisTime, observer, target, position);
position = position*(-1.f); // inverse estimated position because the observer is "target" argument in funciton
}
else {// target has no coverage
getEstimatedPosition(ephemerisTime, target, observer, position);
}
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(pos[0], pos[1], pos[2]);
return targetHasCoverage && observerHasCoverage;
}
return true;
bool SpiceManager::getEstimatedPosition(const double time, const std::string target,
const std::string observer, psc& targetPosition) const
{
int idTarget, idObserver;
bool targetFound = getNaifId(target, idTarget);
if (idTarget == 0) { //SOLAR SYSTEM BARYCENTER special case, no def. in kernels
targetPosition[0] = 0.f;
targetPosition[1] = 0.f;
targetPosition[2] = 0.f;
targetPosition[3] = 0.f;
return true;
}
double pos[3] = { 0.0, 0.0, 0.0 };
bool observerFound = getNaifId(observer, idObserver);
if (!targetFound || !observerFound || (idTarget == idObserver)) {
return false;
}
double lt, earlier, later, difference, quote;
double pos_earlier[3] = { 0.0, 0.0, 0.0 };
double pos_later[3] = { 0.0, 0.0, 0.0 };
if (_spkCoverageTimes.find(idTarget) == _spkCoverageTimes.end()){ // no coverage
LWARNING("No position for " + target + " at any time, was the correct SPK Kernels loaded?");
targetPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(pos[0], pos[1], pos[2]);
return false;
}
std::set<double> coveredTimes = _spkCoverageTimes.find(idTarget)->second;
std::set<double>::iterator first = coveredTimes.begin();
std::set<double>::iterator last = coveredTimes.end();
if (coveredTimes.lower_bound(time) == first) { // coverage later, fetch first position
spkpos_c(target.c_str(), (*first), "GALACTIC",
"NONE", observer.c_str(), pos, &lt);
}
else if (coveredTimes.upper_bound(time) == last) { // coverage earlier, fetch last position
spkpos_c(target.c_str(), *(coveredTimes.rbegin()), "GALACTIC",
"NONE", observer.c_str(), pos, &lt);
}
else { // coverage both earlier and later, interpolate these positions
earlier = *std::prev((coveredTimes.lower_bound(time)));
later = *(coveredTimes.upper_bound(time));
spkpos_c(target.c_str(), earlier, "GALACTIC",
"NONE", observer.c_str(), pos_earlier, &lt);
spkpos_c(target.c_str(), later, "GALACTIC",
"NONE", observer.c_str(), pos_later, &lt);
//linear interpolation
difference = later - earlier;
quote = (time - earlier) / difference;
pos[0] = (pos_earlier[0]*(1-quote) + pos_later[0]*quote);
pos[1] = (pos_earlier[1]*(1-quote) + pos_later[1]*quote);
pos[2] = (pos_earlier[2]*(1-quote) + pos_later[2]*quote);
}
targetPosition = PowerScaledCoordinate::CreatePowerScaledCoordinate(pos[0], pos[1], pos[2]);
checkForError("Error estimating positin for target: " + target + ", or observer: " + observer);
return targetFound && observerFound;
}
// do NOT remove this method.
bool SpiceManager::frameConversion(glm::dvec3& v, const std::string& from, const std::string& to, double ephemerisTime) const{
glm::dmat3 transform;
if (from == to)
return true;
// get rotation matrix from frame A - frame B
pxform_c(from.c_str(), to.c_str(), ephemerisTime, (double(*)[3])glm::value_ptr(transform));
bool hasError = checkForError("Error converting from frame '" + from +
"' to frame '" + to + "' at time " + std::to_string(ephemerisTime));
if (hasError)
@@ -384,7 +613,6 @@ bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
bool& isVisible
) const
{
int visible;
fovtrg_c(instrument.c_str(),
target.c_str(),
@@ -413,13 +641,12 @@ bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
int visible;
std::string bodyfixed = "IAU_";
bodyfixed += target;
std::string frame = frameFromBody(target);
fovtrg_c(instrument.c_str(),
target.c_str(),
method.c_str(),
bodyfixed.c_str(),
frame.c_str(),
aberrationCorrection.c_str(),
observer.c_str(),
&targetEpoch,
@@ -460,9 +687,9 @@ bool SpiceManager::getSurfaceIntercept(const std::string& target,
// allow client specify non-inertial frame.
std::string bodyfixed = "IAU_";
convert = (referenceFrame.find(bodyfixed) == std::string::npos);
if (convert){
bodyfixed += target;
}else{
if (convert) {
bodyfixed = frameFromBody(target);
} else {
bodyfixed = referenceFrame;
}
@@ -500,6 +727,7 @@ bool SpiceManager::getSurfaceIntercept(const std::string& target,
return true;
}
// Not called at the moment @AA
bool SpiceManager::getTargetState(const std::string& target,
const std::string& observer,
const std::string& referenceFrame,
@@ -525,6 +753,7 @@ bool SpiceManager::getTargetState(const std::string& target,
return !hasError;
}
// Not called at the moment @AA
bool SpiceManager::getTargetState(const std::string& target,
const std::string& observer,
const std::string& referenceFrame,
@@ -540,12 +769,25 @@ bool SpiceManager::getTargetState(const std::string& target,
spkezr_c(target.c_str(), ephemerisTime, referenceFrame.c_str(),
aberrationCorrection.c_str(), observer.c_str(), state, &lightTime);
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[0], state[1], state[2]);
velocity = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[3], state[4], state[5]);
bool hasError = checkForError("Error retrieving state of target '" + target + "'" +
"viewed from observer '" + observer + "' in " +
"reference frame '" + referenceFrame + "' at time '" +
std::to_string(ephemerisTime) + "'");
return true;
if (!hasError) {
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[0], state[1], state[2]);
velocity = PowerScaledCoordinate::CreatePowerScaledCoordinate(state[3], state[4], state[5]);
}
else
{
position = PowerScaledCoordinate::CreatePowerScaledCoordinate(0.0, 0.0, 0.0);
velocity = PowerScaledCoordinate::CreatePowerScaledCoordinate(0, 0, 0);
}
return !hasError;
}
// Not called at the moment @AA
bool SpiceManager::getStateTransformMatrix(const std::string& fromFrame,
const std::string& toFrame,
double ephemerisTime,
@@ -560,58 +802,105 @@ bool SpiceManager::getStateTransformMatrix(const std::string& fromFrame,
return !hasError;
}
// I honestly dont even think we need this, deprecatable relic from previous crunch time.
bool SpiceManager::getPositionPrimeMeridian(const std::string& fromFrame,
const std::string& body,
double ephemerisTime,
glm::dmat3& positionMatrix) const{
int id;
getNaifId(body, id);
tipbod_c(fromFrame.c_str(), id, ephemerisTime, (double(*)[3])glm::value_ptr(positionMatrix));
bool hasError = checkForError("Error retrieving position transform matrix from "
"frame '" + fromFrame + "' to frame '" + body +
"at time '" + std::to_string(ephemerisTime) + "' for prime meridian");
positionMatrix = glm::transpose(positionMatrix);
return !hasError;
}
bool SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
const std::string& toFrame,
double ephemerisTime,
glm::dmat3& positionMatrix) const{
glm::dmat3& positionMatrix) const
{
bool success = false, estimated = false;
pxform_c(fromFrame.c_str(), toFrame.c_str(),
ephemerisTime, (double(*)[3])glm::value_ptr(positionMatrix));
bool hasError = checkForError("Error retrieving position transform matrix from "
"frame '" + fromFrame + "' to frame '" + toFrame +
"' at time '" + std::to_string(ephemerisTime) + "'");
ephemerisTime, (double(*)[3])glm::value_ptr(positionMatrix));
success = !(failed_c());
if (!success) {
reset_c();
estimated = getEstimatedTransformMatrix(ephemerisTime, fromFrame, toFrame, positionMatrix);
}
if (_showErrors) {
bool hasError = checkForError("Error retrieving position transform matrix from "
"frame '" + fromFrame + "' to frame '" + toFrame +
"' at time '" + std::to_string(ephemerisTime));
}
positionMatrix = glm::transpose(positionMatrix);
return !hasError;
return estimated || success;
}
// Not called at the moment @AA
bool SpiceManager::getPositionTransformMatrix(const std::string& fromFrame,
const std::string& toFrame,
double ephemerisTimeFrom,
double ephemerisTimeTo,
glm::dmat3& positionMatrix) const{
const std::string& toFrame,
double ephemerisTimeFrom,
double ephemerisTimeTo,
glm::dmat3& positionMatrix) const{
pxfrm2_c(fromFrame.c_str(), toFrame.c_str(), ephemerisTimeFrom, ephemerisTimeTo, (double(*)[3])glm::value_ptr(positionMatrix));
bool hasError = checkForError("Error retrieving position transform matrix from "
"frame '" + fromFrame + "' to frame '" + toFrame +
"' from time '" + std::to_string(ephemerisTimeFrom) + " to time '"
+ std::to_string(ephemerisTimeTo) + "'");
+ std::to_string(ephemerisTimeTo) + "'");
positionMatrix = glm::transpose(positionMatrix);
return !hasError;
}
bool SpiceManager::getEstimatedTransformMatrix(const double time, const std::string fromFrame,
const std::string toFrame, glm::dmat3& positionMatrix) const
{
int idFrame;
bool frameFound = getFrameId(fromFrame, idFrame);
if (!frameFound) {
return false;
}
if (_ckCoverageTimes.find(idFrame) == _ckCoverageTimes.end()){ // no coverage
return false;
}
double earlier, later, difference, quote;
std::set<double> coveredTimes = _ckCoverageTimes.find(idFrame)->second;
std::set<double>::iterator first = coveredTimes.begin();
std::set<double>::iterator last = coveredTimes.end();
if (coveredTimes.lower_bound(time) == first) { // coverage later, fetch first transform
pxform_c(fromFrame.c_str(), toFrame.c_str(),
*first, (double(*)[3])glm::value_ptr(positionMatrix));
}
else if (coveredTimes.upper_bound(time) == last) { // coverage earlier, fetch last transform
pxform_c(fromFrame.c_str(), toFrame.c_str(),
*(coveredTimes.rbegin()), (double(*)[3])glm::value_ptr(positionMatrix));
}
else { // coverage both earlier and later, interpolate these transformations
earlier = *std::prev((coveredTimes.lower_bound(time)));
later = *(coveredTimes.upper_bound(time));
glm::dmat3 earlierTransform, laterTransform;
pxform_c(fromFrame.c_str(), toFrame.c_str(),
earlier, (double(*)[3])glm::value_ptr(earlierTransform));
pxform_c(fromFrame.c_str(), toFrame.c_str(),
later, (double(*)[3])glm::value_ptr(laterTransform));
difference = later - earlier;
quote = (time - earlier) / difference;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
positionMatrix[i][j] = (earlierTransform[i][j] * (1 - quote) + laterTransform[i][j] * quote);
}
}
}
bool hasError = checkForError("Error estimating transform matrix from frame: "
+ fromFrame + ", to frame: " + toFrame);
return !hasError;
}
bool SpiceManager::getFieldOfView(const std::string& instrument, std::string& fovShape,
std::string& frameName, glm::dvec3& boresightVector,
std::vector<glm::dvec3>& bounds) const
@@ -649,6 +938,7 @@ bool SpiceManager::getFieldOfView(int instrument,
&nrReturned, // the number of array values returned for the bounds
(double(*)[3])boundsArr // the bounds
);
bool hasError = checkForError("Error getting Field-of-View parameters for "
"instrument '" + std::to_string(instrument) + "'");
if (hasError)
@@ -667,127 +957,77 @@ bool SpiceManager::getFieldOfView(int instrument,
return true;
}
bool SpiceManager::geographicToRectangular(const std::string& body,
double longitude,
double latitude,
glm::dvec3& coordinates) const
{
int id;
bool success = getNaifId(body, id);
if (!success)
return false;
std::string SpiceManager::frameFromBody(const std::string body) const {
for (auto pair : _frameByBody) {
if (pair.first == body) {
return pair.second;
}
}
std::string unionPrefix = "IAU_";
std::string frame = "";
if (body.find(unionPrefix) == std::string::npos)
frame = unionPrefix + body;
else
return geographicToRectangular(id, longitude, latitude, coordinates);
frame = body;
return frame;
}
bool SpiceManager::geographicToRectangular(int id, double longitude, double latitude,
glm::dvec3& coordinates) const
{
srfrec_c(id, longitude*rpd_c(), latitude*rpd_c(), glm::value_ptr(coordinates));
bool hasError = checkForError("Error transforming geographic coordinates for '" +
std::to_string(id) + "'");
return !hasError;
}
bool SpiceManager::getSubObserverPoint(const std::string& target,
const std::string& observer,
const std::string& computationMethod,
const std::string& bodyFixedFrame,
const std::string& aberrationCorrection,
double ephemerisTime,
glm::dvec3& subObserverPoint,
double& targetEphemerisTime,
glm::dvec3& vectorToSurfacePoint) const
{
if (target.empty()) {
LERROR("No target was provided");
bool SpiceManager::addFrame(const std::string body, const std::string frame) {
if (body == "" || frame == "")
return false;
else {
_frameByBody.push_back(std::make_pair(body, frame));
return true;
}
if (observer.empty()) {
LERROR("No observer was provided");
return false;
}
if (computationMethod.empty()) {
LERROR("No computation method was provided");
return false;
}
if (bodyFixedFrame.empty()) {
LERROR("No body fixed frame was provided");
return false;
}
if (aberrationCorrection.empty()) {
LERROR("No aberration correction was provided");
return false;
}
subpnt_c(computationMethod.c_str(),
target.c_str(),
ephemerisTime,
bodyFixedFrame.c_str(),
aberrationCorrection.c_str(),
observer.c_str(),
glm::value_ptr(subObserverPoint),
&targetEphemerisTime,
glm::value_ptr(vectorToSurfacePoint)
);
bool hasError = checkForError("Error retrieving subobserver point on target '" +
target + "' of observer '" + observer + "' for computation method '" +
computationMethod + "' and body fixed frame '" + bodyFixedFrame + "'");
return !hasError;
}
void SpiceManager::applyTransformationMatrix(glm::dvec3& position,
glm::dvec3& velocity,
const TransformMatrix& transformationMatrix)
{
double input[6];
double output[6];
memmove(input, glm::value_ptr(position), 3 * sizeof(glm::dvec3::value_type));
memmove(input + 3, glm::value_ptr(velocity), 3 * sizeof(glm::dvec3::value_type));
mxvg_c(transformationMatrix.data(), input, 6, 6, output);
memmove(glm::value_ptr(position), output, 3 * sizeof(glm::dvec3::value_type));
memmove(glm::value_ptr(velocity), output + 3, 3 * sizeof(glm::dvec3::value_type));
}
bool SpiceManager::checkForError(std::string errorMessage) {
int failed = failed_c();
if (failed) {
if (failed && _showErrors) {
static char msg[1024];
if (!errorMessage.empty()) {
getmsg_c("LONG", 1024, msg);
LERROR(errorMessage);
LERROR("Spice reported: " + std::string(msg));
LWARNING(errorMessage);
LWARNING("Spice reported: " + std::string(msg));
}
reset_c();
return true;
}
else if (failed) {
reset_c();
return false;
}
else
return false;
}
//bool SpiceManager::getSubSolarPoint(std::string computationMethod,
// std::string target,
// double ephemeris,
// std::string bodyFixedFrame,
// std::string aberrationCorrection,
// std::string observer,
// glm::dvec3& subSolarPoint,
// double& targetEpoch,
// glm::dvec3& vectorToSurfacePoint) const{
// double subPoint[3], vecToSurf[3];
//
// subslr_c(computationMethod.c_str(),
// target.c_str(),
// ephemeris,
// bodyFixedFrame.c_str(),
// aberrationCorrection.c_str(),
// observer.c_str(), subPoint, &targetEpoch, vecToSurf);
//
// memcpy(&subSolarPoint, subPoint, sizeof(double)* 3);
// memcpy(&vectorToSurfacePoint, vecToSurf, sizeof(double)* 3);
//
// return true;
//}
bool SpiceManager::getPlanetEllipsoid(std::string planetName, float &a, float &b, float &c) {
SpiceDouble radii[3];
SpiceInt n;
int id;
getNaifId(planetName, id);
if (bodfnd_c(id, "RADII")) {
bodvrd_c(planetName.c_str(), "RADII", 3, &n, radii);
a = static_cast<float>(radii[0]);
b = static_cast<float>(radii[1]);
c = static_cast<float>(radii[2]);
}
else {
LWARNING("Could not find SPICE data for the shape of " + planetName + ", using modfile value");
a = 1.f;
b = 1.f;
c = 1.f;
}
bool hasError = checkForError("Error retrieving planet radii of " + planetName);
return !hasError;
}
}
@@ -28,11 +28,13 @@ if (OPENSPACE_HAVE_TESTS)
include_directories("${GHOUL_ROOT_DIR}/ext/gtest/include")
include_directories("${GHOUL_ROOT_DIR}/include")
file(GLOB_RECURSE OPENSPACE_TEST_FILES ${HEADER_ROOT_DIR}/openspace/tests/*.inl)
include_directories("${OPENSPACE_BASE_DIR}/tests")
include_directories("${OPENSPACE_BASE_DIR}/include")
file(GLOB_RECURSE OPENSPACE_TEST_FILES ${OPENSPACE_BASE_DIR}/tests/*.inl)
source_group(OpenSpaceSource FILES ${OPENSPACE_SOURCE} ${OPENSPACE_HEADER})
source_group(Tests FILES ${OPENSPACE_TEST_FILES})
add_executable(OpenSpaceTest ${SOURCE_ROOT_DIR}/tests/main.cpp ${OPENSPACE_TEST_FILES} ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE})
add_executable(OpenSpaceTest ${OPENSPACE_BASE_DIR}/tests/main.cpp ${OPENSPACE_TEST_FILES} ${OPENSPACE_HEADER} ${OPENSPACE_SOURCE})
target_link_libraries(OpenSpaceTest gtest ${DEPENDENT_LIBS})
endif (OPENSPACE_HAVE_TESTS)
@@ -0,0 +1,10 @@
return {
{
Name = "CircularDependency1",
Parent = "CircularDependency2"
},
{
Name = "CircularDependency2",
Parent = "CircularDependency1"
}
}
@@ -0,0 +1,6 @@
return {
{
Name = "CommonDependency",
Parent = "Common"
}
}
@@ -0,0 +1,6 @@
return {
{
Name = "Common",
Parent = "Root",
},
}
@@ -0,0 +1,6 @@
return {
{
Name = "DirectDependency",
Parent = "NoDependency"
}
}
@@ -0,0 +1,2 @@
-- Malformed script
a
@@ -0,0 +1,8 @@
-- Malformed script
return {
ScenePath = "foobar",
CommonFolder = "",
Modules = {
}
}
@@ -0,0 +1,7 @@
-- Malformed script
return {
ScenePath = ".",
Modules = {
}
}
@@ -0,0 +1,8 @@
-- Malformed script
return {
ScenePath = ".",
CommonFolder = "nonexisting",
Modules = {
}
}
@@ -0,0 +1,8 @@
-- Malformed script
return {
ScenePath = ".",
CommonFolder = 2,
Modules = {
}
}
@@ -0,0 +1,9 @@
return {
{
Name = "MultipleDependencies",
Parent = "NoDependency",
Dependency = {
"DirectDependency"
}
}
}
@@ -0,0 +1,6 @@
return {
{
Name = "NoDependency",
Parent = "Root"
}
}
@@ -0,0 +1,6 @@
return {
{
Name = "CommonDependency",
Parent = "Common"
}
}
@@ -0,0 +1,6 @@
return {
{
Name = "Common",
Parent = "Root",
},
}

Some files were not shown because too many files have changed in this diff Show More