diff --git a/ext/ghoul b/ext/ghoul index 26de570dec..d073de9ab1 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 26de570dec769496c7d04707325db9a390465906 +Subproject commit d073de9ab1b81b234a5a1cf55fdec36f029fc639 diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index fd14a12faf..2768e29a59 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -33,11 +33,15 @@ #include #include #include +#include "SpiceUsr.h" +#include "SpiceZpr.h" namespace openspace { namespace scripting { struct LuaLibrary; } +void throwSpiceError(const std::string& errorMessage); + class SpiceManager { public: BooleanType(UseException); @@ -462,6 +466,7 @@ public: * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/str2et_c.html */ double ephemerisTimeFromDate(const std::string& timeString) const; + double ephemerisTimeFromDate(const char* timeString) const; /** * Converts the passed \p ephemerisTime into a human-readable date string with a @@ -476,11 +481,33 @@ public: * * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html */ + template std::string dateFromEphemerisTime(double ephemerisTime, - std::string_view format = "YYYY MON DDTHR:MN:SC.### ::RND") const; + const char (&format)[N] = "YYYY MON DDTHR:MN:SC.### ::RND") const + { + static_assert(N != 0, "Format must not be empty"); + std::string res; + res.resize(N); + dateFromEphemerisTime(ephemerisTime, res.data(), N, format); + return res; + } + + template void dateFromEphemerisTime(double ephemerisTime, char* outBuf, int bufferSize, - std::string_view format = "YYYY MON DDTHR:MN:SC.### ::RND") const; + const char (&format)[N] = "YYYY MON DDTHR:MN:SC.### ::RND") const + { + static_assert(N != 0, "Format must not be empty"); + ghoul_assert(N > bufferSize - 1, "Buffer size too small"); + + timout_c(ephemerisTime, format, bufferSize - 1, outBuf); + if (failed_c()) { + throwSpiceError(fmt::format( + "Error converting ephemeris time '{}' to date with format '{}'", + ephemerisTime, format + )); + } + } /** * Returns the \p position of a \p target body relative to an \p observer in a diff --git a/include/openspace/util/time.h b/include/openspace/util/time.h index 25c29bd2e6..d055971725 100644 --- a/include/openspace/util/time.h +++ b/include/openspace/util/time.h @@ -64,6 +64,7 @@ public: * \pre \p timeString must not be empty */ static double convertTime(const std::string& time); + static double convertTime(const char* time); explicit Time(double secondsJ2000 = -1); explicit Time(const std::string& time); @@ -113,13 +114,13 @@ public: * thus also compliant with the Spice library. * \return The current time as a formatted date string */ - std::string UTC() const; + std::string_view UTC() const; /** * Returns the current time as a ISO 8601 formatted, i.e YYYY-MM-DDThh:mm:ssZ * \return The current time as a ISO 8601 formatted string */ - std::string ISO8601() const; + std::string_view ISO8601() const; /** * Advances the simulation time using the deltaTime() and the tickTime. diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index bd717431ad..7327514e37 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -245,7 +245,7 @@ bool FieldlinesState::loadStateFromJson(const std::string& pathToJsonFile, */ void FieldlinesState::saveStateToOsfls(const std::string& absPath) { // ------------------------------- Create the file ------------------------------- // - std::string pathSafeTimeString = Time(_triggerTime).ISO8601(); + std::string pathSafeTimeString = std::string(Time(_triggerTime).ISO8601()); pathSafeTimeString.replace(13, 1, "-"); pathSafeTimeString.replace(16, 1, "-"); pathSafeTimeString.replace(19, 1, "-"); @@ -341,7 +341,7 @@ void FieldlinesState::saveStateToJson(const std::string& absPath) { json jFile; - const std::string timeStr = Time(_triggerTime).ISO8601(); + std::string_view timeStr = Time(_triggerTime).ISO8601(); const size_t nLines = _lineStart.size(); // const size_t nPoints = _vertexPositions.size(); const size_t nExtras = _extraQuantities.size(); diff --git a/modules/globebrowsing/src/tileprovider.cpp b/modules/globebrowsing/src/tileprovider.cpp index 3e57d400d3..fc0f9b4a2c 100644 --- a/modules/globebrowsing/src/tileprovider.cpp +++ b/modules/globebrowsing/src/tileprovider.cpp @@ -278,9 +278,9 @@ std::string timeStringify(TemporalTileProvider::TimeFormatType type, const Time& switch (type) { case TemporalTileProvider::TimeFormatType::YYYY_MM_DD: - return t.ISO8601().substr(0, 10); + return std::string(t.ISO8601().substr(0, 10)); case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmmss: { - std::string ts = t.ISO8601().substr(0, 19); + std::string ts = std::string(t.ISO8601().substr(0, 19)); // YYYY_MM_DDThh_mm_ss -> YYYYMMDD_hhmmss ts.erase(std::remove(ts.begin(), ts.end(), '-'), ts.end()); @@ -289,7 +289,7 @@ std::string timeStringify(TemporalTileProvider::TimeFormatType type, const Time& return ts; } case TemporalTileProvider::TimeFormatType::YYYYMMDD_hhmm: { - std::string ts = t.ISO8601().substr(0, 16); + std::string ts = std::string(t.ISO8601().substr(0, 16)); // YYYY_MM_DDThh_mm -> YYYYMMDD_hhmm ts.erase(std::remove(ts.begin(), ts.end(), '-'), ts.end()); @@ -298,9 +298,9 @@ std::string timeStringify(TemporalTileProvider::TimeFormatType type, const Time& return ts; } case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThhColonmmColonssZ: - return t.ISO8601().substr(0, 19) + "Z"; + return std::string(t.ISO8601().substr(0, 19)) + "Z"; case TemporalTileProvider::TimeFormatType::YYYY_MM_DDThh_mm_ssZ: { - std::string timeString = t.ISO8601().substr(0, 19) + "Z"; + std::string timeString = std::string(t.ISO8601().substr(0, 19)) + "Z"; replace(timeString.begin(), timeString.end(), ':', '_'); return timeString; } @@ -423,7 +423,10 @@ std::string consumeTemporalMetaData(TemporalTileProvider& t, const std::string& } try { - t.timeQuantizer.setStartEndRange(start.ISO8601(), end.ISO8601()); + t.timeQuantizer.setStartEndRange( + std::string(start.ISO8601()), + std::string(end.ISO8601()) + ); t.timeQuantizer.setResolution(timeResolution); } catch (const ghoul::RuntimeError& e) { diff --git a/modules/globebrowsing/src/timequantizer.cpp b/modules/globebrowsing/src/timequantizer.cpp index 707c7f850e..7638cc5237 100644 --- a/modules/globebrowsing/src/timequantizer.cpp +++ b/modules/globebrowsing/src/timequantizer.cpp @@ -137,11 +137,11 @@ std::string RangedTime::clamp(const std::string& checkTime) { } } -std::string RangedTime::start() const { +std::string_view RangedTime::start() const { return _start; } -std::string RangedTime::end() const { +std::string_view RangedTime::end() const { return _end; } @@ -174,10 +174,14 @@ std::string DateTime::ISO8601() const { }; double DateTime::J2000() const { - Time t; - std::string timeString = ISO8601(); - t.setTime(timeString); - return t.j2000Seconds(); + char Buffer[20]; + std::memset(Buffer, 0, 20); + fmt::format_to( + Buffer, + "{:0>4}-{:0>2}-{:0>2}T{:0>2}:{:0>2}:{:0>2}", + _year, _month, _day, _hour, _minute, _second + ); + return Time::convertTime(Buffer); } void DateTime::operator=(DateTime& src) { @@ -471,7 +475,7 @@ double TimeQuantizer::computeSecondsFromResolution(const int valueIn, const char bool TimeQuantizer::quantize(Time& t, bool clamp) { ZoneScoped - const std::string unquantizedStr = t.ISO8601(); + std::string_view unquantizedStr = t.ISO8601(); DateTime unquantized(unquantizedStr); // resolutionFraction helps to improve iteration performance constexpr const double ResolutionFraction = 0.7; @@ -514,7 +518,7 @@ bool TimeQuantizer::quantize(Time& t, bool clamp) { return true; } else if (clamp) { - const std::string clampedTime = _timerange.clamp(unquantizedStr); + const std::string clampedTime = _timerange.clamp(std::string(unquantizedStr)); t.setTime(clampedTime); return true; } @@ -612,7 +616,7 @@ std::vector TimeQuantizer::quantized(Time& start, Time& end) { std::vector result; DateTime itr = s; - RangedTime range(start.ISO8601(), end.ISO8601()); + RangedTime range(std::string(start.ISO8601()), std::string(end.ISO8601())); while (range.includes(Time(itr.ISO8601()))) { itr.incrementOnce(static_cast(_resolutionValue), _resolutionUnit); result.push_back(itr.ISO8601()); diff --git a/modules/globebrowsing/src/timequantizer.h b/modules/globebrowsing/src/timequantizer.h index 3d7b00b81a..f439a952cc 100644 --- a/modules/globebrowsing/src/timequantizer.h +++ b/modules/globebrowsing/src/timequantizer.h @@ -76,14 +76,14 @@ public: * * \returns The ISO8601 date/time string that defines the start of the range */ - std::string start() const; + std::string_view start() const; /* * Get the end date/time of the time range * * \returns The ISO8601 date/time string that defines the end of the range */ - std::string end() const; + std::string_view end() const; /* * Set the start date/time of the time range diff --git a/modules/imgui/src/guimissioncomponent.cpp b/modules/imgui/src/guimissioncomponent.cpp index 12886f8821..49a7c9e3b4 100644 --- a/modules/imgui/src/guimissioncomponent.cpp +++ b/modules/imgui/src/guimissioncomponent.cpp @@ -63,7 +63,7 @@ namespace { openspace::gui::CaptionText("Mission Progress"); - ImGui::Text("%s", startTime.UTC().c_str()); + ImGui::Text("%s", std::string(startTime.UTC()).c_str()); ImGui::SameLine(); float v = static_cast(currentTime); const float s = static_cast(startTime.j2000Seconds()); @@ -74,10 +74,10 @@ namespace { &v, s, e, - openspace::global::timeManager.time().UTC().c_str() + std::string(openspace::global::timeManager.time().UTC()).c_str() ); ImGui::SameLine(); - ImGui::Text("%s", endTime.UTC().c_str()); + ImGui::Text("%s", std::string(endTime.UTC()).c_str()); openspace::gui::CaptionText("Phases"); diff --git a/modules/imgui/src/guispacetimecomponent.cpp b/modules/imgui/src/guispacetimecomponent.cpp index f9acbb05ab..132d52f466 100644 --- a/modules/imgui/src/guispacetimecomponent.cpp +++ b/modules/imgui/src/guispacetimecomponent.cpp @@ -211,7 +211,10 @@ void GuiSpaceTimeComponent::render() { ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 10.f); - ImGui::Text("Current Date: %s", global::timeManager.time().UTC().c_str()); + ImGui::Text( + "Current Date: %s", + std::string(global::timeManager.time().UTC()).c_str() + ); constexpr int BufferSize = 256; static char Buffer[BufferSize]; @@ -296,7 +299,7 @@ void GuiSpaceTimeComponent::render() { const bool nowDay = ImGui::Button("Now"); if (nowDay) { - std::string nowTime = Time::now().UTC(); + std::string nowTime = std::string(Time::now().UTC()); // UTC returns a string of the type YYYY MMM DDTHH:mm:ss.xxx // setTime doesn't like the T in it and wants a space instead nowTime[11] = ' '; diff --git a/modules/iswa/util/iswamanager.cpp b/modules/iswa/util/iswamanager.cpp index 5046bb85a9..7d0eb666b9 100644 --- a/modules/iswa/util/iswamanager.cpp +++ b/modules/iswa/util/iswamanager.cpp @@ -269,8 +269,9 @@ std::string IswaManager::iswaUrl(int id, double timestamp, const std::string& ty } //std::string t = Time::ref().currentTimeUTC(); - std::string t = SpiceManager::ref().dateFromEphemerisTime(timestamp); - std::stringstream ss(t); + std::string_view t = SpiceManager::ref().dateFromEphemerisTime(timestamp); + std::stringstream ss; + ss << t; std::string token; std::getline(ss, token, ' '); diff --git a/modules/server/src/topics/timetopic.cpp b/modules/server/src/topics/timetopic.cpp index 71d422948c..0f69ec293b 100644 --- a/modules/server/src/topics/timetopic.cpp +++ b/modules/server/src/topics/timetopic.cpp @@ -109,7 +109,7 @@ void TimeTopic::sendCurrentTime() { } void TimeTopic::sendFullTimeData() { - const std::string currentTime = global::timeManager.time().ISO8601(); + std::string_view currentTime = global::timeManager.time().ISO8601(); const double deltaTime = global::timeManager.deltaTime(); const double targetDeltaTime = global::timeManager.targetDeltaTime(); const bool isPaused = global::timeManager.isPaused(); diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp index 7e6e05b87d..1d52867fa5 100644 --- a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp @@ -230,7 +230,7 @@ void DashboardItemInstruments::render(glm::vec2& penPosition) { ghoul::fontrendering::CrDirection::Down ); - std::string str = SpiceManager::ref().dateFromEphemerisTime( + std::string_view str = SpiceManager::ref().dateFromEphemerisTime( sequencer.nextCaptureTime(global::timeManager.time().j2000Seconds()), "YYYY MON DD HR:MN:SC" ); diff --git a/modules/volume/rawvolumemetadata.cpp b/modules/volume/rawvolumemetadata.cpp index 83b24616ef..e7886f57ca 100644 --- a/modules/volume/rawvolumemetadata.cpp +++ b/modules/volume/rawvolumemetadata.cpp @@ -112,12 +112,12 @@ ghoul::Dictionary RawVolumeMetadata::dictionary() { } if (hasTime) { - std::string timeString = Time(time).ISO8601(); + std::string_view timeString = Time(time).ISO8601(); // Do not include time offset in time string if (timeString.back() == 'Z') { - timeString.pop_back(); + timeString = timeString.substr(0, timeString.size() - 1); } - dict.setValue(KeyTime, timeString); + dict.setValue(KeyTime, std::string(timeString)); } return dict; } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index c0b79c92af..627576a970 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1057,6 +1057,8 @@ void OpenSpaceEngine::writeSceneDocumentation() { void OpenSpaceEngine::preSynchronization() { ZoneScoped + TracyGpuZone("preSynchronization") + LTRACE("OpenSpaceEngine::preSynchronization(begin)"); FileSys.triggerFilesystemEvents(); @@ -1125,6 +1127,7 @@ void OpenSpaceEngine::preSynchronization() { void OpenSpaceEngine::postSynchronizationPreDraw() { ZoneScoped + TracyGpuZone("postSynchronizationPreDraw") LTRACE("OpenSpaceEngine::postSynchronizationPreDraw(begin)"); bool master = global::windowDelegate.isMaster(); @@ -1196,6 +1199,7 @@ void OpenSpaceEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& view const glm::mat4& projectionMatrix) { ZoneScoped + TracyGpuZone("Render") LTRACE("OpenSpaceEngine::render(begin)"); const bool isGuiWindow = @@ -1220,6 +1224,7 @@ void OpenSpaceEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& view void OpenSpaceEngine::drawOverlays() { ZoneScoped + TracyGpuZone("Draw2D") LTRACE("OpenSpaceEngine::drawOverlays(begin)"); const bool isGuiWindow = @@ -1244,6 +1249,7 @@ void OpenSpaceEngine::drawOverlays() { void OpenSpaceEngine::postDraw() { ZoneScoped + TracyGpuZone("postDraw") LTRACE("OpenSpaceEngine::postDraw(begin)"); global::renderEngine.postDraw(); diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index e637d25e42..19de9034df 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -1132,6 +1132,7 @@ void FramebufferRenderer::updateDownscaledVolume() { void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFactor) { ZoneScoped + TracyGpuZone("FramebufferRenderer") GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); @@ -1177,25 +1178,31 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac RendererTasks tasks; { + TracyGpuZone("Background") GLDebugGroup group("Background"); data.renderBinMask = static_cast(Renderable::RenderBin::Background); scene->render(data, tasks); } { + TracyGpuZone("Opaque") GLDebugGroup group("Opaque"); data.renderBinMask = static_cast(Renderable::RenderBin::Opaque); scene->render(data, tasks); } { + TracyGpuZone("PreDeferredTransparent") GLDebugGroup group("PreDeferredTransparent"); - data.renderBinMask = static_cast(Renderable::RenderBin::PreDeferredTransparent); + data.renderBinMask = static_cast( + Renderable::RenderBin::PreDeferredTransparent + ); scene->render(data, tasks); } // Run Volume Tasks { + TracyGpuZone("Raycaster Tasks") GLDebugGroup group("Raycaster Tasks"); performRaycasterTasks(tasks.raycasterTasks); @@ -1205,6 +1212,7 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac } if (!tasks.deferredcasterTasks.empty()) { + TracyGpuZone("Deferred Caster Tasks") GLDebugGroup group("Deferred Caster Tasks"); // We use ping pong rendering in order to be able to @@ -1220,12 +1228,16 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac glEnablei(GL_BLEND, 0); { + TracyGpuZone("PostDeferredTransparent") GLDebugGroup group("PostDeferredTransparent"); - data.renderBinMask = static_cast(Renderable::RenderBin::PostDeferredTransparent); + data.renderBinMask = static_cast( + Renderable::RenderBin::PostDeferredTransparent + ); scene->render(data, tasks); } { + TracyGpuZone("Overlay") GLDebugGroup group("Overlay"); data.renderBinMask = static_cast(Renderable::RenderBin::Overlay); scene->render(data, tasks); @@ -1252,12 +1264,14 @@ void FramebufferRenderer::render(Scene* scene, Camera* camera, float blackoutFac { // Apply the selected TMO on the results and resolve the result to the default FBO + TracyGpuZone("Apply TMO") GLDebugGroup group("Apply TMO"); applyTMO(blackoutFactor); } if (_enableFXAA) { + TracyGpuZone("Apply FXAA") GLDebugGroup group("Apply FXAA"); glBindFramebuffer(GL_FRAMEBUFFER, _defaultFBO); applyFXAA(); @@ -1268,6 +1282,8 @@ void FramebufferRenderer::performRaycasterTasks(const std::vector ZoneScoped for (const RaycasterTask& raycasterTask : tasks) { + TracyGpuZone("Raycaster") + VolumeRaycaster* raycaster = raycasterTask.raycaster; glBindFramebuffer(GL_FRAMEBUFFER, _exitFramebuffer); @@ -1399,6 +1415,8 @@ void FramebufferRenderer::performDeferredTasks( ZoneScoped for (const DeferredcasterTask& deferredcasterTask : tasks) { + TracyGpuZone("Deferredcaster") + Deferredcaster* deferredcaster = deferredcasterTask.deferredcaster; ghoul::opengl::ProgramObject* deferredcastProgram = nullptr; diff --git a/src/scene/profile_lua.inl b/src/scene/profile_lua.inl index 1c2c904ee7..a60c6b4c59 100644 --- a/src/scene/profile_lua.inl +++ b/src/scene/profile_lua.inl @@ -80,7 +80,7 @@ int saveSettingsToProfile(lua_State* L) { } const properties::PropertyOwner& root = global::rootPropertyOwner; - std::string currentTime = global::timeManager.time().ISO8601(); + std::string currentTime = std::string(global::timeManager.time().ISO8601()); interaction::NavigationHandler::NavigationState navState = global::navigationHandler.navigationState(); global::profile.saveCurrentSettingsToProfile(root, currentTime, navState); diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index 7792a6b2ce..e5ff380b61 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -43,18 +43,6 @@ namespace { // as the maximum message length constexpr const unsigned SpiceErrorBufferSize = 1841; - // This method checks if one of the previous SPICE methods has failed. If it has, an - // exception with the SPICE error message is thrown - // If an error occurred, true is returned, otherwise, false - void throwSpiceError(const std::string& errorMessage) { - if (openspace::SpiceManager::ref().exceptionHandling()) { - char buffer[SpiceErrorBufferSize]; - getmsg_c("LONG", SpiceErrorBufferSize, buffer); - reset_c(); - throw openspace::SpiceManager::SpiceException(errorMessage + ": " + buffer); - } - } - const char* toString(openspace::SpiceManager::FieldOfViewMethod m) { using SM = openspace::SpiceManager; switch (m) { @@ -196,6 +184,18 @@ SpiceManager& SpiceManager::ref() { return *_instance; } +// This method checks if one of the previous SPICE methods has failed. If it has, an +// exception with the SPICE error message is thrown +// If an error occurred, true is returned, otherwise, false +void throwSpiceError(const std::string& errorMessage) { + if (openspace::SpiceManager::ref().exceptionHandling()) { + char buffer[SpiceErrorBufferSize]; + getmsg_c("LONG", SpiceErrorBufferSize, buffer); + reset_c(); + throw openspace::SpiceManager::SpiceException(errorMessage + ": " + buffer); + } +} + SpiceManager::KernelHandle SpiceManager::loadKernel(std::string filePath) { ghoul_assert(!filePath.empty(), "Empty file path"); ghoul_assert( @@ -474,58 +474,20 @@ double SpiceManager::spacecraftClockToET(const std::string& craft, double craftT double SpiceManager::ephemerisTimeFromDate(const std::string& timeString) const { ghoul_assert(!timeString.empty(), "Empty timeString"); + return ephemerisTimeFromDate(timeString.c_str()); +} + +double SpiceManager::ephemerisTimeFromDate(const char* timeString) const { + ghoul_assert(!timeString.empty(), "Empty timeString"); + double et; - str2et_c(timeString.c_str(), &et); + str2et_c(timeString, &et); if (failed_c()) { throwSpiceError(fmt::format("Error converting date '{}'", timeString)); } return et; } -std::string SpiceManager::dateFromEphemerisTime(double ephemerisTime, - std::string_view format) const -{ - ghoul_assert(!formatString.empty(), "Format is empty"); - ghoul_assert(formatString.back() == '\0', "Format string must be null-terminated"); - - if (format.size() < 32) { - constexpr const int BufferSize = 32; - SpiceChar buffer[BufferSize]; - dateFromEphemerisTime(ephemerisTime, buffer, BufferSize, format); - return std::string(buffer); - } - else if (format.size() < 256) { - constexpr const int BufferSize = 256; - SpiceChar buffer[BufferSize]; - dateFromEphemerisTime(ephemerisTime, buffer, BufferSize, format); - return std::string(buffer); - } - else { - std::string res; - res.resize(format.size() + 1); - dateFromEphemerisTime(ephemerisTime, res.data(), format.size(), format); - return res; - } -} - -void SpiceManager::dateFromEphemerisTime(double ephemerisTime, char* outBuf, - int bufferSize, - std::string_view formatString) const -{ - ghoul_assert(!formatString.empty(), "Format is empty"); - ghoul_assert(formatString.back() == '\0', "Format string must be null-terminated"); - ghoul_assert(formatString.size() > bufferSize - 1, "Buffer size too small"); - - timout_c(ephemerisTime, formatString.data(), bufferSize - 1, outBuf); - if (failed_c()) { - throwSpiceError( - fmt::format("Error converting ephemeris time '{}' to date with format '{}'", - ephemerisTime, formatString - ) - ); - } -} - glm::dvec3 SpiceManager::targetPosition(const std::string& target, const std::string& observer, const std::string& referenceFrame, diff --git a/src/util/time.cpp b/src/util/time.cpp index f9ad8bc102..cf5600108d 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -24,7 +24,9 @@ #include +#include #include +#include #include #include #include @@ -43,6 +45,10 @@ double Time::convertTime(const std::string& time) { return SpiceManager::ref().ephemerisTimeFromDate(time); } +double Time::convertTime(const char* time) { + return SpiceManager::ref().ephemerisTimeFromDate(time); +} + Time::Time(double secondsJ2000) : _time(secondsJ2000) {} Time::Time(const std::string& time) : @@ -79,17 +85,26 @@ void Time::setTime(const std::string& time) { _time = SpiceManager::ref().ephemerisTimeFromDate(time); } -std::string Time::UTC() const { - return SpiceManager::ref().dateFromEphemerisTime(_time); +std::string_view Time::UTC() const { + constexpr const char Format[] = "YYYY MON DDTHR:MN:SC.### ::RND"; + char* b = reinterpret_cast(global::memoryManager.TemporaryMemory.allocate(32)); + std::memset(b, 0, 32); + + SpiceManager::ref().dateFromEphemerisTime(_time, b, 32, Format); + + return std::string_view(b, 32); } -std::string Time::ISO8601() const { +std::string_view Time::ISO8601() const { ZoneScoped - return SpiceManager::ref().dateFromEphemerisTime( - _time, - "YYYY-MM-DDTHR:MN:SC.###" - ); + constexpr const char Format[] = "YYYY-MM-DDTHR:MN:SC.###"; + char* b = reinterpret_cast(global::memoryManager.TemporaryMemory.allocate(24)); + std::memset(b, 0, 24); + + SpiceManager::ref().dateFromEphemerisTime(_time, b, 24, Format); + + return std::string_view(b, 24); } scripting::LuaLibrary Time::luaLibrary() { diff --git a/src/util/time_lua.inl b/src/util/time_lua.inl index 008f129b91..0437105147 100644 --- a/src/util/time_lua.inl +++ b/src/util/time_lua.inl @@ -506,7 +506,7 @@ int time_interpolateTimeRelative(lua_State* L) { * It is returned by calling the Time::currentTime method. */ int time_currentTime(lua_State* L) { - lua_pushnumber(L, global::timeManager.time().j2000Seconds()); + ghoul::lua::push(L, global::timeManager.time().j2000Seconds()); ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; } @@ -518,7 +518,7 @@ int time_currentTime(lua_State* L) { * timezone by calling the Time::UTC method */ int time_currentTimeUTC(lua_State* L) { - lua_pushstring(L, global::timeManager.time().UTC().c_str()); + ghoul::lua::push(L, global::timeManager.time().UTC()); ghoul_assert(lua_gettop(L) == 1, "Incorrect number of items left on stack"); return 1; }