From 3d78e698e7128583427ea4610224c9df5a28bd66 Mon Sep 17 00:00:00 2001 From: mariaBrunned Date: Mon, 3 Jun 2024 15:24:31 -0400 Subject: [PATCH] Recieve two textures in Openspace and Send camera matrix --- data/assets/examples/screenspacespout.asset | 2 +- modules/base/CMakeLists.txt | 2 + modules/base/basemodule.cpp | 3 + modules/base/rendering/renderableplane.h | 8 +- modules/base/rendering/renderablevolumeyt.cpp | 401 ++++++++++++++++++ modules/base/rendering/renderablevolumeyt.h | 108 +++++ modules/base/shaders/plane_fs_yt.glsl | 74 ++++ modules/server/CMakeLists.txt | 2 + .../server/include/topics/camerainfotopic.h | 56 +++ modules/server/src/connection.cpp | 2 + modules/server/src/topics/camerainfotopic.cpp | 107 +++++ modules/spout/spoutwrapper.cpp | 11 +- modules/spout/spoutwrapper.h | 4 +- 13 files changed, 770 insertions(+), 10 deletions(-) create mode 100644 modules/base/rendering/renderablevolumeyt.cpp create mode 100644 modules/base/rendering/renderablevolumeyt.h create mode 100644 modules/base/shaders/plane_fs_yt.glsl create mode 100644 modules/server/include/topics/camerainfotopic.h create mode 100644 modules/server/src/topics/camerainfotopic.cpp diff --git a/data/assets/examples/screenspacespout.asset b/data/assets/examples/screenspacespout.asset index 7aa5b6a8d6..272fa61eb2 100644 --- a/data/assets/examples/screenspacespout.asset +++ b/data/assets/examples/screenspacespout.asset @@ -6,7 +6,7 @@ local Spout = { Identifier = "Spouty", Parent = transforms.SolarSystemBarycenter.Identifier, Renderable = { - Type = "RenderablePlaneSpout", + Type = "RenderableVolumeYt", Size = 3.0E11, Origin = "Center", Billboard = true diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index e3168b3272..637721a133 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -54,6 +54,7 @@ set(HEADER_FILES rendering/renderablenodearrow.h rendering/renderablenodeline.h rendering/renderableplane.h + rendering/renderablevolumeyt.h rendering/renderableplaneimagelocal.h rendering/renderableplaneimageonline.h rendering/renderableplanetimevaryingimage.h @@ -116,6 +117,7 @@ set(SOURCE_FILES rendering/renderablenodearrow.cpp rendering/renderablenodeline.cpp rendering/renderableplane.cpp + rendering/renderablevolumeyt.cpp rendering/renderableplaneimagelocal.cpp rendering/renderableplaneimageonline.cpp rendering/renderableplanetimevaryingimage.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 9dc5c9e9b4..3e4c9ef71f 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -61,6 +61,7 @@ #include #include #include +#include // yt #include #include #include @@ -164,6 +165,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) { fRenderable->registerClass("RenderableSphericalGrid"); fRenderable->registerClass("RenderableTrailOrbit"); fRenderable->registerClass("RenderableTrailTrajectory"); + fRenderable->registerClass("RenderableVolumeYt"); // yt ghoul::TemplateFactory* fTranslation = FactoryManager::ref().factory(); @@ -250,6 +252,7 @@ std::vector BaseModule::documentations() const { RenderableTimeVaryingSphere::Documentation(), RenderableTrailOrbit::Documentation(), RenderableTrailTrajectory::Documentation(), + RenderableVolumeYt::Documentation(), // yt ScreenSpaceDashboard::Documentation(), ScreenSpaceFramebuffer::Documentation(), diff --git a/modules/base/rendering/renderableplane.h b/modules/base/rendering/renderableplane.h index 2144d95a75..0c95469a09 100644 --- a/modules/base/rendering/renderableplane.h +++ b/modules/base/rendering/renderableplane.h @@ -42,12 +42,12 @@ namespace ghoul::opengl { namespace openspace { -struct RenderData; -struct UpdateData; + struct RenderData; + struct UpdateData; -namespace documentation { struct Documentation; } + namespace documentation { struct Documentation; } -struct LinePoint; + struct LinePoint; class RenderablePlane : public Renderable { public: diff --git a/modules/base/rendering/renderablevolumeyt.cpp b/modules/base/rendering/renderablevolumeyt.cpp new file mode 100644 index 0000000000..ad7ae9d15f --- /dev/null +++ b/modules/base/rendering/renderablevolumeyt.cpp @@ -0,0 +1,401 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2024 * + * * + * 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 // from renderablespout.cpp +#include +#include +#include +#include +#include +#include +#include +#include + +// Debug purposes +#include +using namespace std; + +namespace { + constexpr std::array UniformNames = { + "modelViewProjection", "modelViewTransform", "colorTexture", "opacity", + "mirrorBackside", "multiplyColor" + }; + + enum BlendMode { + Normal = 0, + Additive + }; + + constexpr openspace::properties::Property::PropertyInfo BillboardInfo = { + "Billboard", + "Billboard mode", + "This value specifies whether the plane is a billboard, which means that it is " + "always facing the camera. If this is false, it can be oriented using other " + "transformations", + openspace::properties::Property::Visibility::AdvancedUser + }; + + constexpr openspace::properties::Property::PropertyInfo MirrorBacksideInfo = { + "MirrorBackside", + "Mirror backside of image plane", + "If this value is set to false, the image plane will not be mirrored when " + "looking from the backside. This is usually desirable when the image shows " + "data at a specific location, but not if it is displaying text for example", + // @VISIBILITY(2.67) + openspace::properties::Property::Visibility::User + }; + + constexpr openspace::properties::Property::PropertyInfo SizeInfo = { + "Size", + "Size (in meters)", + "This value specifies the size of the plane in meters", + openspace::properties::Property::Visibility::AdvancedUser + }; + + constexpr openspace::properties::Property::PropertyInfo AutoScaleInfo = { + "AutoScale", + "Auto Scale", + "When true, the plane will automatically adjust in size to match the aspect " + "ratio of the content. Otherwise it will remain in the given size." + }; + + constexpr openspace::properties::Property::PropertyInfo BlendModeInfo = { + "BlendMode", + "Blending Mode", + "This determines the blending mode that is applied to this plane", + openspace::properties::Property::Visibility::AdvancedUser + }; + + constexpr openspace::properties::Property::PropertyInfo MultiplyColorInfo = { + "MultiplyColor", + "Multiply Color", + "If set, the plane's texture is multiplied with this color. Useful for applying " + "a color grayscale images", + openspace::properties::Property::Visibility::User + }; + + struct [[codegen::Dictionary(RenderablePlane)]] Parameters { + // [[codegen::verbatim(BillboardInfo.description)]] + std::optional billboard; + + // [[codegen::verbatim(MirrorBacksideInfo.description)]] + std::optional mirrorBackside; + + // [[codegen::verbatim(SizeInfo.description)]] + std::variant size; + + enum class [[codegen::map(BlendMode)]] BlendMode { + Normal, + Additive + }; + // [[codegen::verbatim(BlendModeInfo.description)]] + std::optional blendMode; + + // [[codegen::verbatim(MultiplyColorInfo.description)]] + std::optional multiplyColor [[codegen::color()]]; + + std::optional spoutName; // yt + }; +#include "renderableplane_codegen.cpp" +} // namespace + +namespace openspace { + +documentation::Documentation RenderableVolumeYt::Documentation() { + return codegen::doc("yt_renderable_volume"); +} + +RenderableVolumeYt::RenderableVolumeYt(const ghoul::Dictionary& dictionary) + : Renderable(dictionary, { .automaticallyUpdateRenderBin = false }) + , _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown) + , _billboard(BillboardInfo, false) + , _mirrorBackside(MirrorBacksideInfo, false) + , _size(SizeInfo, glm::vec2(10.f), glm::vec2(0.f), glm::vec2(1e25f)) + , _autoScale(AutoScaleInfo, false) + , _multiplyColor(MultiplyColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) + , _spoutReceiver(*this, dictionary, "color") + , _spoutReceiver_depth(*this, dictionary, "depth") +{ + const Parameters p = codegen::bake(dictionary); + + addProperty(Fadeable::_opacity); + + if (std::holds_alternative(p.size)) { + _size = glm::vec2(std::get(p.size)); + } + else { + _size = std::get(p.size); + } + + _billboard = p.billboard.value_or(_billboard); + _mirrorBackside = p.mirrorBackside.value_or(_mirrorBackside); + + _blendMode.addOptions({ + { static_cast(BlendMode::Normal), "Normal" }, + { static_cast(BlendMode::Additive), "Additive"} + }); + _blendMode.onChange([this]() { + BlendMode m = static_cast(_blendMode.value()); + switch (m) { + case BlendMode::Normal: + setRenderBinFromOpacity(); + break; + case BlendMode::Additive: + setRenderBin(Renderable::RenderBin::PreDeferredTransparent); + break; + } + }); + + _opacity.onChange([this]() { + if (_blendMode == static_cast(BlendMode::Normal)) { + setRenderBinFromOpacity(); + } + }); + + if (p.blendMode.has_value()) { + _blendMode = codegen::map(*p.blendMode); + } + + _multiplyColor = p.multiplyColor.value_or(_multiplyColor); + _multiplyColor.setViewOption(properties::Property::ViewOptions::Color); + + addProperty(_billboard); + + _size.setExponent(15.f); + addProperty(_size); + _size.onChange([this](){ _planeIsDirty = true; }); + + addProperty(_autoScale); + + addProperty(_multiplyColor); + + setBoundingSphere(glm::compMax(_size.value())); +} + +bool RenderableVolumeYt::isReady() const { + return _shader != nullptr; +} + +void RenderableVolumeYt::initializeGL() { + ZoneScoped; + + glGenVertexArrays(1, &_quad); // generate array + glGenBuffers(1, &_vertexPositionBuffer); // generate buffer + createPlane(); + + _shader = BaseModule::ProgramObjectManager.request( + "Plane_yt", + []() -> std::unique_ptr { + return global::renderEngine->buildRenderProgram( + "Plane_yt", + absPath("${MODULE_BASE}/shaders/plane_vs.glsl"), + absPath("${MODULE_BASE}/shaders/plane_fs_yt.glsl") + ); + } + ); + + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); +} + +void RenderableVolumeYt::deinitializeGL() { + ZoneScoped; + + glDeleteVertexArrays(1, &_quad); + _quad = 0; + + glDeleteBuffers(1, &_vertexPositionBuffer); + _vertexPositionBuffer = 0; + + BaseModule::ProgramObjectManager.release( + "Plane_yt", + [](ghoul::opengl::ProgramObject* p) { + global::renderEngine->removeRenderProgram(p); + } + ); + _shader = nullptr; +} + +void RenderableVolumeYt::render(const RenderData& data, RendererTasks&) { + ZoneScoped; + + _shader->activate(); + _shader->setUniform(_uniformCache.opacity, opacity()); + + _shader->setUniform(_uniformCache.mirrorBackside, _mirrorBackside); + + glm::dvec3 objectPositionWorld = glm::dvec3( + glm::translate( + glm::dmat4(1.0), + data.modelTransform.translation) * glm::dvec4(0.0, 0.0, 0.0, 1.0) + ); + + glm::dvec3 normal = glm::normalize(data.camera.positionVec3() - objectPositionWorld); + glm::dvec3 newRight = glm::normalize( + glm::cross(data.camera.lookUpVectorWorldSpace(), normal) + ); + glm::dvec3 newUp = glm::cross(normal, newRight); + + glm::dmat4 cameraOrientedRotation = glm::dmat4(1.0); + cameraOrientedRotation[0] = glm::dvec4(newRight, 0.0); + cameraOrientedRotation[1] = glm::dvec4(newUp, 0.0); + cameraOrientedRotation[2] = glm::dvec4(normal, 0.0); + + const glm::dmat4 rotationTransform = _billboard ? + cameraOrientedRotation : + glm::dmat4(data.modelTransform.rotation); + + auto [modelTransform, modelViewTransform, modelViewProjectionTransform] = + calcAllTransforms(data, { .rotation = rotationTransform }); + + _shader->setUniform( + _uniformCache.modelViewProjection, + glm::mat4(modelViewProjectionTransform) + ); + _shader->setUniform(_uniformCache.modelViewTransform, glm::mat4(modelViewTransform)); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + //bindTexture(); // Binds the texture to OpenSpace + // Recive the color texture + if (_spoutReceiver.isReceiving()) { + _spoutReceiver.saveGLTextureState(); + glBindTexture(GL_TEXTURE_2D, static_cast(_spoutReceiver.spoutTexture())); + } + defer { unbindTexture(); }; + + _shader->setUniform(_uniformCache.colorTexture, unit); + + _shader->setUniform(_uniformCache.multiplyColor, _multiplyColor); + + ghoul::opengl::TextureUnit depth_unit; + depth_unit.activate(); + + // Recive the depth texture + if (_spoutReceiver_depth.isReceiving()) { + _spoutReceiver_depth.saveGLTextureState(); + glBindTexture(GL_TEXTURE_2D, static_cast(_spoutReceiver_depth.spoutTexture())); + } + defer{ unbindTexture(); }; + + _shader->setUniform("depthTexture", depth_unit); + + bool additiveBlending = (_blendMode == static_cast(BlendMode::Additive)); + if (additiveBlending) { + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } + glDisable(GL_CULL_FACE); + + glBindVertexArray(_quad); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); + + if (additiveBlending) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); + } + + _shader->deactivate(); +} + +void RenderableVolumeYt::bindTexture() { + // Function from the renderableplanespout.cpp file + if (_spoutReceiver.isReceiving()) { + _spoutReceiver.saveGLTextureState(); + glBindTexture(GL_TEXTURE_2D, static_cast(_spoutReceiver.spoutTexture())); + //cout << "`\nglBindTexture: Texture"; + /*_spoutReceiver.saveGLTextureState(); + glBindTexture(GL_TEXTURE_2D, static_cast(_spoutReceiver.spoutTexture()));*/ + //cout << "\nglBindTexture: Depth values"; + } + else { + //RenderableVolumeYt::bindTexture(); // Crashes with a stack overflow error + } +} + +void RenderableVolumeYt::unbindTexture() { + if (_spoutReceiver.isReceiving()) { + _spoutReceiver.restoreGLTextureState(); + } + else { + //RenderableVolumeYt::unbindTexture(); // Crashes with a stack overflow error + } +} + +void RenderableVolumeYt::update(const UpdateData&) { + ZoneScoped; + + if (_shader->isDirty()) { + _shader->rebuildFromFile(); + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + } + + if (_planeIsDirty) { + createPlane(); + } + + _spoutReceiver.updateReceiver(); // yt +} + +void RenderableVolumeYt::createPlane() { + const GLfloat sizeX = _size.value().x; + const GLfloat sizeY = _size.value().y; + const GLfloat vertexData[] = { + // x y z w s t + -sizeX, -sizeY, 0.f, 0.f, 0.f, 0.f, + sizeX, sizeY, 0.f, 0.f, 1.f, 1.f, + -sizeX, sizeY, 0.f, 0.f, 0.f, 1.f, + -sizeX, -sizeY, 0.f, 0.f, 0.f, 0.f, + sizeX, -sizeY, 0.f, 0.f, 1.f, 0.f, + sizeX, sizeY, 0.f, 0.f, 1.f, 1.f + }; + + glBindVertexArray(_quad); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, nullptr); + + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(GLfloat) * 6, + reinterpret_cast(sizeof(GLfloat) * 4) + ); + glBindVertexArray(0); +} + +} // namespace openspace diff --git a/modules/base/rendering/renderablevolumeyt.h b/modules/base/rendering/renderablevolumeyt.h new file mode 100644 index 0000000000..1f04135865 --- /dev/null +++ b/modules/base/rendering/renderablevolumeyt.h @@ -0,0 +1,108 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2024 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEVOLUMEYT___H__ +#define __OPENSPACE_MODULE_BASE___RENDERABLEVOLUMEYT___H__ + +#ifdef WIN32 + +#include +#include + +#include +#include +#include +#include +#include + +#include + +namespace ghoul::filesystem { class File; } + +namespace ghoul::opengl { + class ProgramObject; + class Texture; +} // namespace ghoul::opengl + +namespace openspace { + +struct RenderData; +struct UpdateData; + +namespace documentation { struct Documentation; } + +struct LinePoint; + +class RenderableVolumeYt : public Renderable { +public: + RenderableVolumeYt(const ghoul::Dictionary& dictionary); + + 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(); + +protected: + + virtual void bindTexture(); + virtual void unbindTexture(); + + void createPlane(); + + properties::OptionProperty _blendMode; + properties::BoolProperty _billboard; + properties::BoolProperty _mirrorBackside; + properties::Vec2Property _size; + properties::BoolProperty _autoScale; + properties::Vec3Property _multiplyColor; + + ghoul::opengl::ProgramObject* _shader = nullptr; + + GLuint _quad = 0; + GLuint _vertexPositionBuffer = 0; + +private: + bool _planeIsDirty = false; + + UniformCache(modelViewProjection, modelViewTransform, colorTexture, opacity, + mirrorBackside, multiplyColor) _uniformCache; + + // -------------------- yt ------------------ + + spout::SpoutReceiverPropertyProxy _spoutReceiver; // color texture + + spout::SpoutReceiverPropertyProxy _spoutReceiver_depth; // depth + // -------------------- end ------------------ +}; + +} // namespace openspace + +#endif // WIN32 + +#endif // __OPENSPACE_MODULE_BASE___RENDERABLEVOLUMEYT___H__ diff --git a/modules/base/shaders/plane_fs_yt.glsl b/modules/base/shaders/plane_fs_yt.glsl new file mode 100644 index 0000000000..fb1c4dab72 --- /dev/null +++ b/modules/base/shaders/plane_fs_yt.glsl @@ -0,0 +1,74 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2024 * + * * + * 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 "fragment.glsl" + +in vec4 vs_gPosition; +in vec3 vs_gNormal; +in float vs_screenSpaceDepth; +in vec2 vs_st; + +uniform sampler2D colorTexture; +uniform float opacity = 1.0; +uniform bool mirrorBackside = true; +uniform vec3 multiplyColor; + +uniform sampler2D depthTexture; + + +Fragment getFragment() { + Fragment frag; + if (gl_FrontFacing) { + frag.color = texture(colorTexture, vs_st); + } + else { + if (mirrorBackside) { + frag.color = texture(colorTexture, vec2(1.0 - vs_st.s, vs_st.t)); + } + else { + frag.color = texture(colorTexture, vs_st); + } + } + + frag.color.rgb *= multiplyColor; + + frag.color.a *= opacity; + if (frag.color.a == 0.0) { + discard; + } + + frag.depth = texture(depthTexture, vs_st).r; + if (frag.depth == 0.0) { + discard; + } + frag.depth = frag.depth; + + //frag.color += texture(depthTexture, vs_st); + + // G-Buffer + frag.gPosition = vs_gPosition; + frag.gNormal = vec4(vs_gNormal, 1.0); + + return frag; +} diff --git a/modules/server/CMakeLists.txt b/modules/server/CMakeLists.txt index 6b278b6984..9d8ed74bca 100644 --- a/modules/server/CMakeLists.txt +++ b/modules/server/CMakeLists.txt @@ -51,6 +51,7 @@ set(HEADER_FILES include/topics/topic.h include/topics/triggerpropertytopic.h include/topics/versiontopic.h + include/topics/camerainfotopic.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -80,6 +81,7 @@ set(SOURCE_FILES src/topics/topic.cpp src/topics/triggerpropertytopic.cpp src/topics/versiontopic.cpp + src/topics/camerainfotopic.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/server/include/topics/camerainfotopic.h b/modules/server/include/topics/camerainfotopic.h new file mode 100644 index 0000000000..7f6bf6af3e --- /dev/null +++ b/modules/server/include/topics/camerainfotopic.h @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2024 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_SERVER___CAMERAINFOTOPIC___H__ +#define __OPENSPACE_MODULE_SERVER___CAMERAINFOTOPIC___H__ + +#include +#include + +namespace openspace { + +class CameraInfoTopic : public Topic { +public: + CameraInfoTopic(); + ~CameraInfoTopic() override; + + void handleJson(const nlohmann::json& json) override; + bool isDone() const override; + +private: + static constexpr int UnsetOnChangeHandle = -1; + + void sendCameraData(); + + int _dataCallbackHandle = UnsetOnChangeHandle; + bool _isDone = false; + std::chrono::system_clock::time_point _lastUpdateTime; + glm::dvec3 _lastPosition = glm::dvec3(0); + + std::chrono::milliseconds _cameraPositionUpdateTime = std::chrono::milliseconds(100); +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_SERVER___CAMERAINFOTOPIC___H__ diff --git a/modules/server/src/connection.cpp b/modules/server/src/connection.cpp index 53026656fe..c8bf8e2e2a 100644 --- a/modules/server/src/connection.cpp +++ b/modules/server/src/connection.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -103,6 +104,7 @@ Connection::Connection(std::unique_ptr s, std::string address _topicFactory.registerClass("camera"); _topicFactory.registerClass("cameraPath"); _topicFactory.registerClass("event"); + _topicFactory.registerClass("cameraInfo"); } void Connection::handleMessage(const std::string& message) { diff --git a/modules/server/src/topics/camerainfotopic.cpp b/modules/server/src/topics/camerainfotopic.cpp new file mode 100644 index 0000000000..72d132f358 --- /dev/null +++ b/modules/server/src/topics/camerainfotopic.cpp @@ -0,0 +1,107 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2024 * + * * + * 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 + + +namespace { + constexpr std::string_view SubscribeEvent = "start_subscription"; +} // namespace + +using nlohmann::json; + +namespace openspace { + +CameraInfoTopic::CameraInfoTopic() + : _lastUpdateTime(std::chrono::system_clock::now()) +{} + +CameraInfoTopic::~CameraInfoTopic() { + if (_dataCallbackHandle != UnsetOnChangeHandle) { + ServerModule* module = global::moduleEngine->module(); + if (module) { + module->removePreSyncCallback(_dataCallbackHandle); + } + } +} + +bool CameraInfoTopic::isDone() const { + return _isDone; +} + +void CameraInfoTopic::handleJson(const nlohmann::json& json) { + std::string event = json.at("event").get(); + + if (event != SubscribeEvent) { + _isDone = true; + return; + } + + ServerModule* module = global::moduleEngine->module(); + _dataCallbackHandle = module->addPreSyncCallback( + [this]() { + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + if (now - _lastUpdateTime > _cameraPositionUpdateTime) { + sendCameraData(); + _lastUpdateTime = std::chrono::system_clock::now(); + } + } + ); +} + +void CameraInfoTopic::sendCameraData() { + glm::dmat4 camMat = global::navigationHandler->camera()->combinedViewMatrix(); + // Send the rotation information + // Angles for rotating + // Get the view matrix and update it in the yt code + // Either make the function in yt public or remake it so the code calls on it instead + + // Split the array to its primative values + // Turn them into a float? + + nlohmann::json jsonData = { + //{ "matrix_x", &camMat[0][1]}, + { "matrix_row0", camMat[0][0]}, + { "matrix_row1", camMat[1][0]}, + { "matrix_row2", camMat[2][0]}, + { "matrix_row3", camMat[3][0]} + + + }; + + _connection->sendJson(wrappedPayload(jsonData)); +} + +} // namespace openspace diff --git a/modules/spout/spoutwrapper.cpp b/modules/spout/spoutwrapper.cpp index 7e50f31359..81bbaaf7b0 100644 --- a/modules/spout/spoutwrapper.cpp +++ b/modules/spout/spoutwrapper.cpp @@ -339,10 +339,12 @@ const properties::Property::PropertyInfo& SpoutReceiverPropertyProxy::UpdateInfo } SpoutReceiverPropertyProxy::SpoutReceiverPropertyProxy(properties::PropertyOwner& owner, - const ghoul::Dictionary& dictionary) + const ghoul::Dictionary& dictionary, + std::string ownerIdentifier) : _spoutName(NameReceiverInfo) , _spoutSelection(SelectionInfo) , _updateSelection(UpdateInfo) + , _subowner({ ownerIdentifier, ownerIdentifier }) { if (dictionary.hasKey(NameReceiverInfo.identifier)) { _spoutName = dictionary.value(NameReceiverInfo.identifier); @@ -352,7 +354,7 @@ SpoutReceiverPropertyProxy::SpoutReceiverPropertyProxy(properties::PropertyOwner } _spoutName.onChange([this]() { _isSpoutDirty = true; }); - owner.addProperty(_spoutName); + _subowner.addProperty(_spoutName); _spoutSelection.onChange([this]() { if (_spoutName.value().empty() && _spoutSelection.value() == 0) { @@ -364,7 +366,7 @@ SpoutReceiverPropertyProxy::SpoutReceiverPropertyProxy(properties::PropertyOwner _spoutName = _spoutSelection.option().description; }); _spoutSelection.addOption(0, ""); - owner.addProperty(_spoutSelection); + _subowner.addProperty(_spoutSelection); _updateSelection.onChange([this]() { const std::vector receiverList = spoutReceiverList(); @@ -385,7 +387,8 @@ SpoutReceiverPropertyProxy::SpoutReceiverPropertyProxy(properties::PropertyOwner _spoutSelection = idx; }); - owner.addProperty(_updateSelection); + _subowner.addProperty(_updateSelection); + owner.addPropertySubOwner(_subowner); _updateSelection.trigger(); } diff --git a/modules/spout/spoutwrapper.h b/modules/spout/spoutwrapper.h index 8753a60ed4..5414d92624 100644 --- a/modules/spout/spoutwrapper.h +++ b/modules/spout/spoutwrapper.h @@ -117,13 +117,15 @@ public: static const properties::Property::PropertyInfo& UpdateInfoProperty(); SpoutReceiverPropertyProxy(properties::PropertyOwner& owner, - const ghoul::Dictionary& dictionary); + const ghoul::Dictionary& dictionary, std::string ownerIdentifier = "Spout"); virtual ~SpoutReceiverPropertyProxy(); bool updateReceiver() override; void releaseReceiver() override; private: + properties::PropertyOwner _subowner; + properties::StringProperty _spoutName; properties::OptionProperty _spoutSelection; properties::TriggerProperty _updateSelection;