From 8becbbde41cd365abef884c30184935a90d78f7d Mon Sep 17 00:00:00 2001 From: Michal Marcinkowski Date: Wed, 22 Apr 2015 21:53:28 -0400 Subject: [PATCH] Imagesequencer update: - label/image data works - fixed issues with instrument firing - read handled in more uniform way - adding ALICE scanner - distance fading in renderabletrail (WIP) - essential fixes to renderableFOV - and additional changes to other classes reliant on imagesequenser. --- .../openspace/rendering/model/modelgeometry.h | 2 + .../rendering/model/renderablemodel.h | 4 +- .../rendering/model/wavefrontgeometry.h | 2 + .../planets/renderableplanetprojection.h | 3 +- include/openspace/rendering/renderablefov.h | 4 +- include/openspace/rendering/renderabletrail.h | 2 + include/openspace/util/imagesequencer2.h | 168 ++++++++++++---- include/openspace/util/instrumentdecoder.h | 2 + include/openspace/util/labelparser.h | 76 +++---- include/openspace/util/scannerdecoder.h | 3 + include/openspace/util/sequenceparser.h | 2 +- openspace-data | 2 +- scripts/default_startup.lua | 4 +- shaders/fboPass_fs.glsl | 7 +- shaders/modules/trails/ephemeris_fs.glsl | 3 +- src/engine/openspaceengine.cpp | 2 - src/rendering/model/renderablemodel.cpp | 75 ++++--- src/rendering/model/wavefrontgeometry.cpp | 7 +- .../planets/renderableplanetprojection.cpp | 52 ++--- src/rendering/renderablefov.cpp | 17 +- src/rendering/renderabletrail.cpp | 23 +++ src/rendering/renderengine.cpp | 122 +++++------- src/scenegraph/spiceephemeris.cpp | 13 +- src/util/hongkangparser.cpp | 71 +++++-- src/util/imagesequencer.cpp | 1 - src/util/imagesequencer2.cpp | 187 +++++++++++------- src/util/instrumentdecoder.cpp | 11 ++ src/util/labelparser.cpp | 155 ++++++++++++--- src/util/scannerdecoder.cpp | 4 + 29 files changed, 673 insertions(+), 351 deletions(-) diff --git a/include/openspace/rendering/model/modelgeometry.h b/include/openspace/rendering/model/modelgeometry.h index 75d13d8e20..d5ecd64b2d 100644 --- a/include/openspace/rendering/model/modelgeometry.h +++ b/include/openspace/rendering/model/modelgeometry.h @@ -42,6 +42,8 @@ public: virtual bool initialize(RenderableModel* parent); virtual void deinitialize(); virtual void render() = 0; + virtual void changeRenderMode(const GLenum mode) = 0; + protected: RenderableModel* _parent; diff --git a/include/openspace/rendering/model/renderablemodel.h b/include/openspace/rendering/model/renderablemodel.h index 2329c609ea..35784c2a3b 100644 --- a/include/openspace/rendering/model/renderablemodel.h +++ b/include/openspace/rendering/model/renderablemodel.h @@ -63,7 +63,6 @@ private: ghoul::opengl::Texture* _texture; ghoul::opengl::Texture* _bumpMap; - modelgeometry::ModelGeometry* _geometry; glm::dmat3 _stateMatrix; @@ -75,8 +74,9 @@ private: properties::BoolProperty _performShading; properties::BoolProperty _performFade; - properties::FloatProperty _fading; + bool _isGhost; + double _time; }; diff --git a/include/openspace/rendering/model/wavefrontgeometry.h b/include/openspace/rendering/model/wavefrontgeometry.h index be9e467205..75d04e8d43 100644 --- a/include/openspace/rendering/model/wavefrontgeometry.h +++ b/include/openspace/rendering/model/wavefrontgeometry.h @@ -40,6 +40,7 @@ public: bool initialize(RenderableModel* parent) override; void deinitialize() override; void render() override; + void changeRenderMode(const GLenum mode); private: struct Vertex { @@ -56,6 +57,7 @@ private: GLuint _vaoID; GLuint _vbo; GLuint _ibo; + GLenum _mode; std::vector _vertices; std::vector _indices; diff --git a/include/openspace/rendering/planets/renderableplanetprojection.h b/include/openspace/rendering/planets/renderableplanetprojection.h index 8ad4369199..e4e96ac17e 100644 --- a/include/openspace/rendering/planets/renderableplanetprojection.h +++ b/include/openspace/rendering/planets/renderableplanetprojection.h @@ -28,7 +28,6 @@ // open space includes #include -#include #include #include @@ -83,11 +82,13 @@ private: properties::StringProperty _colorTexturePath; properties::StringProperty _projectionTexturePath; properties::TriggerProperty _imageTrigger; + 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; diff --git a/include/openspace/rendering/renderablefov.h b/include/openspace/rendering/renderablefov.h index 0fec4870c0..929156e9c5 100644 --- a/include/openspace/rendering/renderablefov.h +++ b/include/openspace/rendering/renderablefov.h @@ -76,9 +76,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 diff --git a/include/openspace/rendering/renderabletrail.h b/include/openspace/rendering/renderabletrail.h index 29f0161359..b5c0bb93ad 100644 --- a/include/openspace/rendering/renderabletrail.h +++ b/include/openspace/rendering/renderabletrail.h @@ -86,6 +86,8 @@ private: float _increment; float _oldTime = 0; + float _time; + float _distanceFade; }; } // namespace openspace diff --git a/include/openspace/util/imagesequencer2.h b/include/openspace/util/imagesequencer2.h index 0e134dd49e..c016e168a8 100644 --- a/include/openspace/util/imagesequencer2.h +++ b/include/openspace/util/imagesequencer2.h @@ -36,6 +36,19 @@ #include 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 + */ class ImageSequencer2 { public: ImageSequencer2(); @@ -43,65 +56,140 @@ 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 time. 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> acronymDictionary, - std::vector potentialTargets); - - // returns upcoming target + /** + * Retrieves the next upcoming target in time. + */ std::pair getNextTarget(); - // returns next target + + /** + * Retrieves the most current target in time. + */ std::pair 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> 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> getActiveInstruments(); - bool ImageSequencer2::getImagePaths(std::vector>& captures, std::string projectee, std::string instrumentID); - bool ImageSequencer2::getImagePaths(std::vector>& captures, std::string projectee); + /* + * Returns a map with key instrument names whose value indicate whether + * an instrument is active or not. + */ + std::map 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>& captures, + std::string projectee, + std::string instrumentID); + + bool ImageSequencer2::getImagePaths(std::vector>& captures, + std::string projectee); + + /* + * returns true if instrumentID is within a capture range. + */ bool instumentActive(std::string instrumentID); - - const Image* findLatestImageInSubset( ImageSubset& subset); + //const Image* findLatestImageInSubset( ImageSubset& subset); private: - //default comparison function - bool imageComparer(const Image &a, const Image &b); - - //binary find O(log n) always - std::vector::iterator binary_find(std::vector::iterator begin, - std::vector::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> _instrumentOnOff; - - std::map _subsetMap; - std::vector> _targetTimes; - std::vector> _instrumentTimes; - std::vector _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 _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 _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 _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> _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> _instrumentTimes; + + /* + * Each consecutive images capture time, for easier traversal. + */ + std::vector _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; + // if no data, no run bool _hasData; }; diff --git a/include/openspace/util/instrumentdecoder.h b/include/openspace/util/instrumentdecoder.h index 41d9b77f7d..d464c3d6ef 100644 --- a/include/openspace/util/instrumentdecoder.h +++ b/include/openspace/util/instrumentdecoder.h @@ -36,8 +36,10 @@ public: InstrumentDecoder(const ghoul::Dictionary& dictionary); virtual std::string getDecoderType(); virtual std::vector getTranslation(); + std::string getStopCommand(); private: std::string _type; + std::string _stopCommand; std::vector _spiceIDs; }; diff --git a/include/openspace/util/labelparser.h b/include/openspace/util/labelparser.h index 220e7b4c3e..738de59552 100644 --- a/include/openspace/util/labelparser.h +++ b/include/openspace/util/labelparser.h @@ -33,44 +33,54 @@ #include namespace openspace { - class LabelParser : public SequenceParser{ - public: - LabelParser(); - LabelParser(const std::string& fileName, - ghoul::Dictionary translationDictionary); - virtual void create(); - virtual std::map getSubsetMap(); - virtual std::vector> getIstrumentTimes(); - virtual std::vector> getTargetTimes(); +class LabelParser : public SequenceParser{ +public: + LabelParser(); + LabelParser(const std::string& fileName, + ghoul::Dictionary translationDictionary); + virtual void create(); + virtual std::map getSubsetMap(); + virtual std::vector> getIstrumentTimes(); + virtual std::vector> getTargetTimes(); - // temporary need to figure this out - std::map getTranslation(){ return _fileTranslation; }; - virtual std::vector getCaptureProgression(){ return _captureProgression; }; + // temporary need to figure this out + std::map getTranslation(){ return _fileTranslation; }; + virtual std::vector getCaptureProgression(){ return _captureProgression; }; - private: - void createImage(Image& image, - double startTime, - double stopTime, - std::vector instr, - std::string targ, - std::string pot); +private: + void createImage(Image& image, + double startTime, + double stopTime, + std::vector instr, + std::string targ, + std::string path); - bool augmentWithSpice(Image& image, - std::string spacecraft, - std::vector payload, - std::vector potentialTargets); + std::string decode(std::string line); + + bool augmentWithSpice(Image& image, + std::string spacecraft, + std::vector payload, + std::vector potentialTargets); - std::string _fileName; - std::string _spacecraft; - std::map _fileTranslation; - std::vector _specsOfInterest; + std::string _fileName; + std::string _spacecraft; + std::map _fileTranslation; + std::vector _specsOfInterest; - //returnable - std::map _subsetMap; - std::vector> _instrumentTimes; - std::vector> _targetTimes; - std::vector _captureProgression; - }; + //returnable + std::map _subsetMap; + std::vector> _instrumentTimes; + std::vector> _targetTimes; + std::vector _captureProgression; + + std::string _target; + std::string _instrumentID; + std::string _instrumentHostID; + std::string _detectorType; + std::string _sequenceID; + double _startTime; + double _stopTime; +}; } #endif //__LABELPARSER_H__ \ No newline at end of file diff --git a/include/openspace/util/scannerdecoder.h b/include/openspace/util/scannerdecoder.h index 8eddf3aafb..4ddff2a935 100644 --- a/include/openspace/util/scannerdecoder.h +++ b/include/openspace/util/scannerdecoder.h @@ -35,8 +35,11 @@ public: ScannerDecoder(const ghoul::Dictionary& dictionary); virtual std::string getDecoderType(); virtual std::vector getSpiceIDs(); + std::string getStopCommand(); + void setStopCommand(std::string stopCommand); private: std::string _type; + std::string _abort; std::vector _spiceIDs; }; diff --git a/include/openspace/util/sequenceparser.h b/include/openspace/util/sequenceparser.h index 90197884be..b8b54336b8 100644 --- a/include/openspace/util/sequenceparser.h +++ b/include/openspace/util/sequenceparser.h @@ -37,7 +37,7 @@ namespace openspace { double startTime; double stopTime; std::string path; - std::vector activeInstruments; + std::vector activeInstruments; std::string target; bool projected; }; diff --git a/openspace-data b/openspace-data index 6b34ef9849..de36eeeb00 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 6b34ef9849d58fa33a40c571eee6432bde83e343 +Subproject commit de36eeeb000a6345bd6d63f21bf9c705e01ddfc0 diff --git a/scripts/default_startup.lua b/scripts/default_startup.lua index 19cd4413d1..27e520b7c4 100644 --- a/scripts/default_startup.lua +++ b/scripts/default_startup.lua @@ -14,11 +14,11 @@ dofile(openspace.absPath('${SCRIPTS}/bind_keys.lua')) -- Load the default keyb -- openspace.time.setDeltaTime(50); -openspace.time.setTime("2015-07-14T10:10:00.00") -- PLUTO +--openspace.time.setTime("2015-07-14T10:10:00.00") -- PLUTO -- NH takes series of images from visible to dark side (across terminator) -- Sequence lasts ~10 mins, (recommended dt = 10) ---openspace.time.setTime("2015-07-14T11:22:00.00") -- PLUTO +openspace.time.setTime("2015-07-14T11:00:00.00") -- PLUTO --BEAUTIFUL SEQUENCE -- NH takes series of images (same as previous) -- Sequence ends at 2015 JUL 14T11:24:00:000, (recommended dt = 1) diff --git a/shaders/fboPass_fs.glsl b/shaders/fboPass_fs.glsl index b89dc7f7cf..b339ec85c7 100644 --- a/shaders/fboPass_fs.glsl +++ b/shaders/fboPass_fs.glsl @@ -25,12 +25,15 @@ #version 430 uniform sampler2D texture1; +uniform sampler2D texture2; uniform mat4 ProjectorMatrix; uniform mat4 ModelTransform; uniform vec2 _scaling; uniform vec2 radius; flat in uint vs_segments; +uniform float projectionFading; + in vec4 vs_position; uniform vec3 boresight; @@ -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 } \ No newline at end of file diff --git a/shaders/modules/trails/ephemeris_fs.glsl b/shaders/modules/trails/ephemeris_fs.glsl index a5a72ae47f..c9a8c5f111 100644 --- a/shaders/modules/trails/ephemeris_fs.glsl +++ b/shaders/modules/trails/ephemeris_fs.glsl @@ -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); } \ No newline at end of file diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 132b43e705..ae3fa64834 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include // testing @@ -102,7 +101,6 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName) { SpiceManager::initialize(); Time::initialize(); - ImageSequencer::initialize(); ImageSequencer2::initialize(); FactoryManager::initialize(); ghoul::systemcapabilities::SystemCapabilities::initialize(); diff --git a/src/rendering/model/renderablemodel.cpp b/src/rendering/model/renderablemodel.cpp index 258a85f0d8..c567ed67d5 100644 --- a/src/rendering/model/renderablemodel.cpp +++ b/src/rendering/model/renderablemodel.cpp @@ -37,6 +37,8 @@ #include #include +#include + #include #include @@ -47,6 +49,7 @@ const std::string _loggerCat = "RenderableModel"; const std::string keyDestination = "Rotation.Destination"; const std::string keyShading = "Shading.PerformShading"; const std::string keyFading = "Shading.Fadeable"; + const std::string keyGhosting = "Shading.Ghosting"; } @@ -60,6 +63,7 @@ namespace openspace { , _texture(nullptr) , _bumpMap(nullptr) , _geometry(nullptr) + , _isGhost(false) , _performShading("performShading", "Perform Shading", true) , _fading("fading", "Fade", 0) , _performFade("performFading", "Perform Fading", false) @@ -114,11 +118,17 @@ namespace openspace { if (dictionary.hasKeyAndValue(keyFading)) { bool fading; - dictionary.getValue(keyShading, fading); + dictionary.getValue(keyFading, fading); _performFade = fading; } addProperty(_performFade); + + if (dictionary.hasKeyAndValue(keyGhosting)) { + bool ghosting; + dictionary.getValue(keyGhosting, ghosting); + _isGhost = ghosting; + } } bool RenderableModel::isReady() const { @@ -163,26 +173,21 @@ bool RenderableModel::deinitialize() { } void RenderableModel::render(const RenderData& data) { - _programObject->activate(); + double lt; - glm::mat4 transform = glm::mat4(1); + _programObject->activate(); + glm::mat4 transform = glm::mat4(1); glm::mat4 tmp = glm::mat4(1); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ tmp[i][j] = static_cast(_stateMatrix[i][j]); } } - transform *= tmp; - double lt; psc tmppos; - - SpiceManager::ref().getTargetPosition(_source, "SUN", "GALACTIC", "NONE", Time::ref().currentTime(), tmppos, lt); - + SpiceManager::ref().getTargetPosition(_source, "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("ViewProjection", data.camera.viewProjectionMatrix()); @@ -191,44 +196,58 @@ void RenderableModel::render(const RenderData& data) { _programObject->setUniform("_performShading", _performShading); - if (_performFade && _fading > 0.f){ _fading = _fading - 0.01f; - - } - else if (!_performFade && _fading < 1.f){ + }else if (!_performFade && _fading < 1.f){ _fading = _fading + 0.01f; } - _programObject->setUniform("fading", _fading); - - - // Bind texture - ghoul::opengl::TextureUnit unit; - unit.activate(); - _texture->bind(); - _programObject->setUniform("texture1", unit); + // 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 - _programObject->deactivate(); + // disable shader + _programObject->deactivate(); } void RenderableModel::update(const UpdateData& data) { + _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", _source, "GALACTIC", "NONE", _time, _sunPosition, lt); } void RenderableModel::loadTexture() { diff --git a/src/rendering/model/wavefrontgeometry.cpp b/src/rendering/model/wavefrontgeometry.cpp index aa88ba01a9..a31276a112 100644 --- a/src/rendering/model/wavefrontgeometry.cpp +++ b/src/rendering/model/wavefrontgeometry.cpp @@ -47,6 +47,7 @@ namespace modelgeometry { WavefrontGeometry::WavefrontGeometry(const ghoul::Dictionary& dictionary) : ModelGeometry() + ,_mode(GL_TRIANGLES) { using constants::scenegraphnode::keyName; @@ -139,10 +140,14 @@ void WavefrontGeometry::deinitialize() { glDeleteBuffers(1, &_ibo); } +void WavefrontGeometry::changeRenderMode(const GLenum mode){ + _mode = mode; +} + void WavefrontGeometry::render() { glBindVertexArray(_vaoID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); - glDrawElements(GL_TRIANGLES, _indices.size(), GL_UNSIGNED_INT, 0); + glDrawElements(_mode, _indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); } diff --git a/src/rendering/planets/renderableplanetprojection.cpp b/src/rendering/planets/renderableplanetprojection.cpp index 596ec9006e..24b4baf913 100644 --- a/src/rendering/planets/renderableplanetprojection.cpp +++ b/src/rendering/planets/renderableplanetprojection.cpp @@ -86,11 +86,12 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::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) , _once(false) @@ -158,9 +159,8 @@ RenderablePlanetProjection::RenderablePlanetProjection(const ghoul::Dictionary& _projectionTexturePath = path + "/" + texturePath; } addPropertySubOwner(_geometry); - - addProperty(_imageTrigger); - _imageTrigger.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this)); + + addProperty(_fadeProjection); addProperty(_colorTexturePath); _colorTexturePath.onChange(std::bind(&RenderablePlanetProjection::loadTexture, this)); @@ -181,34 +181,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 +299,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); @@ -395,7 +390,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]); @@ -457,13 +451,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 +471,6 @@ void RenderablePlanetProjection::loadProjectionTexture(){ _textureProj->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); } } - //_sequencer->sequenceReset(); } void RenderablePlanetProjection::loadTexture(){ @@ -490,5 +483,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 diff --git a/src/rendering/renderablefov.cpp b/src/rendering/renderablefov.cpp index 66233c48dd..33cb8d82f8 100644 --- a/src/rendering/renderablefov.cpp +++ b/src/rendering/renderablefov.cpp @@ -29,7 +29,6 @@ #include #include -#include #include // testing #include @@ -104,7 +103,7 @@ namespace openspace{ } void RenderableFov::allocateData(){ - int points = 10; + int points = 20; _stride[0] = points; _isize[0] = points; _iarray1[0] = new int[_isize[0]]; @@ -123,7 +122,7 @@ void RenderableFov::allocateData(){ _vtotal[0] = static_cast(_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 +292,8 @@ void RenderableFov::fovProjection(bool H[], std::vector 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]; @@ -383,7 +382,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,14 +415,13 @@ 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); } @@ -513,7 +511,7 @@ void RenderableFov::render(const RenderData& data){ } } - _interceptTag[4] = _interceptTag[0]; + _interceptTag[bounds.size()] = _interceptTag[0]; fovProjection(_interceptTag, bounds); updateData(); } @@ -529,6 +527,7 @@ void RenderableFov::render(const RenderData& data){ glDrawArrays(GL_LINES, 0, _vtotal[0]); glBindVertexArray(0); + //second vbo if (drawFOV){ glLineWidth(1.f); diff --git a/src/rendering/renderabletrail.cpp b/src/rendering/renderabletrail.cpp index 044932897c..e9a0553ec6 100644 --- a/src/rendering/renderabletrail.cpp +++ b/src/rendering/renderabletrail.cpp @@ -30,6 +30,9 @@ #include #include #include +#include +#include + /* 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"; @@ -86,6 +90,7 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary) addProperty(_lineFade); addProperty(_lineWidth); + _distanceFade = 1.0; } bool RenderableTrail::initialize() { @@ -139,6 +144,23 @@ void RenderableTrail::render(const RenderData& data) { _programObject->setUniform("nVertices", static_cast(_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(); + + + //std::cout << openspace::OpenSpaceEngine::ref().interactionHandler()->focusNode()->name()<< std::endl; + //std::cout << this->owner()->name() << std::endl; + + if (pssl[0] < 0.00001){ + 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); @@ -151,6 +173,7 @@ void RenderableTrail::render(const RenderData& data) { } void RenderableTrail::update(const UpdateData& data) { + _time = data.time; if (data.isTimeJump) _needsSweep = true; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index ae5ce38a4f..fce275c30a 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -24,7 +24,6 @@ #include -#include #include @@ -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 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,9 +537,9 @@ 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++, "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()); @@ -605,6 +549,7 @@ namespace openspace { PrintText(i++, "Cam->origin: (% .15f, % .4f)", pssl[0], pssl[1]); PrintText(i++, "Scaling: (% .5f, % .5f)", scaling[0], scaling[1]); */ + if (openspace::ImageSequencer2::ref().isReady()){ double remaining = openspace::ImageSequencer2::ref().getNextCaptureTime() - currentTime; double t = 1.f - remaining / openspace::ImageSequencer2::ref().getIntervalLength(); @@ -625,9 +570,9 @@ namespace openspace { } glm::vec4 w(1); PrintColorText(i++, "Ucoming capture : %s", 10, w, str.c_str()); - + std::pair nextTarget = ImageSequencer2::ref().getNextTarget(); - std::pair currentTarget = ImageSequencer2::ref().getCurrentTarget(); + std::pair currentTarget = ImageSequencer2::ref().getCurrentTarget(); int timeleft = nextTarget.first - currentTime; @@ -649,7 +594,7 @@ namespace openspace { 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> incidentTargets = ImageSequencer2::ref().getIncidentTargetList(2); std::string space; glm::vec4 color; @@ -664,35 +609,26 @@ namespace openspace { } i++; - std::vector> instrVec = ImageSequencer2::ref().getActiveInstruments(); - + + std::map 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); - - - double reduce = 0.01; - PrintColorText(i++, "Active Instruments : ", 10, active); - for (int k = 0; k < instrVec.size(); k++){ - - if (instrVec[k].second == false){ + 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), instrVec[k].first.c_str()); + 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 (instrVec[k].first == "NH_LORRI"){ + 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, instrVec[k].first.c_str()); - + PrintColorText(i++, " %5s", 10, active, t.first.c_str()); } } - } #undef PrintText @@ -1037,6 +973,7 @@ void RenderEngine::changeViewPoint(std::string origin) { SceneGraphNode* solarSystemBarycenterNode = sceneGraph()->sceneGraphNode("SolarSystemBarycenter"); SceneGraphNode* plutoBarycenterNode = sceneGraph()->sceneGraphNode("PlutoBarycenter"); SceneGraphNode* newHorizonsNode = sceneGraph()->sceneGraphNode("NewHorizons"); + SceneGraphNode* newHorizonsGhostNode = sceneGraph()->sceneGraphNode("NewHorizonsGhost"); SceneGraphNode* jupiterBarycenterNode = sceneGraph()->sceneGraphNode("JupiterBarycenter"); if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr) { @@ -1076,6 +1013,16 @@ void RenderEngine::changeViewPoint(std::string origin) { }; newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + ghoul::Dictionary newHorizonsGhostDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("NEW HORIZONS GHOST") }, + { 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") { @@ -1109,6 +1056,17 @@ void RenderEngine::changeViewPoint(std::string origin) { { std::string("Kernels"), ghoul::Dictionary() } }; newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + + ghoul::Dictionary newHorizonsGhostDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("NEW HORIZONS GHOST") }, + { 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") { @@ -1142,6 +1100,16 @@ void RenderEngine::changeViewPoint(std::string origin) { { std::string("Kernels"), ghoul::Dictionary() } }; newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary)); + + ghoul::Dictionary newHorizonsGhostDictionary = + { + { std::string("Type"), std::string("Spice") }, + { std::string("Body"), std::string("NEW HORIZONS GHOST") }, + { std::string("Reference"), std::string("GALACTIC") }, + { std::string("Observer"), std::string("JUPITER BARYCENTER") }, + { std::string("Kernels"), ghoul::Dictionary() } + }; + newHorizonsGhostNode->setEphemeris(new SpiceEphemeris(newHorizonsGhostDictionary)); return; } diff --git a/src/scenegraph/spiceephemeris.cpp b/src/scenegraph/spiceephemeris.cpp index 0e42a8f9da..cb7776611b 100644 --- a/src/scenegraph/spiceephemeris.cpp +++ b/src/scenegraph/spiceephemeris.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace { const std::string _loggerCat = "SpiceEphemeris"; @@ -73,15 +74,15 @@ void SpiceEphemeris::update(const UpdateData& data) { glm::dvec3 position(0,0,0); double lightTime = 0.0; - + if (_targetName != "NEW HORIZONS GHOST") 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). - SpiceManager::ref().getTargetPosition(_targetName, _originName, - "GALACTIC", "NONE", data.time, position, lightTime); + double interval = openspace::ImageSequencer2::ref().getIntervalLength(); + if (_targetName == "NEW HORIZONS GHOST" && interval > 60){ + double _time = openspace::ImageSequencer2::ref().getNextCaptureTime(); + SpiceManager::ref().getTargetPosition("NEW HORIZONS", _originName, + "GALACTIC", "NONE", _time, position, lightTime); } _position = psc::CreatePowerScaledCoordinate(position.x, position.y, position.z); diff --git a/src/util/hongkangparser.cpp b/src/util/hongkangparser.cpp index 8f700dce35..2817818fd0 100644 --- a/src/util/hongkangparser.cpp +++ b/src/util/hongkangparser.cpp @@ -32,8 +32,9 @@ #include #include #include - #include +#include + namespace { const std::string _loggerCat = "HongKangParser"; @@ -61,9 +62,10 @@ namespace openspace { translationDictionary.getValue(decoders[i], typeDictionary); //for each playbook call -> create a Decoder object const std::vector& 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); @@ -101,7 +103,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 = ""; @@ -126,18 +128,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); @@ -167,13 +173,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(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! @@ -186,7 +227,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; @@ -201,9 +242,9 @@ void HongKangParser::create(){ _subsetMap[image.target]._range.setRange(scan_start); scan_start = -1; - } + }*/ } - } while (!file.eof()); + } } } } @@ -273,10 +314,10 @@ bool HongKangParser::augmentWithSpice(Image& image, return false; } -void HongKangParser::createImage(Image& image, double startTime, double stopTime, std::vector instr, std::string targ, std::string pot) { +void HongKangParser::createImage(Image& image, double startTime, double stopTime, std::vector 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]); } diff --git a/src/util/imagesequencer.cpp b/src/util/imagesequencer.cpp index db2ee3c0b7..6ccbbb56ef 100644 --- a/src/util/imagesequencer.cpp +++ b/src/util/imagesequencer.cpp @@ -23,7 +23,6 @@ ****************************************************************************************/ // open space includes -#include #include #include #include diff --git a/src/util/imagesequencer2.cpp b/src/util/imagesequencer2.cpp index a9e2e10567..ccf3dfa4f7 100644 --- a/src/util/imagesequencer2.cpp +++ b/src/util/imagesequencer2.cpp @@ -49,7 +49,6 @@ _hasData(false), _defaultCaptureImage(absPath("C:/Users/michal/openspace/openspace-data/scene/common/textures/placeholder_blank.png")) {} - ImageSequencer2& ImageSequencer2::ref() { assert(_instance != nullptr); return *_instance; @@ -68,22 +67,6 @@ bool ImageSequencer2::isReady(){ return _hasData; } -bool ImageSequencer2::imageComparer(const Image &a, const Image &b){ - return a.startTime < b.startTime; -}; - -std::vector::iterator ImageSequencer2::binary_find(std::vector::iterator begin, - std::vector::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::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 +75,6 @@ void ImageSequencer2::updateSequencer(double time){ } std::pair ImageSequencer2::getNextTarget(){ - // make into template func auto compareTime = [](const std::pair &a, const std::pair &b)->bool{ return a.first < b.first; @@ -101,22 +83,21 @@ std::pair 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 ImageSequencer2::getCurrentTarget(){ - // make into template func auto compareTime = [](const std::pair &a, - const std::pair &b)->bool{ + const std::pair &b)->bool{ return a.first < b.first; }; std::pair findEqualToThis; 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 *std::prev(it); } } @@ -125,21 +106,26 @@ std::pair> ImageSequencer2::getIncidentTargetLi std::pair> incidentTargets; auto compareTime = [](const std::pair &a, - const std::pair &b)->bool{ - return a.first < b.first; + const std::pair &b)->bool{ + return a.first < b.first; }; + // what to look for std::pair 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; @@ -166,29 +152,36 @@ double ImageSequencer2::getNextCaptureTime(){ return nextCaptureTime; } -std::vector> ImageSequencer2::getActiveInstruments(){ - for (int i = 0; i < _instrumentOnOff.size(); i++){ - _instrumentOnOff[i].second = false; - } +std::map 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 spiceIDs = _fileTranslation[i.first]->getTranslation(); //check which specific subinstrument is firing for (auto s : spiceIDs){ if (s == instrumentID){ @@ -199,65 +192,115 @@ bool ImageSequencer2::instumentActive(std::string instrumentID){ } return false; } -bool ImageSequencer2::getImagePaths(std::vector>& captures, std::string projectee, std::string instrumentID){ +bool ImageSequencer2::getImagePaths(std::vector>& captures, + std::string projectee, + std::string instrumentID){ + if (!instumentActive(instrumentID) && !Time::ref().timeJumped()) return false; + // developer note: this is only due to LORRI being the only instrument implemented so far. return (instrumentID == "NH_LORRI") ? getImagePaths(captures, projectee) : false; } bool ImageSequencer2::getImagePaths(std::vector>& 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(); - + + // for readability we store the iterators + auto begin = _subsetMap[projectee]._subset.begin(); + auto end = _subsetMap[projectee]._subset.end(); + + // create temporary storage std::vector> captureTimes; - Image findPrevious; + // 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){ - 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){ + // insert + 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; + } } } return false; } +void ImageSequencer2::sortData(){ + auto targetComparer = [](const std::pair &a, + const std::pair &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 in1 = parser->getTranslation(); + std::map in2 = parser->getSubsetMap(); + std::vector> in3 = parser->getIstrumentTimes(); + std::vector> in4 = parser->getTargetTimes(); + std::vector 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 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 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 diff --git a/src/util/instrumentdecoder.cpp b/src/util/instrumentdecoder.cpp index e2370ed5e1..c062ce0df0 100644 --- a/src/util/instrumentdecoder.cpp +++ b/src/util/instrumentdecoder.cpp @@ -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(keyStopCommand) && _type == "SCANNER"){ + LWARNING("Scanner must provide stop command, please check mod file."); + }else{ + dictionary.getValue(keyStopCommand, _stopCommand); + } + std::vector 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; } diff --git a/src/util/labelparser.cpp b/src/util/labelparser.cpp index 9ecf1293d9..9a0f7a39a2 100644 --- a/src/util/labelparser.cpp +++ b/src/util/labelparser.cpp @@ -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& decoders = translationDictionary.keys(); //for each decoder (assuming might have more if hong makes changes) @@ -95,18 +93,27 @@ 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. } } - } + void LabelParser::create(){ - - std::vector tmp; - + auto imageComparer = [](const Image &a, const Image &b)->bool{ + return a.startTime < b.startTime; + }; + auto targetComparer = [](const std::pair &a, + const std::pair &b)->bool{ + return a.first < b.first; + }; + std::string previousTarget; ghoul::filesystem::Directory sequenceDir(_fileName, true); std::vector sequencePaths = sequenceDir.read(true, false); // check inputs @@ -121,44 +128,130 @@ void LabelParser::create(){ 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); + 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); + Image image; + std::vector 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 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 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("LORRI", _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 instr, std::string targ, std::string pot) { diff --git a/src/util/scannerdecoder.cpp b/src/util/scannerdecoder.cpp index e707bd8e99..953e183e8f 100644 --- a/src/util/scannerdecoder.cpp +++ b/src/util/scannerdecoder.cpp @@ -46,4 +46,8 @@ std::vector ScannerDecoder::getSpiceIDs(){ return _spiceIDs; } +void ScannerDecoder::setStopCommand(std::string stopCommand){ + _abort = stopCommand; +} + } // namespace openspace \ No newline at end of file