Merge branch 'develop' into feature/scenegraphloader

Conflicts:
	src/abuffer/abuffer.cpp
	src/rendering/renderengine.cpp
	src/scene/scene.cpp
This commit is contained in:
Alexander Bock
2015-04-17 13:31:39 +02:00
17 changed files with 721 additions and 395 deletions
@@ -62,6 +62,7 @@ private:
modelgeometry::ModelGeometry* _geometry;
float _alpha;
glm::dmat3 _stateMatrix;
std::string _source;
@@ -67,6 +67,7 @@ private:
planetgeometry::PlanetGeometry* _geometry;
properties::BoolProperty _performShading;
properties::IntProperty _rotation;
float _alpha;
glm::dmat3 _stateMatrix;
+5
View File
@@ -69,6 +69,8 @@ public:
virtual void update(const UpdateData& data);
bool isVisible() const;
bool hasTimeInterval();
bool getInterval(double& start, double& end);
protected:
std::string findPath(const std::string& path);
@@ -79,6 +81,9 @@ private:
PowerScaledScalar boundingSphere_;
std::string _relativePath;
std::string _startTime;
std::string _endTime;
bool _hasTimeInterval;
};
} // namespace openspace
+2
View File
@@ -68,6 +68,8 @@ public:
void addNode(SceneGraphNode* child);
void setParent(SceneGraphNode* parent);
bool abandonChild(SceneGraphNode* child);
const psc& position() const;
psc worldPosition() const;
+110 -112
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,6 @@ 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;
/**
* 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 method checks if one of the previous SPICE methods has failed. If it has, the
@@ -675,6 +668,11 @@ 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;
/// The last assigned kernel-id, used to determine the next free kernel id
KernelIdentifier _lastAssignedKernel;
@@ -684,4 +682,4 @@ private:
} // namespace openspace
#endif // __SPICEMANAGER_H__
#endif // __SPICEMANAGER_H__
+4 -3
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);
}
+16 -2
View File
@@ -40,12 +40,15 @@
#include <openspace/engine/openspaceengine.h>
#include <sgct.h>
#include "imgui.h"
namespace {
const std::string _loggerCat = "RenderableModel";
const std::string _loggerCat = "RenderableModel";
const std::string keySource = "Rotation.Source";
const std::string keyDestination = "Rotation.Destination";
const std::string keyBody = "Body";
const std::string keyStart = "StartTime";
const std::string keyEnd = "EndTime";
}
namespace openspace {
@@ -57,6 +60,7 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
, _texture(nullptr)
, _geometry(nullptr)
, _performShading("performShading", "Perform Shading", true)
, _alpha(1.f)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
@@ -139,9 +143,19 @@ void RenderableModel::render(const RenderData& data) {
tmp[i][j] = static_cast<float>(_stateMatrix[i][j]);
}
}
transform *= tmp;
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;
_programObject->setUniform("transparency", _alpha);
_programObject->setUniform("sun_pos", _sunPosition.vec3());
_programObject->setUniform("ViewProjection", data.camera.viewProjectionMatrix());
_programObject->setUniform("ModelTransform", transform);
@@ -61,6 +61,7 @@ RenderablePlanet::RenderablePlanet(const ghoul::Dictionary& dictionary)
, _geometry(nullptr)
, _performShading("performShading", "Perform Shading", true)
, _rotation("rotation", "Rotation", 0, 0, 360)
, _alpha(1.f)
{
std::string name;
bool success = dictionary.getValue(constants::scenegraphnode::keyName, name);
@@ -172,6 +173,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);
+28 -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,10 @@ 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("")
{
setName("renderable");
#ifndef NDEBUG
@@ -86,6 +93,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 +148,20 @@ bool Renderable::isVisible() const {
return _enabled;
}
bool Renderable::hasTimeInterval() {
return _hasTimeInterval;
}
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::isReady() const {
return true;
}
+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);
}
+41 -14
View File
@@ -78,13 +78,12 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
glm::vec3 color(0.f);
if (dictionary.hasKeyAndValue<glm::vec3>(keyColor))
dictionary.getValue(keyColor, color);
_lineColor = color;
_lineColor = color;
_lineColor.setViewOption(properties::Property::ViewOptions::Color);
addProperty(_lineColor);
addProperty(_lineFade);
addProperty(_lineWidth);
}
@@ -151,7 +150,7 @@ void RenderableTrail::render(const RenderData& data) {
}
void RenderableTrail::update(const UpdateData& data) {
if (data.isTimeJump)
if (data.isTimeJump)
_needsSweep = true;
if (_needsSweep) {
@@ -166,7 +165,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 +182,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 +203,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 +236,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;
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;
+126 -4
View File
@@ -966,10 +966,16 @@ void RenderEngine::changeViewPoint(std::string origin) {
SceneGraphNode* plutoBarycenterNode = scene()->sceneGraphNode("PlutoBarycenter");
SceneGraphNode* newHorizonsNode = scene()->sceneGraphNode("NewHorizons");
SceneGraphNode* jupiterBarycenterNode = scene()->sceneGraphNode("JupiterBarycenter");
//SceneGraphNode* dawnNode = scene()->sceneGraphNode("Dawn");
//SceneGraphNode* vestaNode = scene()->sceneGraphNode("Vesta");
if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr || newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr) {
LERROR("WTF");
return;
if (solarSystemBarycenterNode == nullptr || plutoBarycenterNode == nullptr ||
newHorizonsNode == nullptr || jupiterBarycenterNode == nullptr
//|| dawnNode == nullptr
//|| vestaNode == nullptr
) {
LERROR("Necessary nodes does not exist");
return;
}
if (origin == "Pluto") {
@@ -1004,6 +1010,26 @@ void RenderEngine::changeViewPoint(std::string origin) {
};
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("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));
return;
}
if (origin == "Sun") {
@@ -1037,7 +1063,28 @@ void RenderEngine::changeViewPoint(std::string origin) {
{ std::string("Kernels"), ghoul::Dictionary() }
};
newHorizonsNode->setEphemeris(new SpiceEphemeris(newHorizonsDictionary));
return;
//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));
return;
}
if (origin == "Jupiter") {
ghoul::Dictionary plutoDictionary =
@@ -1070,8 +1117,83 @@ void RenderEngine::changeViewPoint(std::string origin) {
{ 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("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));
return;
}
//if (origin == "Vesta") {
// 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("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("ECLIPJ2000") },
// { 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("ECLIPJ2000") },
// { 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");
}
+2
View File
@@ -37,6 +37,8 @@
#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>
+11
View File
@@ -291,6 +291,17 @@ void SceneGraphNode::setParent(SceneGraphNode* parent)
_parent = parent;
}
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();
+2 -2
View File
@@ -76,12 +76,12 @@ void SpiceEphemeris::update(const UpdateData& data) {
SpiceManager::ref().getTargetPosition(_targetName, _originName,
"GALACTIC", "NONE", data.time, position, lightTime);
if (_targetName == "NEW HORIZONS"){
/*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);
}
}*/
_position = psc::CreatePowerScaledCoordinate(position.x, position.y, position.z);
_position[3] += 3;
+367 -164
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,15 +491,92 @@ 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]);
return targetFound && observerFound;
}
// do NOT remove this method.
@@ -359,6 +584,12 @@ bool SpiceManager::frameConversion(glm::dvec3& v, const std::string& from, const
glm::dmat3 transform;
// get rotation matrix from frame A - frame B
pxform_c(from.c_str(), to.c_str(), ephemerisTime, (double(*)[3])glm::value_ptr(transform));
bool success = !failed_c();
if (!success){
reset_c();
return false;
}
bool hasError = checkForError("Error converting from frame '" + from +
"' to frame '" + to + "' at time " + std::to_string(ephemerisTime));
if (hasError)
@@ -384,7 +615,6 @@ bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
bool& isVisible
) const
{
int visible;
fovtrg_c(instrument.c_str(),
target.c_str(),
@@ -396,6 +626,12 @@ bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
&visible);
isVisible = (visible == SPICETRUE);
bool success = !failed_c();
if (!success){
reset_c();
return false;
}
bool hasError = checkForError("Checking if target '" + target +
"' is in view of instrument '" + instrument + "' failed");
@@ -426,6 +662,12 @@ bool SpiceManager::targetWithinFieldOfView(const std::string& instrument,
&visible);
isVisible = (visible == SPICETRUE);
bool success = !failed_c();
if (!success){
reset_c();
return false;
}
bool hasError = checkForError("Checking if target '" + target +
"' is in view of instrument '" + instrument + "' failed");
@@ -481,6 +723,12 @@ bool SpiceManager::getSurfaceIntercept(const std::string& target,
isVisible = (found == SPICETRUE);
bool success = !failed_c();
if (!success){
reset_c();
return false;
}
bool hasError = checkForError("Error retrieving surface intercept on target '" + target + "'" +
"viewed from observer '" + observer + "' in " +
"reference frame '" + bodyfixed + "' at time '" +
@@ -500,6 +748,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 +774,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 +790,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 +823,98 @@ 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, 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);
}
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);
}
}
}
return true;
}
bool SpiceManager::getFieldOfView(const std::string& instrument, std::string& fovShape,
std::string& frameName, glm::dvec3& boresightVector,
std::vector<glm::dvec3>& bounds) const
@@ -649,6 +952,13 @@ bool SpiceManager::getFieldOfView(int instrument,
&nrReturned, // the number of array values returned for the bounds
(double(*)[3])boundsArr // the bounds
);
bool success = !failed_c();
if (!success){
reset_c();
return false;
}
bool hasError = checkForError("Error getting Field-of-View parameters for "
"instrument '" + std::to_string(instrument) + "'");
if (hasError)
@@ -667,89 +977,6 @@ 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;
else
return geographicToRectangular(id, longitude, latitude, coordinates);
}
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");
return false;
}
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();
@@ -757,8 +984,8 @@ bool SpiceManager::checkForError(std::string errorMessage) {
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;
@@ -775,9 +1002,9 @@ bool SpiceManager::getPlanetEllipsoid(std::string planetName, float &a, float &b
getNaifId(planetName, id);
if (bodfnd_c(id, "RADII")) {
bodvrd_c(planetName.c_str(), "RADII", 3, &n, radii);
a = radii[0];
b = radii[1];
c = radii[2];
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");
@@ -790,28 +1017,4 @@ bool SpiceManager::getPlanetEllipsoid(std::string planetName, float &a, float &b
return !hasError;
}
//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;
//}
}
}
-90
View File
@@ -306,7 +306,6 @@ TEST_F(SpiceManagerTest, getStateTransformMatrix){
}
mxvg_c(referenceMatrix, state, 6, 6, state_t);
openspace::SpiceManager::ref().applyTransformationMatrix(position, velocity, stateMatrix);
for (int i = 0; i < 3; i++){
EXPECT_DOUBLE_EQ(position[i], state_t[i]) << "Position vector differs from its reference";
@@ -388,92 +387,3 @@ TEST_F(SpiceManagerTest, getFieldOfView){
}
unload_c(META.c_str());
}
// Try to convert planetocentric coordinates to rectangular
TEST_F(SpiceManagerTest, planetocentricToRectangular){
loadPCKKernel();
double lat = -35.0; //initial values
double lon = 100.0;
double rectangular_ref[3];
SpiceInt naifId;
SpiceBoolean foundSpice;
bodn2c_c("EARTH", &naifId, &foundSpice);
ASSERT_TRUE(foundSpice == SPICETRUE);
srfrec_c(naifId, lon*rpd_c(), lat*rpd_c(), rectangular_ref);
glm::dvec3 rectangular;
bool found = openspace::SpiceManager::ref().geographicToRectangular("EARTH", lon, lat, rectangular);
ASSERT_TRUE(found);
for (int i = 0; i < 3; i++){
EXPECT_EQ(rectangular[i], rectangular_ref[i]) << "Rectangular coordinates differ from expected output";
}
unload_c(PCK.c_str());
}
// Try getting sub-observer point
TEST_F(SpiceManagerTest, getSubObserverPoint){
loadMetaKernel();
double et;
double targetEt_ref;
double targetEt;
double subObserverPoint_ref[3];
double vectorToSurfacePoint_ref[3];
static SpiceChar* method[2] = { static_cast<char*>("Intercept: ellipsoid"), static_cast<char*>("Near point: ellipsoid") };
str2et_c("2004 jun 11 19:32:00", &et);
glm::dvec3 subObserverPoint;
glm::dvec3 vectorToSurfacePoint;
for (int i = 0; i < 2; i++){
subpnt_c(method[i], "phoebe", et, "iau_phoebe",
"lt+s", "earth", subObserverPoint_ref, &targetEt_ref, vectorToSurfacePoint_ref);
bool found = openspace::SpiceManager::ref().getSubObserverPoint(
"phoebe", "earth", method[i], "iau_phoebe", "lt+s", et, subObserverPoint,
targetEt, vectorToSurfacePoint);
ASSERT_TRUE(found);
EXPECT_EQ(targetEt_ref, targetEt);
for (int i = 0; i < 3; i++){
EXPECT_EQ(subObserverPoint_ref[i], subObserverPoint[i])
<< "Sub-observer vector differs from its reference";
EXPECT_EQ(vectorToSurfacePoint_ref[i], vectorToSurfacePoint[i])
<< "Observer to surface point vector differs from its reference";
}
}
unload_c(META.c_str());
}
// Try getting sub-solar point
//TEST_F(SpiceManagerTest, getSubSolarPoint){
// loadMetaKernel();
//
// double et, targetEt_ref, targetEt;
// double subSolarPoint_ref[3];
// double vectorToSurfacePoint_ref[3];
// static SpiceChar * method[2] = { "Intercept: ellipsoid", "Near point: ellipsoid" };
//
// str2et_c("2004 jun 11 19:32:00", &et);
//
// glm::dvec3 subSolarPoint;
// glm::dvec3 vectorToSurfacePoint;
//
// for (int i = 0; i < 2; i++){
// subslr_c(method[i], "phoebe", et, "iau_phoebe",
// "lt+s", "earth", subSolarPoint_ref, &targetEt_ref, vectorToSurfacePoint_ref);
//
// bool found = openspace::SpiceManager::ref().getSubSolarPoint(method[i], "phoebe", et, "iau_phoebe",
// "lt+s", "earth", subSolarPoint,
// targetEt, vectorToSurfacePoint);
// ASSERT_TRUE(found);
// EXPECT_EQ(targetEt_ref, targetEt);
// for (int i = 0; i < 3; i++){
// EXPECT_EQ(subSolarPoint_ref[i], subSolarPoint[i])
// << "Sub-solar vector differs from its reference";
// EXPECT_EQ(vectorToSurfacePoint_ref[i], vectorToSurfacePoint[i])
// << "Observer to surface point vector differs from its reference";
// }
// }
// unload_c(META.c_str());
//}