From 95079bb81a1c7f4faedf74b8a7a1774684f33ff8 Mon Sep 17 00:00:00 2001 From: Jonathan Fransson Date: Mon, 8 Apr 2019 09:21:59 -0600 Subject: [PATCH] merge --- .../earth/satellites/satellites_shared.asset | 6 +- .../space/rendering/renderablesatellites.cpp | 1531 +++++++++-------- .../space/rendering/renderablesatellites.h | 250 +-- modules/space/spacemodule.cpp | 14 +- 4 files changed, 912 insertions(+), 889 deletions(-) diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset b/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset index d60413b0d7..bedf1a43e5 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/satellites_shared.asset @@ -54,7 +54,7 @@ local addSatelliteGroupObjects = function(group, tleFolder, shouldAddDuplicates) Identifier = title, Parent = transforms.EarthInertial.Identifier, Renderable = { - Type = "ElonsTest", + Type = "RenderableSatellites", --Translation = { -- Type = "TLETranslation", @@ -62,10 +62,8 @@ local addSatelliteGroupObjects = function(group, tleFolder, shouldAddDuplicates) -- Observer = transforms.EarthInertial.Identifier, -- File = file -- }, - Path = file, - - Segments = 160, + Segments = 1, EccentricityColumn = "bubbis", SemiMajorAxisColumn = "bubbis", SemiMajorAxisUnit = 1, diff --git a/modules/space/rendering/renderablesatellites.cpp b/modules/space/rendering/renderablesatellites.cpp index 0cbc9ed17a..0b320cbe42 100644 --- a/modules/space/rendering/renderablesatellites.cpp +++ b/modules/space/rendering/renderablesatellites.cpp @@ -1,771 +1,788 @@ -// /**************************************************************************************** -// * * -// * OpenSpace * -// * * -// * Copyright (c) 2014-2018 * -// * * -// * Permission is hereby granted, free of charge, to any person obtaining a copy of this * -// * software and associated documentation files (the "Software"), to deal in the Software * -// * without restriction, including without limitation the rights to use, copy, modify, * -// * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -// * permit persons to whom the Software is furnished to do so, subject to the following * -// * conditions: * -// * * -// * The above copyright notice and this permission notice shall be included in all copies * -// * or substantial portions of the Software. * -// * * -// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -// * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -// * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -// * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -// * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -// * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -// ****************************************************************************************/ -// #include -// #include -// #include + /**************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2018 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #include + #include + #include -// #include -// #include -// #include -// #include + #include + #include + #include + #include -// #include + #include -// #include -// #include -// #include -// #include -// #include -// #include + #include + #include + #include +#include + #include + #include + #include -// #include -// #include -// #include -// #include + #include + #include + #include + #include +#include -// #include + + #include -// // Todo: -// // Parse epoch correctly -// // read distances using correct unit -// // ... + // Todo: + // Parse epoch correctly + // read distances using correct unit + // ... -// namespace { -// constexpr const char* ProgramName = "KeplerTrails"; -// constexpr const char* KeyFile = "File"; -// constexpr const char* KeyLineNum = "LineNumber"; + namespace { + constexpr const char* ProgramName = "RenderableSatellites"; + constexpr const char* _loggerCat = "SpaceDebris"; + -// static const openspace::properties::Property::PropertyInfo PathInfo = { -// "Path", -// "Path", -// "The file path to the CSV file to read" -// }; - -// static const openspace::properties::Property::PropertyInfo SegmentsInfo = { -// "Segments", -// "Segments", -// "The number of segments to use for each orbit ellipse" -// }; - -// static const openspace::properties::Property::PropertyInfo EccentricityColumnInfo = { -// "EccentricityColumn", -// "EccentricityColumn", -// "The header of the column where the eccentricity is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo SemiMajorAxisColumnInfo = { -// "SemiMajorAxisColumn", -// "SemiMajorAxisColumn", -// "The header of the column where the semi-major axis is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo SemiMajorAxisUnitInfo = { -// "SemiMajorAxisUnit", -// "SemiMajorAxisUnit", -// "The unit of the semi major axis. For example: If specified in km, set this to 1000." -// }; - -// static const openspace::properties::Property::PropertyInfo InclinationColumnInfo = { -// "InclinationColumn", -// "InclinationColumn", -// "The header of the column where the inclination is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo AscendingNodeColumnInfo = { -// "AscendingNodeColumn", -// "AscendingNodeColumn", -// "The header of the column where the ascending node is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo ArgumentOfPeriapsisColumnInfo = { -// "ArgumentOfPeriapsisColumn", -// "ArgumentOfPeriapsisColumn", -// "The header of the column where the argument of periapsis is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo MeanAnomalyAtEpochColumnInfo = { -// "MeanAnomalyAtEpochColumn", -// "MeanAnomalyAtEpochColumn", -// "The header of the column where the mean anomaly at epoch is stored" -// }; - -// static const openspace::properties::Property::PropertyInfo EpochColumnInfo = { -// "EpochColumn", -// "EpochColumn", -// "The header of the column where the epoch is stored" -// }; -// } + static const openspace::properties::Property::PropertyInfo PathInfo = { + "Path", + "Path", + "The file path to the CSV file to read" + }; -//namespace openspace { -//documentation::Documentation RenderableSatellites::Documentation() { -// using namespace documentation; -// return { -// "Renderable Kepler Orbits", -// "space_renderable_kepler_orbits", -// { -// { -// SegmentsInfo.identifier, -// new DoubleVerifier, -// Optional::No, -// SegmentsInfo.description -// }, -// { -// PathInfo.identifier, -// new StringVerifier, -// Optional::No, -// PathInfo.description -// }, -// { -// EccentricityColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// EccentricityColumnInfo.description -// }, -// { -// SemiMajorAxisColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// SemiMajorAxisColumnInfo.description -// }, -// { -// SemiMajorAxisUnitInfo.identifier, -// new DoubleVerifier, -// Optional::No, -// SemiMajorAxisUnitInfo.description -// }, -// { -// InclinationColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// InclinationColumnInfo.description -// }, -// { -// AscendingNodeColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// AscendingNodeColumnInfo.description -// }, -// { -// ArgumentOfPeriapsisColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// ArgumentOfPeriapsisColumnInfo.description -// }, -// { -// MeanAnomalyAtEpochColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// MeanAnomalyAtEpochColumnInfo.description -// }, -// { -// EpochColumnInfo.identifier, -// new StringVerifier, -// Optional::No, -// EpochColumnInfo.description -// } -// } -// }; -//} -// -//RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) -// : Renderable(dictionary) -// , _path(PathInfo) -// , _nSegments(SegmentsInfo) -// , _eccentricityColumnName(EccentricityColumnInfo) -// , _semiMajorAxisColumnName(SemiMajorAxisColumnInfo) -// , _semiMajorAxisUnit(SemiMajorAxisUnitInfo) -// , _inclinationColumnName(InclinationColumnInfo) -// , _ascendingNodeColumnName(AscendingNodeColumnInfo) -// , _argumentOfPeriapsisColumnName(ArgumentOfPeriapsisColumnInfo) -// , _meanAnomalyAtEpochColumnName(MeanAnomalyAtEpochColumnInfo) -// , _epochColumnName(EpochColumnInfo) -//{ -// documentation::testSpecificationAndThrow( -// Documentation(), -// dictionary, -// "RenderableSatellites" -// ); -// -// _nSegments = -// static_cast(dictionary.value(SegmentsInfo.identifier)); -// _path = -// dictionary.value(PathInfo.identifier); -// _eccentricityColumnName = -// dictionary.value(EccentricityColumnInfo.identifier); -// _semiMajorAxisColumnName = -// dictionary.value(SemiMajorAxisColumnInfo.identifier); -// _inclinationColumnName = -// dictionary.value(InclinationColumnInfo.identifier); -// _ascendingNodeColumnName = -// dictionary.value(AscendingNodeColumnInfo.identifier); -// _argumentOfPeriapsisColumnName = -// dictionary.value(ArgumentOfPeriapsisColumnInfo.identifier); -// _meanAnomalyAtEpochColumnName = -// dictionary.value(MeanAnomalyAtEpochColumnInfo.identifier); -// _epochColumnName = -// dictionary.value(EpochColumnInfo.identifier); -// _semiMajorAxisUnit = -// dictionary.value(SemiMajorAxisUnitInfo.identifier); -// -// addPropertySubOwner(_appearance); -// addProperty(_path); -// addProperty(_nSegments); -// addProperty(_semiMajorAxisUnit); -// -///* -//* test -//*/ -// -// const std::string& file = dictionary.value(KeyFile); -// readTLEFile(file); -// -//} -// // The list of leap years only goes until 2056 as we need to touch this file then -// // again anyway ;) -// const std::vector LeapYears = { -// 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, -// 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, -// 2044, 2048, 2052, 2056 -// }; -// -// // Count the number of full days since the beginning of 2000 to the beginning of -// // the parameter 'year' -// int countDays(int year) { -// // Find the position of the current year in the vector, the difference -// // between its position and the position of 2000 (for J2000) gives the -// // number of leap years -// constexpr const int Epoch = 2000; -// constexpr const int DaysRegularYear = 365; -// constexpr const int DaysLeapYear = 366; -// -// if (year == Epoch) { -// return 0; -// } -// -// // Get the position of the most recent leap year -// const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year); -// -// // Get the position of the epoch -// const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch); -// -// // The distance between the two iterators gives us the number of leap years -// const int nLeapYears = static_cast(std::abs(std::distance(y2000, lb))); -// -// const int nYears = std::abs(year - Epoch); -// const int nRegularYears = nYears - nLeapYears; -// -// // Get the total number of days as the sum of leap years + non leap years -// const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear; -// return result; -// } -// -// // Returns the number of leap seconds that lie between the {year, dayOfYear} -// // time point and { 2000, 1 } -// int countLeapSeconds(int year, int dayOfYear) { -// // Find the position of the current year in the vector; its position in -// // the vector gives the number of leap seconds -// struct LeapSecond { -// int year; -// int dayOfYear; -// bool operator<(const LeapSecond& rhs) const { -// return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear); -// } -// }; -// -// const LeapSecond Epoch = { 2000, 1 }; -// -// // List taken from: https://www.ietf.org/timezones/data/leap-seconds.list -// static const std::vector LeapSeconds = { -// { 1972, 1 }, -// { 1972, 183 }, -// { 1973, 1 }, -// { 1974, 1 }, -// { 1975, 1 }, -// { 1976, 1 }, -// { 1977, 1 }, -// { 1978, 1 }, -// { 1979, 1 }, -// { 1980, 1 }, -// { 1981, 182 }, -// { 1982, 182 }, -// { 1983, 182 }, -// { 1985, 182 }, -// { 1988, 1 }, -// { 1990, 1 }, -// { 1991, 1 }, -// { 1992, 183 }, -// { 1993, 182 }, -// { 1994, 182 }, -// { 1996, 1 }, -// { 1997, 182 }, -// { 1999, 1 }, -// { 2006, 1 }, -// { 2009, 1 }, -// { 2012, 183 }, -// { 2015, 182 }, -// { 2017, 1 } -// }; -// -// // Get the position of the last leap second before the desired date -// LeapSecond date { year, dayOfYear }; -// const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date); -// -// // Get the position of the Epoch -// const auto y2000 = std::lower_bound( -// LeapSeconds.begin(), -// LeapSeconds.end(), -// Epoch -// ); -// -// // The distance between the two iterators gives us the number of leap years -// const int nLeapSeconds = static_cast(std::abs(std::distance(y2000, it))); -// return nLeapSeconds; -// } -// -// double calculateSemiMajorAxis(double meanMotion) { -// constexpr const double GravitationalConstant = 6.6740831e-11; -// constexpr const double MassEarth = 5.9721986e24; -// constexpr const double muEarth = GravitationalConstant * MassEarth; -// -// // Use Kepler's 3rd law to calculate semimajor axis -// // a^3 / P^2 = mu / (2pi)^2 -// // <=> a = ((mu * P^2) / (2pi^2))^(1/3) -// // with a = semimajor axis -// // P = period in seconds -// // mu = G*M_earth -// double period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; -// -// const double pisq = glm::pi() * glm::pi(); -// double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0); -// -// // We need the semi major axis in km instead of m -// return semiMajorAxis / 1000.0; -// } -// -//double epochFromSubstring(const std::string& epochString) { -// // The epochString is in the form: -// // YYDDD.DDDDDDDD -// // With YY being the last two years of the launch epoch, the first DDD the day -// // of the year and the remaning a fractional part of the day -// -// // The main overview of this function: -// // 1. Reconstruct the full year from the YY part -// // 2. Calculate the number of seconds since the beginning of the year -// // 2.a Get the number of full days since the beginning of the year -// // 2.b If the year is a leap year, modify the number of days -// // 3. Convert the number of days to a number of seconds -// // 4. Get the number of leap seconds since January 1st, 2000 and remove them -// // 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not -// // midnight -// -// // According to https://celestrak.com/columns/v04n03/ -// // Apparently, US Space Command sees no need to change the two-line element -// // set format yet since no artificial earth satellites existed prior to 1957. -// // By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and -// // those from 00-56 correspond to 2000-2056. We'll see each other again in 2057! -// -// // 1. Get the full year -// std::string yearPrefix = [y = epochString.substr(0, 2)](){ -// int year = std::atoi(y.c_str()); -// return year >= 57 ? "19" : "20"; -// }(); -// const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str()); -// const int daysSince2000 = countDays(year); -// -// // 2. -// // 2.a -// double daysInYear = std::atof(epochString.substr(2).c_str()); -// -// // 2.b -// const bool isInLeapYear = std::find( -// LeapYears.begin(), -// LeapYears.end(), -// year -// ) != LeapYears.end(); -// if (isInLeapYear && daysInYear >= 60) { -// // We are in a leap year, so we have an effective day more if we are -// // beyond the end of february (= 31+29 days) -// --daysInYear; -// } -// -// // 3 -// using namespace std::chrono; -// const int SecondsPerDay = static_cast(seconds(hours(24)).count()); -// //Need to subtract 1 from daysInYear since it is not a zero-based count -// const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; -// -// // 4 -// // We need to remove additionbal leap seconds past 2000 and add them prior to -// // 2000 to sync up the time zones -// const double nLeapSecondsOffset = -countLeapSeconds( -// year, -// static_cast(std::floor(daysInYear)) -// ); -// -// // 5 -// const double nSecondsEpochOffset = static_cast( -// seconds(hours(12)).count() -// ); -// -// // Combine all of the values -// const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset; -// return epoch; -// } -// -//void RenderableSatellites::readTLEFile(const std::string& filename) { -// ghoul_assert(FileSys.fileExists(filename), "The filename must exist"); -// -// std::ifstream file; -// file.exceptions(std::ofstream::failbit | std::ofstream::badbit); -// file.open(filename); -// -// // All of the Kepler element information -// struct KeplerParameters{ -// double inclination = 0.0; -// double semiMajorAxis = 0.0; -// double ascendingNode = 0.0; -// double eccentricity = 0.0; -// double argumentOfPeriapsis = 0.0; -// double meanAnomaly = 0.0; -// double meanMotion = 0.0; -// double epoch = 0.0; -// }; -// -// // std::vector TLEData; -// -// // int numberOfLines = std::count(std::istreambuf_iterator(file), -// // std::istreambuf_iterator(), '\n' ); -// // 3 because a TLE has 3 lines per element/ object. -// // int numberOfObjects = numberOfLines/3; -// // LINFO("Number of data elements: " + numberOfObjects); -// -// // for(int i=0 ; i> keplerElements.inclination; -// stream.clear(); -// -// // Get Right ascension of the ascending node -// stream.str(line.substr(17, 8)); -// stream >> keplerElements.ascendingNode; -// stream.clear(); -// -// // Get Eccentricity -// stream.str("0." + line.substr(26, 7)); -// stream >> keplerElements.eccentricity; -// stream.clear(); -// -// // Get argument of periapsis -// stream.str(line.substr(34, 8)); -// stream >> keplerElements.argumentOfPeriapsis; -// stream.clear(); -// -// // Get mean anomaly -// stream.str(line.substr(43, 8)); -// stream >> keplerElements.meanAnomaly; -// stream.clear(); -// -// // Get mean motion -// stream.str(line.substr(52, 11)); -// stream >> keplerElements.meanMotion; -// } else { -// throw ghoul::RuntimeError(fmt::format( -// "File {} @ line {} does not have '2' header", filename // , lineNum + 2 -// )); -// } -// -// // Calculate the semi major axis based on the mean motion using kepler's laws -// keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion); -// -// // Converting the mean motion (revolutions per day) to period (seconds per revolution) -// using namespace std::chrono; -// double period = seconds(hours(24)).count() / keplerElements.meanMotion; -// -// KeplerTranslation::KeplerOrbit TLEElements{ -// keplerElements.eccentricity, -// keplerElements.semiMajorAxis, -// keplerElements.inclination, -// keplerElements.ascendingNode, -// keplerElements.argumentOfPeriapsis, -// keplerElements.meanAnomaly, -// period, -// keplerElements.epoch -// }; -// -// /* -// _keplerTranslator.setKeplerElements( -// keplerElements.eccentricity, -// keplerElements.semiMajorAxis, -// keplerElements.inclination, -// keplerElements.ascendingNode, -// keplerElements.argumentOfPeriapsis, -// keplerElements.meanAnomaly, -// period, -// keplerElements.epoch -// ); -// */ -// TLEData.push_back(TLEElements); -// -// -// } // !while loop -// -// file.close(); -// } -// -//RenderableSatellites::~RenderableSatellites() { -// -//} -// -//void RenderableSatellites::initialize() { -// readFromCsvFile(); -// updateBuffers(); -// -// _path.onChange([this]() { -// readFromCsvFile(); -// updateBuffers(); -// }); -// -// _semiMajorAxisUnit.onChange([this]() { -// readFromCsvFile(); -// updateBuffers(); -// }); -// -// _nSegments.onChange([this]() { -// updateBuffers(); -// }); -//} -// -//void RenderableSatellites::deinitialize() { -// -//} -// -//void RenderableSatellites::initializeGL() { -// glGenVertexArrays(1, &_vertexArray); -// glGenBuffers(1, &_vertexBuffer); -// glGenBuffers(1, &_indexBuffer); -// -// _programObject = SpaceModule::ProgramObjectManager.request( -// ProgramName, -// []() -> std::unique_ptr { -// return global::renderEngine.buildRenderProgram( -// ProgramName, -// absPath("${MODULE_SPACE}/shaders/RenderableKeplerOrbits_vs.glsl"), -// absPath("${MODULE_SPACE}/shaders/RenderableKeplerOrbits_fs.glsl") -// ); -// } -// ); -// -// _uniformCache.opacity = _programObject->uniformLocation("opacity"); -// _uniformCache.modelView = _programObject->uniformLocation("modelViewTransform"); -// _uniformCache.projection = _programObject->uniformLocation("projectionTransform"); -// _uniformCache.color = _programObject->uniformLocation("color"); -// _uniformCache.useLineFade = _programObject->uniformLocation("useLineFade"); -// _uniformCache.lineFade = _programObject->uniformLocation("lineFade"); -// -// setRenderBin(Renderable::RenderBin::Overlay); -//} -// -//void RenderableSatellites::deinitializeGL() { -// SpaceModule::ProgramObjectManager.release(ProgramName); -// -// glDeleteBuffers(1, &_vertexBuffer); -// glDeleteBuffers(1, &_indexBuffer); -// glDeleteVertexArrays(1, &_vertexArray); -//} -// -// -//bool RenderableSatellites::isReady() const { -// return true; -//} -// -//void RenderableSatellites::update(const UpdateData&) {} -// -//void RenderableSatellites::render(const RenderData& data, RendererTasks&) { -// _programObject->activate(); -// _programObject->setUniform(_uniformCache.opacity, _opacity); -// -// glm::dmat4 modelTransform = -// glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * -// glm::dmat4(data.modelTransform.rotation) * -// glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); -// -// _programObject->setUniform( -// _uniformCache.modelView, -// data.camera.combinedViewMatrix() * modelTransform -// ); -// -// _programObject->setUniform(_uniformCache.projection, data.camera.projectionMatrix()); -// _programObject->setUniform(_uniformCache.color, _appearance.lineColor); -// //_programObject->setUniform(_uniformCache.useLineFade, _appearance.useLineFade); -// -// /*if (_appearance.useLineFade) { -// _programObject->setUniform(_uniformCache.lineFade, _appearance.lineFade); -// }*/ -// -// glDepthMask(false); -// //glBlendFunc(GL_SRC_ALPHA, GL_ONE); -// -// glBindVertexArray(_vertexArray); -// glDrawElements(GL_LINES, -// static_cast(_indexBufferData.size()), -// GL_UNSIGNED_INT, -// 0); -// glBindVertexArray(0); -// _programObject->deactivate(); -//} -// -//void RenderableSatellites::updateBuffers() { -// const size_t nVerticesPerOrbit = _nSegments + 1; -// _vertexBufferData.resize(TLEData.size() * nVerticesPerOrbit); -// _indexBufferData.resize(TLEData.size() * _nSegments * 2); -// -// size_t orbitIndex = 0; -// size_t elementIndex = 0; -// -// for (const auto& orbit : TLEData) { -// // KeplerTranslation setKeplerElements(orbit); -// _keplerTranslator.setKeplerElements( -// orbit.eccentricity, -// orbit.semiMajorAxis, -// orbit.inclination, -// orbit.ascendingNode, -// orbit.argumentOfPeriapsis, -// orbit.meanAnomalyAtEpoch, -// orbit.period, -// orbit.epoch -// ); -// // KeplerTranslation keplerTranslation(orbit); -// const double period = orbit.period(); -// for (size_t i = 0; i <= _nSegments; ++i) { -// size_t index = orbitIndex * nVerticesPerOrbit + i; -// -// double timeOffset = period * -// static_cast(i) / static_cast(_nSegments); -// -// // _updateData.time.setTime(orbit.epoch + timeOffset); -// // UpdateData::time(Time(orbit.epoch + timeOffset)); -// -// UpdateData updateTime; -// updateTime.time = Time(orbit.epoch + timeOffset); -// -// glm::vec3 position = _keplerTranslator.position(updateTime); -// // _keplerTranslator.position(_updateData.time); -// -// -// _vertexBufferData[index].x = position.x; -// _vertexBufferData[index].y = position.y; -// _vertexBufferData[index].z = position.z; -// _vertexBufferData[index].time = timeOffset; -// if (i > 0) { -// _indexBufferData[elementIndex++] = static_cast(index) - 1; -// _indexBufferData[elementIndex++] = static_cast(index); -// } -// } -// ++orbitIndex; -// } -// -// glBindVertexArray(_vertexArray); -// -// glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); -// glBufferData(GL_ARRAY_BUFFER, -// _vertexBufferData.size() * sizeof(TrailVBOLayout), -// _vertexBufferData.data(), -// GL_STATIC_DRAW -// ); -// -// -// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); -// glBufferData(GL_ELEMENT_ARRAY_BUFFER, -// _indexBufferData.size() * sizeof(int), -// _indexBufferData.data(), -// GL_STATIC_DRAW -// ); -// -// glBindVertexArray(0); -// -//} -// -//void RenderableSatellites::readFromCsvFile() { + static const openspace::properties::Property::PropertyInfo SegmentsInfo = { + "Segments", + "Segments", + "The number of segments to use for each orbit ellipse" + }; + + static const openspace::properties::Property::PropertyInfo EccentricityColumnInfo = { + "EccentricityColumn", + "EccentricityColumn", + "The header of the column where the eccentricity is stored" + }; + + static const openspace::properties::Property::PropertyInfo SemiMajorAxisColumnInfo = { + "SemiMajorAxisColumn", + "SemiMajorAxisColumn", + "The header of the column where the semi-major axis is stored" + }; + + static const openspace::properties::Property::PropertyInfo SemiMajorAxisUnitInfo = { + "SemiMajorAxisUnit", + "SemiMajorAxisUnit", + "The unit of the semi major axis. For example: If specified in km, set this to 1000." + }; + + static const openspace::properties::Property::PropertyInfo InclinationColumnInfo = { + "InclinationColumn", + "InclinationColumn", + "The header of the column where the inclination is stored" + }; + + static const openspace::properties::Property::PropertyInfo AscendingNodeColumnInfo = { + "AscendingNodeColumn", + "AscendingNodeColumn", + "The header of the column where the ascending node is stored" + }; + + static const openspace::properties::Property::PropertyInfo ArgumentOfPeriapsisColumnInfo = { + "ArgumentOfPeriapsisColumn", + "ArgumentOfPeriapsisColumn", + "The header of the column where the argument of periapsis is stored" + }; + + static const openspace::properties::Property::PropertyInfo MeanAnomalyAtEpochColumnInfo = { + "MeanAnomalyAtEpochColumn", + "MeanAnomalyAtEpochColumn", + "The header of the column where the mean anomaly at epoch is stored" + }; + + static const openspace::properties::Property::PropertyInfo EpochColumnInfo = { + "EpochColumn", + "EpochColumn", + "The header of the column where the epoch is stored" + }; + + constexpr const char* KeyFile = "Path"; + constexpr const char* KeyLineNum = "LineNumber"; + + // LINFO("Keyfile: " + KeyFile); + } + +namespace openspace { + + // The list of leap years only goes until 2056 as we need to touch this file then + // again anyway ;) + const std::vector LeapYears = { + 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, + 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, + 2044, 2048, 2052, 2056 + }; + + // Count the number of full days since the beginning of 2000 to the beginning of + // the parameter 'year' + int countDays(int year) { + // Find the position of the current year in the vector, the difference + // between its position and the position of 2000 (for J2000) gives the + // number of leap years + constexpr const int Epoch = 2000; + constexpr const int DaysRegularYear = 365; + constexpr const int DaysLeapYear = 366; + + if (year == Epoch) { + return 0; + } + + // Get the position of the most recent leap year + const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year); + + // Get the position of the epoch + const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch); + + // The distance between the two iterators gives us the number of leap years + const int nLeapYears = static_cast(std::abs(std::distance(y2000, lb))); + + const int nYears = std::abs(year - Epoch); + const int nRegularYears = nYears - nLeapYears; + + // Get the total number of days as the sum of leap years + non leap years + const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear; + return result; + } + + // Returns the number of leap seconds that lie between the {year, dayOfYear} + // time point and { 2000, 1 } + int countLeapSeconds(int year, int dayOfYear) { + // Find the position of the current year in the vector; its position in + // the vector gives the number of leap seconds + struct LeapSecond { + int year; + int dayOfYear; + bool operator<(const LeapSecond& rhs) const { + return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear); + } + }; + + const LeapSecond Epoch = { 2000, 1 }; + + // List taken from: https://www.ietf.org/timezones/data/leap-seconds.list + static const std::vector LeapSeconds = { + { 1972, 1 }, + { 1972, 183 }, + { 1973, 1 }, + { 1974, 1 }, + { 1975, 1 }, + { 1976, 1 }, + { 1977, 1 }, + { 1978, 1 }, + { 1979, 1 }, + { 1980, 1 }, + { 1981, 182 }, + { 1982, 182 }, + { 1983, 182 }, + { 1985, 182 }, + { 1988, 1 }, + { 1990, 1 }, + { 1991, 1 }, + { 1992, 183 }, + { 1993, 182 }, + { 1994, 182 }, + { 1996, 1 }, + { 1997, 182 }, + { 1999, 1 }, + { 2006, 1 }, + { 2009, 1 }, + { 2012, 183 }, + { 2015, 182 }, + { 2017, 1 } + }; + + // Get the position of the last leap second before the desired date + LeapSecond date { year, dayOfYear }; + const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date); + + // Get the position of the Epoch + const auto y2000 = std::lower_bound( + LeapSeconds.begin(), + LeapSeconds.end(), + Epoch + ); + + // The distance between the two iterators gives us the number of leap years + const int nLeapSeconds = static_cast(std::abs(std::distance(y2000, it))); + return nLeapSeconds; + } + + double calculateSemiMajorAxis(double meanMotion) { + constexpr const double GravitationalConstant = 6.6740831e-11; + constexpr const double MassEarth = 5.9721986e24; + constexpr const double muEarth = GravitationalConstant * MassEarth; + + // Use Kepler's 3rd law to calculate semimajor axis + // a^3 / P^2 = mu / (2pi)^2 + // <=> a = ((mu * P^2) / (2pi^2))^(1/3) + // with a = semimajor axis + // P = period in seconds + // mu = G*M_earth + double period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; + + const double pisq = glm::pi() * glm::pi(); + double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0); + + // We need the semi major axis in km instead of m + return semiMajorAxis / 1000.0; + } + +double epochFromSubstring(const std::string& epochString) { + // The epochString is in the form: + // YYDDD.DDDDDDDD + // With YY being the last two years of the launch epoch, the first DDD the day + // of the year and the remaning a fractional part of the day + + // The main overview of this function: + // 1. Reconstruct the full year from the YY part + // 2. Calculate the number of seconds since the beginning of the year + // 2.a Get the number of full days since the beginning of the year + // 2.b If the year is a leap year, modify the number of days + // 3. Convert the number of days to a number of seconds + // 4. Get the number of leap seconds since January 1st, 2000 and remove them + // 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not + // midnight + + // According to https://celestrak.com/columns/v04n03/ + // Apparently, US Space Command sees no need to change the two-line element + // set format yet since no artificial earth satellites existed prior to 1957. + // By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and + // those from 00-56 correspond to 2000-2056. We'll see each other again in 2057! + + // 1. Get the full year + std::string yearPrefix = [y = epochString.substr(0, 2)](){ + int year = std::atoi(y.c_str()); + return year >= 57 ? "19" : "20"; + }(); + const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str()); + const int daysSince2000 = countDays(year); + + // 2. + // 2.a + double daysInYear = std::atof(epochString.substr(2).c_str()); + + // 2.b + const bool isInLeapYear = std::find( + LeapYears.begin(), + LeapYears.end(), + year + ) != LeapYears.end(); + if (isInLeapYear && daysInYear >= 60) { + // We are in a leap year, so we have an effective day more if we are + // beyond the end of february (= 31+29 days) + --daysInYear; + } + + // 3 + using namespace std::chrono; + const int SecondsPerDay = static_cast(seconds(hours(24)).count()); + //Need to subtract 1 from daysInYear since it is not a zero-based count + const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; + + // 4 + // We need to remove additionbal leap seconds past 2000 and add them prior to + // 2000 to sync up the time zones + const double nLeapSecondsOffset = -countLeapSeconds( + year, + static_cast(std::floor(daysInYear)) + ); + + // 5 + const double nSecondsEpochOffset = static_cast( + seconds(hours(12)).count() + ); + + // Combine all of the values + const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset; + return epoch; + } + +documentation::Documentation RenderableSatellites::Documentation() { + using namespace documentation; + return { + "RenderableSatellites", + "space_renderable_satellites", + { + { + SegmentsInfo.identifier, + new DoubleVerifier, + Optional::No, + SegmentsInfo.description + }, + { + PathInfo.identifier, + new StringVerifier, + Optional::No, + PathInfo.description + }, + { + EccentricityColumnInfo.identifier, + new StringVerifier, + Optional::No, + EccentricityColumnInfo.description + }, + { + SemiMajorAxisColumnInfo.identifier, + new StringVerifier, + Optional::No, + SemiMajorAxisColumnInfo.description + }, + { + SemiMajorAxisUnitInfo.identifier, + new DoubleVerifier, + Optional::No, + SemiMajorAxisUnitInfo.description + }, + { + InclinationColumnInfo.identifier, + new StringVerifier, + Optional::No, + InclinationColumnInfo.description + }, + { + AscendingNodeColumnInfo.identifier, + new StringVerifier, + Optional::No, + AscendingNodeColumnInfo.description + }, + { + ArgumentOfPeriapsisColumnInfo.identifier, + new StringVerifier, + Optional::No, + ArgumentOfPeriapsisColumnInfo.description + }, + { + MeanAnomalyAtEpochColumnInfo.identifier, + new StringVerifier, + Optional::No, + MeanAnomalyAtEpochColumnInfo.description + }, + { + EpochColumnInfo.identifier, + new StringVerifier, + Optional::No, + EpochColumnInfo.description + } + } + }; +} + +RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _path(PathInfo) + , _nSegments(SegmentsInfo) + , _eccentricityColumnName(EccentricityColumnInfo) + , _semiMajorAxisColumnName(SemiMajorAxisColumnInfo) + , _semiMajorAxisUnit(SemiMajorAxisUnitInfo) + , _inclinationColumnName(InclinationColumnInfo) + , _ascendingNodeColumnName(AscendingNodeColumnInfo) + , _argumentOfPeriapsisColumnName(ArgumentOfPeriapsisColumnInfo) + , _meanAnomalyAtEpochColumnName(MeanAnomalyAtEpochColumnInfo) + , _epochColumnName(EpochColumnInfo) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableSatellites" + ); + + _path = + dictionary.value(PathInfo.identifier); + _nSegments = + static_cast(dictionary.value(SegmentsInfo.identifier)); + _eccentricityColumnName = + dictionary.value(EccentricityColumnInfo.identifier); + _semiMajorAxisColumnName = + dictionary.value(SemiMajorAxisColumnInfo.identifier); + _semiMajorAxisUnit = + dictionary.value(SemiMajorAxisUnitInfo.identifier); + _inclinationColumnName = + dictionary.value(InclinationColumnInfo.identifier); + _ascendingNodeColumnName = + dictionary.value(AscendingNodeColumnInfo.identifier); + _argumentOfPeriapsisColumnName = + dictionary.value(ArgumentOfPeriapsisColumnInfo.identifier); + _meanAnomalyAtEpochColumnName = + dictionary.value(MeanAnomalyAtEpochColumnInfo.identifier); + _epochColumnName = + dictionary.value(EpochColumnInfo.identifier); + + //addPropertySubOwner(_appearance); + addProperty(_path); + addProperty(_nSegments); + //addProperty(_semiMajorAxisUnit); + +/* +* test + +*/ + const std::string& file = dictionary.value(KeyFile); + //readTLEFile(file); + + LINFO(fmt::format("file: {} ", file)); + LINFO(fmt::format("KeyFile: {} ", KeyFile)); +} + + +void RenderableSatellites::readTLEFile(const std::string& filename) { + ghoul_assert(FileSys.fileExists(filename), "The filename must exist"); + + std::ifstream file; + file.exceptions(std::ofstream::failbit | std::ofstream::badbit); + file.open(filename); + + // All of the Kepler element information + struct KeplerParameters{ + double inclination = 0.0; + double semiMajorAxis = 0.0; + double ascendingNode = 0.0; + double eccentricity = 0.0; + double argumentOfPeriapsis = 0.0; + double meanAnomaly = 0.0; + double meanMotion = 0.0; + double epoch = 0.0; + }; + + //std::vector TLEData; + std::vector TLEData; + + // int numberOfLines = std::count(std::istreambuf_iterator(file), + // std::istreambuf_iterator(), '\n' ); + // 3 because a TLE has 3 lines per element/ object. + // int numberOfObjects = numberOfLines/3; + // LINFO("Number of data elements: " + numberOfObjects); + + // for(int i=0 ; i> keplerElements.inclination; + stream.clear(); + + // Get Right ascension of the ascending node + stream.str(line.substr(17, 8)); + stream >> keplerElements.ascendingNode; + stream.clear(); + + // Get Eccentricity + stream.str("0." + line.substr(26, 7)); + stream >> keplerElements.eccentricity; + stream.clear(); + + // Get argument of periapsis + stream.str(line.substr(34, 8)); + stream >> keplerElements.argumentOfPeriapsis; + stream.clear(); + + // Get mean anomaly + stream.str(line.substr(43, 8)); + stream >> keplerElements.meanAnomaly; + stream.clear(); + + // Get mean motion + stream.str(line.substr(52, 11)); + stream >> keplerElements.meanMotion; + } else { + throw ghoul::RuntimeError(fmt::format( + "File {} @ line {} does not have '2' header", filename // , lineNum + 2 + )); + } + + // Calculate the semi major axis based on the mean motion using kepler's laws + keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion); + + // Converting the mean motion (revolutions per day) to period (seconds per revolution) + using namespace std::chrono; + double period = seconds(hours(24)).count() / keplerElements.meanMotion; + /* + KeplerTranslation::KeplerOrbit TLEElements{ + keplerElements.eccentricity, + keplerElements.semiMajorAxis, + keplerElements.inclination, + keplerElements.ascendingNode, + keplerElements.argumentOfPeriapsis, + keplerElements.meanAnomaly, + period, + keplerElements.epoch + }; + + */ + _keplerTranslator.setKeplerElements( + keplerElements.eccentricity, + keplerElements.semiMajorAxis, + keplerElements.inclination, + keplerElements.ascendingNode, + keplerElements.argumentOfPeriapsis, + keplerElements.meanAnomaly, + period, + keplerElements.epoch + ); + + TLEData.push_back(keplerElements); + + + } // !while loop + + file.close(); + } +/* +RenderableSatellites::~RenderableSatellites() { + +} + */ +void RenderableSatellites::initialize() { + //readFromCsvFile(); + //LINFO(fmt::format("_path: {} ", _path)); + //readTLEFile(_path); + //updateBuffers(); + + //_path.onChange([this]() { + // readFromCsvFile(); + // updateBuffers(); + //}); + // + //_semiMajorAxisUnit.onChange([this]() { + // readFromCsvFile(); + // updateBuffers(); + //}); + + //_nSegments.onChange([this]() { + // updateBuffers(); + //}); +} + +void RenderableSatellites::deinitialize() { + +} + +void RenderableSatellites::initializeGL() { + /* + glGenVertexArrays(1, &_vertexArray); + glGenBuffers(1, &_vertexBuffer); + glGenBuffers(1, &_indexBuffer); + */ + _programObject = SpaceModule::ProgramObjectManager.request( + ProgramName, + []() -> std::unique_ptr { + return global::renderEngine.buildRenderProgram( + ProgramName, + absPath("${MODULE_SPACE}/shaders/RenderableKeplerOrbits_vs.glsl"), + absPath("${MODULE_SPACE}/shaders/RenderableKeplerOrbits_fs.glsl") + ); + } + ); + /* + _uniformCache.opacity = _programObject->uniformLocation("opacity"); + _uniformCache.modelView = _programObject->uniformLocation("modelViewTransform"); + _uniformCache.projection = _programObject->uniformLocation("projectionTransform"); + _uniformCache.color = _programObject->uniformLocation("color"); + _uniformCache.useLineFade = _programObject->uniformLocation("useLineFade"); + _uniformCache.lineFade = _programObject->uniformLocation("lineFade"); + + setRenderBin(Renderable::RenderBin::Overlay);*/ +} + +void RenderableSatellites::deinitializeGL() { + /*SpaceModule::ProgramObjectManager.release(ProgramName); + + glDeleteBuffers(1, &_vertexBuffer); + glDeleteBuffers(1, &_indexBuffer); + glDeleteVertexArrays(1, &_vertexArray);*/ +} + + +bool RenderableSatellites::isReady() const { + return true; +} + +void RenderableSatellites::update(const UpdateData&) {} + +void RenderableSatellites::render(const RenderData& data, RendererTasks&) { + //_programObject->activate(); + //_programObject->setUniform(_uniformCache.opacity, _opacity); + // + //glm::dmat4 modelTransform = + // glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + // glm::dmat4(data.modelTransform.rotation) * + // glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + //_programObject->setUniform( + // _uniformCache.modelView, + // data.camera.combinedViewMatrix() * modelTransform + //); + + //_programObject->setUniform(_uniformCache.projection, data.camera.projectionMatrix()); + //_programObject->setUniform(_uniformCache.color, _appearance.lineColor); + ////_programObject->setUniform(_uniformCache.useLineFade, _appearance.useLineFade); + + ///*if (_appearance.useLineFade) { + // _programObject->setUniform(_uniformCache.lineFade, _appearance.lineFade); + //}*/ + + //glDepthMask(false); + ////glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + //glBindVertexArray(_vertexArray); + //glDrawElements(GL_LINES, + // static_cast(_indexBufferData.size()), + // GL_UNSIGNED_INT, + // 0); + //glBindVertexArray(0); + //_programObject->deactivate(); +} + +void RenderableSatellites::updateBuffers() { + //const size_t nverticesperorbit = _nsegments + 1; + //_vertexbufferdata.resize(tledata.size() * nverticesperorbit); + //_indexbufferdata.resize(tledata.size() * _nsegments * 2); + // + //size_t orbitindex = 0; + //size_t elementindex = 0; + + //for (const auto& orbit : tledata) { + // // keplertranslation setkeplerelements(orbit); + // _keplertranslator.setkeplerelements( + // orbit.eccentricity, + // orbit.semimajoraxis, + // orbit.inclination, + // orbit.ascendingnode, + // orbit.argumentofperiapsis, + // orbit.meananomalyatepoch, + // orbit.period, + // orbit.epoch + // ); + // // keplertranslation keplertranslation(orbit); + // const double period = orbit.period(); + // for (size_t i = 0; i <= _nsegments; ++i) { + // size_t index = orbitindex * nverticesperorbit + i; + + // double timeoffset = period * + // static_cast(i) / static_cast(_nsegments); + + // // _updatedata.time.settime(orbit.epoch + timeoffset); + // // updatedata::time(time(orbit.epoch + timeoffset)); + + // updatedata updatetime; + // updatetime.time = time(orbit.epoch + timeoffset); + // + // glm::vec3 position = _keplertranslator.position(updatetime); + // // _keplertranslator.position(_updatedata.time); + // + + // _vertexbufferdata[index].x = position.x; + // _vertexbufferdata[index].y = position.y; + // _vertexbufferdata[index].z = position.z; + // _vertexbufferdata[index].time = timeoffset; + // if (i > 0) { + // _indexbufferdata[elementindex++] = static_cast(index) - 1; + // _indexbufferdata[elementindex++] = static_cast(index); + // } + // } + // ++orbitindex; + //} + // + //glbindvertexarray(_vertexarray); + // + //glbindbuffer(gl_array_buffer, _vertexbuffer); + //glbufferdata(gl_array_buffer, + // _vertexbufferdata.size() * sizeof(trailvbolayout), + // _vertexbufferdata.data(), + // gl_static_draw + // ); + // + + //glbindbuffer(gl_element_array_buffer, _indexbuffer); + //glbufferdata(gl_element_array_buffer, + // _indexbufferdata.size() * sizeof(int), + // _indexbufferdata.data(), + // gl_static_draw + // ); + // + //glbindvertexarray(0); + +} + +void RenderableSatellites::readFromCsvFile() { // std::vector columns = { // _eccentricityColumnName, // _semiMajorAxisColumnName, @@ -793,6 +810,6 @@ // std::stof(line[6]) // }; // } -//} -// -//} +} + +} diff --git a/modules/space/rendering/renderablesatellites.h b/modules/space/rendering/renderablesatellites.h index b7eff3aef5..ada8b3824e 100644 --- a/modules/space/rendering/renderablesatellites.h +++ b/modules/space/rendering/renderablesatellites.h @@ -1,125 +1,125 @@ -//// /**************************************************************************************** -//// * * -//// * OpenSpace * -//// * * -//// * Copyright (c) 2014-2018 * -//// * * -//// * Permission is hereby granted, free of charge, to any person obtaining a copy of this * -//// * software and associated documentation files (the "Software"), to deal in the Software * -//// * without restriction, including without limitation the rights to use, copy, modify, * -//// * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -//// * permit persons to whom the Software is furnished to do so, subject to the following * -//// * conditions: * -//// * * -//// * The above copyright notice and this permission notice shall be included in all copies * -//// * or substantial portions of the Software. * -//// * * -//// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -//// * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -//// * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -//// * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -//// * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -//// * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -//// ****************************************************************************************/ -// -//#include -// -//#include -//#include -// -//// #include -//#include -//#include -// -//#include -//#include -// -//#ifndef __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ -//#define __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ -// -//namespace openspace { -// -// class RenderableSatellites : public Renderable { -// public: -// RenderableSatellites(const ghoul::Dictionary& dictionary); -// virtual ~RenderableSatellites(); -// -// void initialize() override; -// void deinitialize() override; -// void initializeGL() override; -// void deinitializeGL() override; -// -// bool isReady() const override; -// -// void render(const RenderData& data, RendererTasks& rendererTask) override; -// void update(const UpdateData& data) override; -// -// static documentation::Documentation Documentation(); -// -// private: -// /// The layout of the VBOs -// struct TrailVBOLayout { -// float x, y, z, time; -// }; -// -// KeplerTranslation _keplerTranslator; -// std::vector TLEData; -// -// /// The backend storage for the vertex buffer object containing all points for this -// /// trail. -// std::vector _vertexBufferData; -// -// /// The index array that is potentially used in the draw call. If this is empty, no -// /// element draw call is used. -// std::vector _indexBufferData; -// -// GLuint _vertexArray; -// GLuint _vertexBuffer; -// GLuint _indexBuffer; -// -// void readFromCsvFile(); -// void updateBuffers(); -// -// std::vector _orbits; -// ghoul::opengl::ProgramObject* _programObject; -// //ghoul::ObjectManager* _objectManager; -// -// -// properties::StringProperty _path; -// properties::UIntProperty _nSegments; -// -// properties::StringProperty _eccentricityColumnName; -// properties::StringProperty _semiMajorAxisColumnName; -// properties::DoubleProperty _semiMajorAxisUnit; -// properties::StringProperty _inclinationColumnName; -// properties::StringProperty _ascendingNodeColumnName; -// properties::StringProperty _argumentOfPeriapsisColumnName; -// properties::StringProperty _meanAnomalyAtEpochColumnName; -// properties::StringProperty _epochColumnName; -// -// RenderableTrail::Appearance _appearance; -// -// UniformCache(opacity, modelView, projection, color, useLineFade, lineFade) -// _uniformCache; -// -// /** -// * Reads the provided TLE file and calles the KeplerTranslation::setKeplerElments -// * method with the correct values. If \p filename is a valid TLE file but contains -// * disallowed values (see KeplerTranslation::setKeplerElements), a -// * KeplerTranslation::RangeError is thrown. -// * -// * \param filename The path to the file that contains the TLE file. -// * \param lineNum The line number in the file where the set of 3 TLE lines starts -// * -// * \throw std::system_error if the TLE file is malformed (does not contain at least -// * two lines that start with \c 1 and \c 2. -// * \throw KeplerTranslation::RangeError If the Keplerian elements are outside of -// * the valid range supported by Kepler::setKeplerElements -// * \pre The \p filename must exist -// */ -// void readTLEFile(const std::string& filename); -// }; -// -//#endif // __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ -// -//} +// /**************************************************************************************** +// * * +// * OpenSpace * +// * * +// * Copyright (c) 2014-2018 * +// * * +// * Permission is hereby granted, free of charge, to any person obtaining a copy of this * +// * software and associated documentation files (the "Software"), to deal in the Software * +// * without restriction, including without limitation the rights to use, copy, modify, * +// * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +// * permit persons to whom the Software is furnished to do so, subject to the following * +// * conditions: * +// * * +// * The above copyright notice and this permission notice shall be included in all copies * +// * or substantial portions of the Software. * +// * * +// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +// * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +// * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +// * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +// * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +// * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +// ****************************************************************************************/ + +#include + +#include +#include + +// #include +#include +#include + +#include +#include + +#ifndef __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ +#define __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ + +namespace openspace { + + class RenderableSatellites : public Renderable { + public: + RenderableSatellites(const ghoul::Dictionary& dictionary); + //virtual ~RenderableSatellites(); + + void initialize() override; + void deinitialize() override; + void initializeGL() override; + void deinitializeGL() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; + + static documentation::Documentation Documentation(); + + private: + /// The layout of the VBOs + struct TrailVBOLayout { + float x, y, z, time; + }; + + KeplerTranslation _keplerTranslator; + std::vector TLEData; + + /// The backend storage for the vertex buffer object containing all points for this + /// trail. + std::vector _vertexBufferData; + + /// The index array that is potentially used in the draw call. If this is empty, no + /// element draw call is used. + std::vector _indexBufferData; + + GLuint _vertexArray; + GLuint _vertexBuffer; + GLuint _indexBuffer; + + void readFromCsvFile(); + void updateBuffers(); + + std::vector _orbits; + ghoul::opengl::ProgramObject* _programObject; + //ghoul::ObjectManager* _objectManager; + + + properties::StringProperty _path; + properties::UIntProperty _nSegments; + + properties::StringProperty _eccentricityColumnName; + properties::StringProperty _semiMajorAxisColumnName; + properties::DoubleProperty _semiMajorAxisUnit; + properties::StringProperty _inclinationColumnName; + properties::StringProperty _ascendingNodeColumnName; + properties::StringProperty _argumentOfPeriapsisColumnName; + properties::StringProperty _meanAnomalyAtEpochColumnName; + properties::StringProperty _epochColumnName; + + //RenderableTrail::Appearance _appearance; + + // UniformCache(opacity, modelView, projection, color, useLineFade, lineFade) + // _uniformCache; + + /** + * Reads the provided TLE file and calles the KeplerTranslation::setKeplerElments + * method with the correct values. If \p filename is a valid TLE file but contains + * disallowed values (see KeplerTranslation::setKeplerElements), a + * KeplerTranslation::RangeError is thrown. + * + * \param filename The path to the file that contains the TLE file. + * \param lineNum The line number in the file where the set of 3 TLE lines starts + * + * \throw std::system_error if the TLE file is malformed (does not contain at least + * two lines that start with \c 1 and \c 2. + * \throw KeplerTranslation::RangeError If the Keplerian elements are outside of + * the valid range supported by Kepler::setKeplerElements + * \pre The \p filename must exist + */ + void readTLEFile(const std::string& filename); + }; + +#endif // __OPENSPACE_MODULE_BASE___RenderableSatellites___H__ + +} diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index efac46c3b1..12a91b6eed 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -22,6 +22,9 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__ +#define __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__ + #include #include @@ -29,7 +32,7 @@ #include #include #include -#include +#include s #include #include #include @@ -82,7 +85,9 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary&) { fRenderable->registerClass("RenderablePlanet"); fRenderable->registerClass("RenderableRings"); fRenderable->registerClass("RenderableStars"); - fRenderable->registerClass("ElonsTest"); + fRenderable->registerClass("RenderableSatellites"); + //fRenderable->registerClass("ElonsTest"); + auto fTranslation = FactoryManager::ref().factory(); ghoul_assert(fTranslation, "Ephemeris factory was not created"); @@ -112,7 +117,8 @@ std::vector SpaceModule::documentations() const { RenderablePlanet::Documentation(), RenderableRings::Documentation(), RenderableStars::Documentation(), - ElonsTest::Documentation(), + RenderableSatellites::Documentation(), + //ElonsTest::Documentation(), SpiceRotation::Documentation(), SpiceTranslation::Documentation(), KeplerTranslation::Documentation(), @@ -124,3 +130,5 @@ std::vector SpaceModule::documentations() const { } } // namespace openspace + +#endif // __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__