Issue/518 (#529)

* Adding ScreenSpaceSpout object to display spout textures in screen space
 * Enable the clearing of option properties
 * Fix crash in ScreenSpaceImageLocal specification
 * Split RenderablePlane into RenderablePlaneImageLocal and RenderablePlaneImageOnline
 * Add RenderablePlane Spout
 * Rename Texture parameter in ScreenSpaceImageOnline into URL

Closes #518
This commit is contained in:
Alexander Bock
2018-02-23 13:24:35 -05:00
committed by GitHub
parent 9ad1d7e3ed
commit 58f79a8851
46 changed files with 1430 additions and 142 deletions
+4
View File
@@ -37,6 +37,8 @@ set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneimagelocal.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneimageonline.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphere.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphericalgrid.h
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrail.h
@@ -69,6 +71,8 @@ set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplane.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneimagelocal.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneimageonline.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphere.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablesphericalgrid.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabletrail.cpp
+4 -2
View File
@@ -45,7 +45,8 @@
#include <modules/base/rendering/renderablesphericalgrid.h>
#include <modules/base/rendering/renderabletrailorbit.h>
#include <modules/base/rendering/renderabletrailtrajectory.h>
#include <modules/base/rendering/renderableplane.h>
#include <modules/base/rendering/renderableplaneimagelocal.h>
#include <modules/base/rendering/renderableplaneimageonline.h>
#include <modules/base/rendering/modelgeometry.h>
#include <modules/base/rendering/multimodelgeometry.h>
#include <modules/base/rendering/screenspacedashboard.h>
@@ -107,7 +108,8 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
ghoul_assert(fRenderable, "Renderable factory was not created");
fRenderable->registerClass<RenderableModel>("RenderableModel");
fRenderable->registerClass<RenderablePlane>("RenderablePlane");
fRenderable->registerClass<RenderablePlaneImageLocal>("RenderablePlaneImageLocal");
fRenderable->registerClass<RenderablePlaneImageOnline>("RenderablePlaneImageOnline");
fRenderable->registerClass<RenderableSphere>("RenderableSphere");
fRenderable->registerClass<RenderableSphericalGrid>("RenderableSphericalGrid");
fRenderable->registerClass<RenderableTrailOrbit>("RenderableTrailOrbit");
+15 -78
View File
@@ -33,6 +33,7 @@
#include <ghoul/filesystem/filesystem>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/misc/defer.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
@@ -43,13 +44,6 @@ namespace {
BlendModeAdditive
};
static const openspace::properties::Property::PropertyInfo TextureInfo = {
"Texture",
"Texture",
"This value specifies an image that is loaded from disk and is used as a texture "
"that is applied to this plane. This image has to be square."
};
static const openspace::properties::Property::PropertyInfo BillboardInfo = {
"Billboard",
"Billboard mode",
@@ -96,12 +90,6 @@ documentation::Documentation RenderablePlane::Documentation() {
new StringInListVerifier({ "Normal", "Additive" }),
Optional::Yes,
BlendModeInfo.description, // + " The default value is 'Normal'.",
},
{
TextureInfo.identifier,
new StringVerifier,
Optional::No,
TextureInfo.description,
}
}
};
@@ -109,16 +97,13 @@ documentation::Documentation RenderablePlane::Documentation() {
RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
: Renderable(dictionary)
, _texturePath(TextureInfo)
, _billboard(BillboardInfo, false)
, _size(SizeInfo, 10.f, 0.f, 1e25f)
, _blendMode(BlendModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _shader(nullptr)
, _texture(nullptr)
, _quad(0)
, _vertexPositionBuffer(0)
, _planeIsDirty(false)
, _textureIsDirty(false)
{
documentation::testSpecificationAndThrow(
Documentation(),
@@ -158,15 +143,8 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
_blendMode = BlendModeAdditive;
}
}
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
addProperty(_billboard);
addProperty(_texturePath);
_texturePath.onChange([this]() {loadTexture(); });
_textureFile->setCallback(
[this](const ghoul::filesystem::File&) { _textureIsDirty = true; }
);
addProperty(_size);
_size.onChange([this](){ _planeIsDirty = true; });
@@ -175,7 +153,7 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary)
}
bool RenderablePlane::isReady() const {
return _shader && _texture;
return _shader != nullptr;
}
void RenderablePlane::initializeGL() {
@@ -188,8 +166,6 @@ void RenderablePlane::initializeGL() {
absPath("${MODULE_BASE}/shaders/plane_vs.glsl"),
absPath("${MODULE_BASE}/shaders/plane_fs.glsl")
);
loadTexture();
}
void RenderablePlane::deinitializeGL() {
@@ -199,8 +175,6 @@ void RenderablePlane::deinitializeGL() {
glDeleteBuffers(1, &_vertexPositionBuffer);
_vertexPositionBuffer = 0;
_textureFile = nullptr;
RenderEngine& renderEngine = OsEng.renderEngine();
if (_shader) {
renderEngine.removeRenderProgram(_shader);
@@ -210,22 +184,6 @@ void RenderablePlane::deinitializeGL() {
void RenderablePlane::render(const RenderData& data, RendererTasks&) {
_shader->activate();
//if (_projectionListener){
// //get parent node-texture and set with correct dimensions
// SceneGraphNode* textureNode = OsEng.renderEngine().scene()->sceneGraphNode(
// _nodeName
// )->parent();
// if (textureNode != nullptr){
// RenderablePlanetProjection* t = static_cast<RenderablePlanetProjection*>(
// textureNode->renderable()
// );
// _texture = std::unique_ptr<ghoul::opengl::Texture>(&(t->baseTexture()));
// unsigned int h = _texture->height();
// unsigned int w = _texture->width();
// float scale = static_cast<float>(h) / static_cast<float>(w);
// scaleTransform = glm::scale(glm::mat4(1.0), glm::vec3(1.f, scale, 1.f));
// }
//}
// Model transform and view transform needs to be in double precision
const glm::dmat4 rotationTransform = _billboard ?
@@ -248,7 +206,9 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) {
ghoul::opengl::TextureUnit unit;
unit.activate();
_texture->bind();
bindTexture();
defer { unbindTexture(); };
_shader->setUniform("texture1", unit);
bool usingFramebufferRenderer =
@@ -280,42 +240,19 @@ void RenderablePlane::render(const RenderData& data, RendererTasks&) {
_shader->deactivate();
}
void RenderablePlane::update(const UpdateData&) {
if (_shader->isDirty())
_shader->rebuildFromFile();
void RenderablePlane::bindTexture() {}
if (_planeIsDirty)
void RenderablePlane::unbindTexture() {}
void RenderablePlane::update(const UpdateData&) {
if (_shader->isDirty()) {
_shader->rebuildFromFile();
}
if (_planeIsDirty) {
createPlane();
if (_textureIsDirty) {
loadTexture();
_textureIsDirty = false;
}
}
void RenderablePlane::loadTexture() {
if (_texturePath.value() != "") {
std::unique_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath));
if (texture) {
LDEBUGC(
"RenderablePlane",
"Loaded texture from '" << absPath(_texturePath) << "'"
);
texture->uploadTexture();
// Textures of planets looks much smoother with AnisotropicMipMap rather than
// linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_texture = std::move(texture);
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
_textureFile->setCallback(
[&](const ghoul::filesystem::File&) { _textureIsDirty = true; }
);
}
}
}
+6 -9
View File
@@ -33,13 +33,11 @@
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/opengl/programobject.h>
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl {
class ProgramObject;
class Texture;
} // namespace ghoul::opengl
namespace ghoul::opengl { class Texture; }
namespace openspace {
@@ -64,24 +62,23 @@ public:
static documentation::Documentation Documentation();
protected:
virtual void bindTexture();
virtual void unbindTexture();
private:
void loadTexture();
void createPlane();
properties::StringProperty _texturePath;
properties::BoolProperty _billboard;
properties::FloatProperty _size;
properties::OptionProperty _blendMode;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader;
std::unique_ptr<ghoul::opengl::Texture> _texture;
std::unique_ptr<ghoul::filesystem::File> _textureFile;
GLuint _quad;
GLuint _vertexPositionBuffer;
bool _planeIsDirty;
bool _textureIsDirty;
};
} // namespace openspace
@@ -0,0 +1,139 @@
/*****************************************************************************************
* *
* 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 <modules/base/rendering/renderableplaneimagelocal.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/texture.h>
namespace {
static const openspace::properties::Property::PropertyInfo TextureInfo = {
"Texture",
"Texture",
"This value specifies an image that is loaded from disk and is used as a texture "
"that is applied to this plane. This image has to be square."
};
} // namespace
namespace openspace {
documentation::Documentation RenderablePlaneImageLocal::Documentation() {
using namespace documentation;
return {
"Renderable Plane Image Local",
"base_renderable_plane_image_local",
{
{
TextureInfo.identifier,
new StringVerifier,
Optional::No,
TextureInfo.description,
}
}
};
}
RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& dictionary)
: RenderablePlane(dictionary)
, _texturePath(TextureInfo)
, _texture(nullptr)
, _textureIsDirty(false)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderablePlaneImageLocal"
);
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
addProperty(_texturePath);
_texturePath.onChange([this]() {loadTexture(); });
_textureFile->setCallback(
[this](const ghoul::filesystem::File&) { _textureIsDirty = true; }
);
}
bool RenderablePlaneImageLocal::isReady() const {
return RenderablePlane::isReady() && _texture != nullptr;
}
void RenderablePlaneImageLocal::initializeGL() {
RenderablePlane::initializeGL();
loadTexture();
}
void RenderablePlaneImageLocal::deinitializeGL() {
_textureFile = nullptr;
_texture = nullptr;
RenderablePlane::deinitializeGL();
}
void RenderablePlaneImageLocal::bindTexture() {
_texture->bind();
}
void RenderablePlaneImageLocal::update(const UpdateData& data) {
RenderablePlane::update(data);
if (_textureIsDirty) {
loadTexture();
_textureIsDirty = false;
}
}
void RenderablePlaneImageLocal::loadTexture() {
if (!_texturePath.value().empty()) {
std::unique_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath));
if (texture) {
LDEBUGC(
"RenderablePlane",
"Loaded texture from '" << absPath(_texturePath) << "'"
);
texture->uploadTexture();
// Textures of planets looks much smoother with AnisotropicMipMap rather than
// linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_texture = std::move(texture);
_textureFile = std::make_unique<ghoul::filesystem::File>(_texturePath);
_textureFile->setCallback(
[&](const ghoul::filesystem::File&) { _textureIsDirty = true; }
);
}
}
}
} // namespace openspace
@@ -0,0 +1,68 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGELOCAL___H__
#define __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGELOCAL___H__
#include <modules/base/rendering/renderableplane.h>
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl { class Texture; }
namespace openspace {
struct RenderData;
struct UpdateData;
namespace documentation { struct Documentation; }
class RenderablePlaneImageLocal : public RenderablePlane {
public:
RenderablePlaneImageLocal(const ghoul::Dictionary& dictionary);
void initializeGL() override;
void deinitializeGL() override;
bool isReady() const override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
protected:
virtual void bindTexture();
private:
void loadTexture();
properties::StringProperty _texturePath;
std::unique_ptr<ghoul::opengl::Texture> _texture;
std::unique_ptr<ghoul::filesystem::File> _textureFile;
bool _textureIsDirty;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGELOCAL___H__
@@ -0,0 +1,170 @@
/*****************************************************************************************
* *
* 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 <modules/base/rendering/renderableplaneimageonline.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/openspaceengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/opengl/texture.h>
#include <ghoul/opengl/textureunit.h>
namespace {
static const openspace::properties::Property::PropertyInfo TextureInfo = {
"URL",
"Image URL",
"Sets the URL of the texture that is displayed on this screen space plane. If "
"this value is changed, the image at the new path will automatically be loaded "
"and displayed."
};
} // namespace
namespace openspace {
documentation::Documentation RenderablePlaneImageOnline::Documentation() {
using namespace documentation;
return {
"Renderable Plane Image Online",
"base_renderable_plane_image_online",
{
{
TextureInfo.identifier,
new StringVerifier,
Optional::No,
TextureInfo.description,
}
}
};
}
RenderablePlaneImageOnline::RenderablePlaneImageOnline(const ghoul::Dictionary& dictionary)
: RenderablePlane(dictionary)
, _texturePath(TextureInfo)
, _texture(nullptr)
, _textureIsDirty(false)
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderablePlaneImageOnline"
);
_texturePath.onChange([this]() { _textureIsDirty = true; });
addProperty(_texturePath);
std::string texturePath;
if (dictionary.hasKey(TextureInfo.identifier)) {
_texturePath = dictionary.value<std::string>(TextureInfo.identifier);
}
addProperty(_texturePath);
}
void RenderablePlaneImageOnline::deinitializeGL() {
_texture = nullptr;
RenderablePlane::deinitializeGL();
}
void RenderablePlaneImageOnline::bindTexture() {
if (_texture) {
_texture->bind();
}
else {
glBindTexture(GL_TEXTURE_2D, 0);
}
}
void RenderablePlaneImageOnline::update(const UpdateData&) {
if (_textureIsDirty) {
if (!_imageFuture.valid()) {
std::future<DownloadManager::MemoryFile> future = downloadImageToMemory(
_texturePath
);
if (future.valid()) {
_imageFuture = std::move(future);
}
}
if (_imageFuture.valid() && DownloadManager::futureReady(_imageFuture)) {
DownloadManager::MemoryFile imageFile = _imageFuture.get();
if (imageFile.corrupted) {
LERRORC(
"ScreenSpaceImageOnline",
"Error loading image from URL '" << _texturePath << "'"
);
return;
}
std::unique_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(
reinterpret_cast<void*>(imageFile.buffer),
imageFile.size,
imageFile.format
);
if (texture) {
// Images don't need to start on 4-byte boundaries, for example if the
// image is only RGB
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
texture->uploadTexture();
// Textures of planets looks much smoother with AnisotropicMipMap rather
// than linear
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_texture = std::move(texture);
_textureIsDirty = false;
}
}
}
}
std::future<DownloadManager::MemoryFile>
RenderablePlaneImageOnline::downloadImageToMemory(std::string url)
{
return OsEng.downloadManager().fetchFile(
url,
[url](const DownloadManager::MemoryFile&) {
LDEBUGC(
"ScreenSpaceImageOnline",
"Download to memory finished for screen space image"
);
},
[url](const std::string& err) {
LDEBUGC(
"ScreenSpaceImageOnline",
"Download to memory failer for screen space image: " + err
);
}
);
}
} // namespace openspace
@@ -0,0 +1,72 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGEONLINE___H__
#define __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGEONLINE___H__
#include <modules/base/rendering/renderableplane.h>
#include <openspace/engine/downloadmanager.h>
namespace ghoul::filesystem { class File; }
namespace ghoul::opengl { class Texture; }
namespace openspace {
struct RenderData;
struct UpdateData;
namespace documentation { struct Documentation; }
class RenderablePlaneImageOnline : public RenderablePlane {
public:
RenderablePlaneImageOnline(const ghoul::Dictionary& dictionary);
void deinitializeGL() override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
protected:
virtual void bindTexture();
private:
std::future<DownloadManager::MemoryFile> downloadImageToMemory(std::string url);
properties::StringProperty _texturePath;
std::future<DownloadManager::MemoryFile> _imageFuture;
std::unique_ptr<ghoul::opengl::Texture> _texture;
bool _textureIsDirty;
bool _downloadImage;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___RENDERABLEPLANEIMAGEONLINE___H__
@@ -182,6 +182,8 @@ void ScreenSpaceFramebuffer::createFramebuffer() {
_originalViewportSize.y,
1
));
_objectSize = glm::ivec2(_originalViewportSize);
_texture->uploadTexture();
_texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_framebuffer->attachTexture(_texture.get(), GL_COLOR_ATTACHMENT0);
@@ -193,4 +195,8 @@ int ScreenSpaceFramebuffer::id() {
return id++;
}
void ScreenSpaceFramebuffer::bindTexture() {
_texture->bind();
}
} //namespace openspace
@@ -65,12 +65,16 @@ protected:
properties::Vec4Property _size;
private:
void bindTexture() override;
static int id();
std::unique_ptr<ghoul::opengl::FramebufferObject> _framebuffer;
std::vector<std::shared_ptr<std::function<void()>>> _renderFunctionsShared;
std::vector<std::function<void()>> _renderFunctions;
std::unique_ptr<ghoul::opengl::Texture> _texture;
int _id;
};
@@ -123,10 +123,15 @@ void ScreenSpaceImageLocal::update() {
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_texture = std::move(texture);
_objectSize = _texture->dimensions();
_textureIsDirty = false;
}
}
}
void ScreenSpaceImageLocal::bindTexture() {
_texture->bind();
}
} // namespace openspace
@@ -44,7 +44,11 @@ public:
static documentation::Documentation Documentation();
private:
void bindTexture() override;
properties::StringProperty _texturePath;
std::unique_ptr<ghoul::opengl::Texture> _texture;
bool _textureIsDirty;
};
@@ -36,12 +36,11 @@
#include <ghoul/filesystem/filesystem>
namespace {
const char* KeyName = "Name";
const char* KeyTexturePath = "TexturePath";
constexpr const char* KeyName = "Name";
static const openspace::properties::Property::PropertyInfo TexturePathInfo = {
"TexturePath",
"Texture path",
static const openspace::properties::Property::PropertyInfo TextureInfo = {
"URL",
"Image URL",
"Sets the URL of the texture that is displayed on this screen space plane. If "
"this value is changed, the image at the new path will automatically be loaded "
"and displayed. The size of the image will also automatically set the default "
@@ -64,10 +63,10 @@ documentation::Documentation ScreenSpaceImageOnline::Documentation() {
"Specifies the GUI name of the ScreenspaceImage"
},
{
KeyTexturePath,
TextureInfo.identifier,
new StringVerifier,
Optional::Yes,
TexturePathInfo.description
TextureInfo.description
}
}
};
@@ -76,7 +75,7 @@ documentation::Documentation ScreenSpaceImageOnline::Documentation() {
ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _textureIsDirty(false)
, _texturePath(TexturePathInfo)
, _texturePath(TextureInfo)
{
documentation::testSpecificationAndThrow(
Documentation(),
@@ -102,8 +101,8 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona
addProperty(_texturePath);
std::string texturePath;
if (dictionary.hasKey(TexturePathInfo.identifier)) {
_texturePath = dictionary.value<std::string>(TexturePathInfo.identifier);
if (dictionary.hasKey(TextureInfo.identifier)) {
_texturePath = dictionary.value<std::string>(TextureInfo.identifier);
}
}
@@ -149,6 +148,7 @@ void ScreenSpaceImageOnline::update() {
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
_texture = std::move(texture);
_objectSize = _texture->dimensions();
_textureIsDirty = false;
}
}
@@ -175,4 +175,13 @@ std::future<DownloadManager::MemoryFile> ScreenSpaceImageOnline::downloadImageTo
);
}
void ScreenSpaceImageOnline::bindTexture() {
if (_texture) {
_texture->bind();
}
else {
glBindTexture(GL_TEXTURE_2D, 0);
}
}
} // namespace openspace
@@ -51,7 +51,11 @@ protected:
properties::StringProperty _texturePath;
private:
void bindTexture() override;
std::future<DownloadManager::MemoryFile> downloadImageToMemory(std::string url);
std::unique_ptr<ghoul::opengl::Texture> _texture;
};
} // namespace openspace
+2 -2
View File
@@ -221,7 +221,7 @@ static void RenderDrawLists(ImDrawData* drawData) {
void addScreenSpaceRenderableLocal(std::string texturePath) {
if (!FileSys.fileExists(texturePath)) {
if (!FileSys.fileExists(absPath(texturePath))) {
LWARNING("Could not find image '" << texturePath << "'");
return;
}
@@ -239,7 +239,7 @@ void addScreenSpaceRenderableLocal(std::string texturePath) {
void addScreenSpaceRenderableOnline(std::string texturePath) {
const std::string luaTable =
"{Type = 'ScreenSpaceImageOnline', TexturePath = '" + texturePath + "' }";
"{Type = 'ScreenSpaceImageOnline', URL = '" + texturePath + "' }";
const std::string script = "openspace.addScreenSpaceRenderable(" +
luaTable + ");";
OsEng.scriptEngine().queueScript(
+51
View File
@@ -0,0 +1,51 @@
##########################################################################################
# #
# 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(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/renderableplanespout.h
${CMAKE_CURRENT_SOURCE_DIR}/screenspacespout.h
${CMAKE_CURRENT_SOURCE_DIR}/spoutlibrary.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/renderableplanespout.cpp
${CMAKE_CURRENT_SOURCE_DIR}/screenspacespout.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})
create_new_module(
"Spout"
spout_module
STATIC
${HEADER_FILES} ${SOURCE_FILES}
)
target_include_directories(openspace-module-spout SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ext/spout)
target_link_libraries(openspace-module-spout ${CMAKE_CURRENT_SOURCE_DIR}/ext/spout/SpoutLibrary.lib)
register_external_libraries("${CMAKE_CURRENT_SOURCE_DIR}/ext/spout/SpoutLibrary.dll")
target_compile_definitions(openspace-module-spout PUBLIC "OPENSPACE_HAS_SPOUT")
+8
View File
@@ -0,0 +1,8 @@
The spout folder is a copy of the folder:
SpoutSDK/Source in the repository:
https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Binaries
and
https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Include
Last update:
https://github.com/leadedge/Spout2/commit/28dbea6059cd7968c4d2b296d6739a5fdebe9104
Binary file not shown.
+90
View File
@@ -0,0 +1,90 @@
//
// SpoutLibrary.dll
//
// Spout SDK dll compatible with any C++ compiler
//
#include <windows.h>
#include <GL/GL.h>
#define SPOUTLIBRARY_EXPORTS // defined for this DLL. The application imports rather than exports
#ifdef SPOUTLIBRARY_EXPORTS
#define SPOUTAPI __declspec(dllexport)
#else
#define SPOUTAPI __declspec(dllimport)
#endif
////////////////////////////////////////////////////////////////////////////////
//
// COM-Like abstract interface.
// This interface doesn't require __declspec(dllexport/dllimport) specifier.
// Method calls are dispatched via virtual table.
// Any C++ compiler can use it.
// Instances are obtained via factory function.
//
struct SPOUTLIBRARY
{
// Sender
virtual bool CreateSender(const char *Sendername, unsigned int width, unsigned int height, DWORD dwFormat = 0) = 0;
virtual void ReleaseSender(DWORD dwMsec = 0) = 0;
virtual bool UpdateSender(const char* Sendername, unsigned int width, unsigned int height) = 0;
virtual bool SendTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, bool bInvert = true, GLuint HostFBO = 0) = 0;
virtual bool SendImage(const unsigned char* pixels, unsigned int width, unsigned int height, GLenum glFormat = GL_RGBA, bool bInvert=false) = 0;
// Receiver
virtual bool CreateReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool bUseActive = false) = 0;
virtual void ReleaseReceiver() = 0;
virtual bool ReceiveTexture(char* Sendername, unsigned int &width, unsigned int &height, GLuint TextureID = 0, GLuint TextureTarget = 0, bool bInvert = false, GLuint HostFBO = 0) = 0;
virtual bool ReceiveImage(char* Sendername, unsigned int &width, unsigned int &height, unsigned char* pixels, GLenum glFormat = GL_RGBA, bool bInvert = false, GLuint HostFBO=0) = 0;
virtual bool CheckReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool &bConnected) = 0;
virtual bool GetImageSize(char* sendername, unsigned int &width, unsigned int &height, bool &bMemoryMode) = 0;
virtual bool BindSharedTexture() = 0;
virtual bool UnBindSharedTexture() = 0;
virtual bool DrawSharedTexture(float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = true) = 0;
virtual bool DrawToSharedTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = false, GLuint HostFBO = 0) = 0;
virtual int GetSenderCount() = 0;
virtual bool GetSenderName(int index, char* sendername, int MaxSize = 256) = 0;
virtual bool GetSenderInfo(const char* sendername, unsigned int &width, unsigned int &height, HANDLE &dxShareHandle, DWORD &dwFormat) = 0;
virtual bool GetActiveSender(char* Sendername) = 0;
virtual bool SetActiveSender(const char* Sendername) = 0;
// Utilities
virtual bool SetDX9(bool bDX9 = true) = 0; // User request to use DirectX 9 (default is DirectX 11)
virtual bool GetDX9() = 0; // Return the flag that has been set
virtual bool SetMemoryShareMode(bool bMem = true) = 0;
virtual bool GetMemoryShareMode() = 0;
virtual int GetMaxSenders() = 0; // Get maximum senders allowed
virtual void SetMaxSenders(int maxSenders) = 0; // Set maximum senders allowed
virtual bool GetHostPath(const char *sendername, char *hostpath, int maxchars) = 0; // The path of the host that produced the sender
virtual int GetVerticalSync() = 0;
virtual bool SetVerticalSync(bool bSync = true) = 0;
virtual bool SelectSenderPanel(const char* message = NULL) = 0;
// Access to globals
virtual bool GetSpoutSenderName(char * sendername, int maxchars) = 0; // get the global sender name
virtual bool IsSpoutInitialized() = 0; // has the class been initialized
// Adapter functions
virtual int GetNumAdapters() = 0; // Get the number of graphics adapters in the system
virtual bool GetAdapterName(int index, char *adaptername, int maxchars) = 0; // Get an adapter name
virtual bool SetAdapter(int index = 0) = 0; // Set required graphics adapter for output
virtual int GetAdapter() = 0; // Get the SpoutDirectX global adapter index
// Library release function
virtual void Release() = 0;
};
// Handle type. In C++ language the interface type is used.
typedef SPOUTLIBRARY* SPOUTHANDLE;
// Factory function that creates instances of the SPOUT object.
extern "C" SPOUTAPI SPOUTHANDLE WINAPI GetSpout(VOID);
////////////////////////////////////////////////////////////////////////////////
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
set (OPENSPACE_DEPENDENCIES
base
)
+243
View File
@@ -0,0 +1,243 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifdef WIN32
#include <modules/spout/renderableplanespout.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/filesystem/filesystem>
#include <ghoul/misc/defer.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/texture.h>
namespace {
const char* KeyName = "Name";
static const openspace::properties::Property::PropertyInfo NameInfo = {
"SpoutName",
"Spout Sender Name",
"This value explicitly sets the Spout receiver to use a specific name. If this "
"is not a valid name, an empty image is used."
};
static const openspace::properties::Property::PropertyInfo SelectionInfo = {
"SpoutSelection",
"Spout Selection",
"This property displays all available Spout sender on the system. If one them is "
"selected, its value is stored in the 'SpoutName' property, overwriting its "
"previous value."
};
static const openspace::properties::Property::PropertyInfo UpdateInfo = {
"UpdateSelection",
"Update Selection",
"If this property is trigged, the 'SpoutSelection' options will be refreshed."
};
} // namespace
namespace openspace {
documentation::Documentation RenderablePlaneSpout::Documentation() {
using namespace openspace::documentation;
return {
"ScreenSpace Spout",
"spout_screenspace_spout",
{
{
KeyName,
new StringVerifier,
Optional::Yes,
"Specifies the GUI name of the ScreenspaceSpout"
},
{
NameInfo.identifier,
new StringVerifier,
Optional::Yes,
NameInfo.description
}
}
};
}
RenderablePlaneSpout::RenderablePlaneSpout(const ghoul::Dictionary& dictionary)
: RenderablePlane(dictionary)
, _spoutName(NameInfo)
, _spoutSelection(SelectionInfo)
, _updateSelection(UpdateInfo)
, _receiver(GetSpout())
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"RenderablePlaneSpout"
);
if (dictionary.hasKey(KeyName)) {
setName(dictionary.value<std::string>(KeyName));
}
else {
static int id = 0;
if (id == 0) {
setName("ScreenSpaceSpout");
}
else {
setName("ScreenSpaceSpout " + std::to_string(id));
}
++id;
}
_isSpoutDirty = true;
if (dictionary.hasKey(NameInfo.identifier)) {
_spoutName = dictionary.value<std::string>(NameInfo.identifier);
_isSpoutDirty = true;
}
_spoutName.onChange([this]() {
_isSpoutDirty = true;
_isErrorMessageDisplayed = false;
_receiver->SetActiveSender(_spoutName.value().c_str());
});
addProperty(_spoutName);
_spoutSelection.onChange([this](){
_spoutName = _spoutSelection.option().description;
});
_spoutSelection.addOption(0, "");
addProperty(_spoutSelection);
_updateSelection.onChange([this]() {
std::string currentValue = _spoutSelection.options().empty() ?
"" :
_spoutSelection.option().description;
_spoutSelection.clearOptions();
_spoutSelection.addOption(0, "");
int nSenders = _receiver->GetSenderCount();
int idx = 0;
for (int i = 0; i < nSenders; ++i) {
char Name[256];
_receiver->GetSenderName(i, Name, 256);
_spoutSelection.addOption(i + 1, Name);
if (currentValue == Name) {
idx = i + 1;
}
}
_spoutSelection = idx;
});
addProperty(_updateSelection);
}
void RenderablePlaneSpout::deinitializeGL() {
_receiver->ReleaseReceiver();
_receiver->Release();
RenderablePlane::deinitializeGL();
}
void RenderablePlaneSpout::update(const UpdateData& data) {
RenderablePlane::update(data);
if (_isFirstUpdate) {
defer { _isFirstUpdate = false; };
// Trigger an update; the value is a dummy that is ignored
_updateSelection.set(0);
// #0 is the empty string and we just pick the first one after that (if it exists)
if (_spoutSelection.options().size() > 1) {
_spoutSelection = 1;
}
}
if (_spoutName.value().empty()) {
return;
}
if (_isSpoutDirty) {
defer { _isSpoutDirty = false; };
std::memset(_currentSenderName, 0, 256);
unsigned int width;
unsigned int height;
_receiver->ReleaseReceiver();
_receiver->GetActiveSender(_currentSenderName);
bool createSuccess = _receiver->CreateReceiver(
_currentSenderName,
width,
height
);
if (!createSuccess) {
LWARNINGC(
"ScreenSpaceSpout",
"Could not create receiver for " << _currentSenderName
);
return;
}
}
unsigned int width;
unsigned int height;
bool receiveSuccess = _receiver->ReceiveTexture(
_currentSenderName,
width,
height
);
if (!receiveSuccess && !_isErrorMessageDisplayed) {
LWARNINGC(
"ScreenSpaceSpout",
"Could not receive texture for " << _currentSenderName
);
_isErrorMessageDisplayed = true;
}
}
void RenderablePlaneSpout::bindTexture() {
_receiver->BindSharedTexture();
}
void RenderablePlaneSpout::unbindTexture() {
_receiver->UnBindSharedTexture();
}
} // namespace openspace
#endif // WIN32
+74
View File
@@ -0,0 +1,74 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_SPOUT___RENDERABLEPLANESPOUT___H__
#define __OPENSPACE_MODULE_SPOUT___RENDERABLEPLANESPOUT___H__
#ifdef WIN32
#include <modules/base/rendering/renderableplane.h>
#include <modules/spout/spoutlibrary.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/triggerproperty.h>
namespace openspace {
namespace documentation { struct Documentation; }
class RenderablePlaneSpout : public RenderablePlane {
public:
RenderablePlaneSpout(const ghoul::Dictionary& dictionary);
void deinitializeGL() override;
void update(const UpdateData& data) override;
static documentation::Documentation Documentation();
private:
void bindTexture() override;
void unbindTexture() override;
properties::StringProperty _spoutName;
properties::OptionProperty _spoutSelection;
properties::TriggerProperty _updateSelection;
SPOUTHANDLE _receiver;
bool _isSpoutDirty = false;
char _currentSenderName[256];
bool _isFirstUpdate = true;
bool _isErrorMessageDisplayed = false;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SPOUT___RENDERABLEPLANESPOUT___H__
#endif // WIN32
+244
View File
@@ -0,0 +1,244 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifdef WIN32
#include <modules/spout/screenspacespout.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <ghoul/misc/defer.h>
namespace {
const char* KeyName = "Name";
static const openspace::properties::Property::PropertyInfo NameInfo = {
"SpoutName",
"Spout Sender Name",
"This value explicitly sets the Spout receiver to use a specific name. If this "
"is not a valid name, an empty image is used."
};
static const openspace::properties::Property::PropertyInfo SelectionInfo = {
"SpoutSelection",
"Spout Selection",
"This property displays all available Spout sender on the system. If one them is "
"selected, its value is stored in the 'SpoutName' property, overwriting its "
"previous value."
};
static const openspace::properties::Property::PropertyInfo UpdateInfo = {
"UpdateSelection",
"Update Selection",
"If this property is trigged, the 'SpoutSelection' options will be refreshed."
};
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceSpout::Documentation() {
using namespace openspace::documentation;
return {
"ScreenSpace Spout",
"spout_screenspace_spout",
{
{
KeyName,
new StringVerifier,
Optional::Yes,
"Specifies the GUI name of the ScreenspaceSpout"
},
{
NameInfo.identifier,
new StringVerifier,
Optional::Yes,
NameInfo.description
}
}
};
}
ScreenSpaceSpout::ScreenSpaceSpout(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _spoutName(NameInfo)
, _spoutSelection(SelectionInfo)
, _updateSelection(UpdateInfo)
, _receiver(GetSpout())
{
documentation::testSpecificationAndThrow(
Documentation(),
dictionary,
"ScreenSpaceSpout"
);
if (dictionary.hasKey(KeyName)) {
setName(dictionary.value<std::string>(KeyName));
}
else {
static int id = 0;
if (id == 0) {
setName("ScreenSpaceSpout");
}
else {
setName("ScreenSpaceSpout " + std::to_string(id));
}
++id;
}
_isSpoutDirty = true;
if (dictionary.hasKey(NameInfo.identifier)) {
_spoutName = dictionary.value<std::string>(NameInfo.identifier);
_isSpoutDirty = true;
}
_spoutName.onChange([this]() {
_isSpoutDirty = true;
_isErrorMessageDisplayed = false;
_receiver->SetActiveSender(_spoutName.value().c_str());
});
addProperty(_spoutName);
_spoutSelection.onChange([this](){
_spoutName = _spoutSelection.option().description;
});
_spoutSelection.addOption(0, "");
addProperty(_spoutSelection);
_updateSelection.onChange([this]() {
std::string currentValue = _spoutSelection.options().empty() ?
"" :
_spoutSelection.option().description;
_spoutSelection.clearOptions();
_spoutSelection.addOption(0, "");
int nSenders = _receiver->GetSenderCount();
int idx = 0;
for (int i = 0; i < nSenders; ++i) {
char Name[256];
_receiver->GetSenderName(i, Name, 256);
_spoutSelection.addOption(i + 1, Name);
if (currentValue == Name) {
idx = i + 1;
}
}
_spoutSelection = idx;
});
addProperty(_updateSelection);
}
bool ScreenSpaceSpout::deinitializeGL() {
_receiver->ReleaseReceiver();
_receiver->Release();
return ScreenSpaceRenderable::deinitializeGL();
}
bool ScreenSpaceSpout::isReady() const {
return ScreenSpaceRenderable::isReady() && !_spoutName.value().empty();
}
void ScreenSpaceSpout::update() {
if (_isFirstUpdate) {
defer { _isFirstUpdate = false; };
// Trigger an update; the value is a dummy that is ignored
_updateSelection.set(0);
// #0 is the empty string and we just pick the first one after that (if it exists)
if (_spoutSelection.options().size() > 1) {
_spoutSelection = 1;
}
}
if (_spoutName.value().empty()) {
return;
}
if (_isSpoutDirty) {
defer { _isSpoutDirty = false; };
std::memset(_currentSenderName, 0, 256);
unsigned int width;
unsigned int height;
_receiver->ReleaseReceiver();
_receiver->GetActiveSender(_currentSenderName);
bool createSuccess = _receiver->CreateReceiver(
_currentSenderName,
width,
height
);
_objectSize = { width, height };
if (!createSuccess) {
LWARNINGC(
"ScreenSpaceSpout",
"Could not create receiver for " << _currentSenderName
);
return;
}
}
unsigned int width;
unsigned int height;
bool receiveSuccess = _receiver->ReceiveTexture(
_currentSenderName,
width,
height
);
if (!receiveSuccess && !_isErrorMessageDisplayed) {
LWARNINGC(
"ScreenSpaceSpout",
"Could not receive texture for " << _currentSenderName
);
_isErrorMessageDisplayed = true;
}
}
void ScreenSpaceSpout::bindTexture() {
_receiver->BindSharedTexture();
}
void ScreenSpaceSpout::unbindTexture() {
_receiver->UnBindSharedTexture();
}
} // namespace openspace
#endif // WIN32
+74
View File
@@ -0,0 +1,74 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_SPOUT___SCREENSPACESPOUT___H__
#define __OPENSPACE_MODULE_SPOUT___SCREENSPACESPOUT___H__
#ifdef WIN32
#include <openspace/rendering/screenspacerenderable.h>
#include <modules/spout/spoutlibrary.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/triggerproperty.h>
namespace openspace {
namespace documentation { struct Documentation; }
class ScreenSpaceSpout : public ScreenSpaceRenderable {
public:
ScreenSpaceSpout(const ghoul::Dictionary& dictionary);
bool deinitializeGL() override;
bool isReady() const override;
void update() override;
static documentation::Documentation Documentation();
private:
void bindTexture() override;
void unbindTexture() override;
properties::StringProperty _spoutName;
properties::OptionProperty _spoutSelection;
properties::TriggerProperty _updateSelection;
SPOUTHANDLE _receiver;
bool _isSpoutDirty = false;
char _currentSenderName[256];
bool _isFirstUpdate = true;
bool _isErrorMessageDisplayed = false;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SPOUT___SCREENSPACESPOUT___H__
#endif // WIN32
+34
View File
@@ -0,0 +1,34 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_SPOUT___SPOUTLIBRARY___H__
#define __OPENSPACE_MODULE_SPOUT___SPOUTLIBRARY___H__
// We need to have this extra file as the Spout people have not put an include guard into
// their file which leads to a violation of the ODR in our usage.
#define __gl_h_
#include <modules/spout/ext/spout/SpoutLibrary.h>
#endif // __OPENSPACE_MODULE_SPOUT___SPOUTLIBRARY___H__
+51
View File
@@ -0,0 +1,51 @@
/*****************************************************************************************
* *
* 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 <modules/spout/spoutmodule.h>
#include <modules/spout/renderableplanespout.h>
#include <modules/spout/screenspacespout.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/misc/assert.h>
namespace openspace {
SpoutModule::SpoutModule() : OpenSpaceModule(Name) {}
void SpoutModule::internalInitialize(const ghoul::Dictionary&) {
#ifdef WIN32
auto fSsRenderable = FactoryManager::ref().factory<ScreenSpaceRenderable>();
ghoul_assert(fSsRenderable, "ScreenSpaceRenderable factory was not created");
fSsRenderable->registerClass<ScreenSpaceSpout>("ScreenSpaceSpout");
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "Renderable factory was not created");
fRenderable->registerClass<RenderablePlaneSpout>("RenderablePlaneSpout");
#endif // WIN32
}
} // namespace openspace
+43
View File
@@ -0,0 +1,43 @@
/*****************************************************************************************
* *
* 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. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_SPOUT___SPOUTMODULE___H__
#define __OPENSPACE_MODULE_SPOUT___SPOUTMODULE___H__
#include <openspace/util/openspacemodule.h>
namespace openspace {
class SpoutModule : public OpenSpaceModule {
public:
constexpr static const char* Name = "Spout";
SpoutModule();
void internalInitialize(const ghoul::Dictionary&) override;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SPOUT___SPOUTMODULE___H__