diff --git a/data/scene/default.scene b/data/scene/default.scene index 5e0b18f4f3..98a1a8612f 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -77,16 +77,29 @@ function postInitialization() openspace.setPropertyValue("SunGlare.renderable.Enabled", false) openspace.setPropertyValue("SunMarker.renderable.Enabled", false) - - -- DU Objects - openspace.setPropertyValue("Quasars.renderable.Enabled", false) - openspace.setPropertyValue("WMAP.renderable.Enabled", false) - openspace.setPropertyValue("Pulsars.renderable.Enabled", false) - openspace.setPropertyValue("Kepler Planetary Candidates.renderable.Enabled", false) - openspace.setPropertyValue("Globular Clusters.renderable.Enabled", false) - - openspace.setPropertyValue("Constellation Bounds.renderable.Enabled", false) + openspace.setPropertyValue("Constellation Bounds.renderable.Enabled", false) + + + -- Digital Universe + openspace.setPropertyValue("WMAP.renderable.Enabled", false) + openspace.setPropertyValue("Quasars.renderable.Enabled", false) + openspace.setPropertyValue("Pulsars.renderable.Enabled", false) + openspace.setPropertyValue("Globular Clusters.renderable.Enabled", false) + openspace.setPropertyValue("Kepler Planetary Candidates.renderable.Enabled", false) + openspace.setPropertyValue("Local Dwarf Galaxies.renderable.Enabled", false) + openspace.setPropertyValue("Exoplanets.renderable.Enabled", false) + openspace.setPropertyValue("Sloan Digital Sky Survey Galaxies.renderable.Enabled", false) + openspace.setPropertyValue("Planetary Nebulae.renderable.Enabled", false) + openspace.setPropertyValue("OB Associations.renderable.Enabled", false) + openspace.setPropertyValue("Open Star Clusters.renderable.Enabled", false) + openspace.setPropertyValue("Supernova Remnants.renderable.Enabled", false) + openspace.setPropertyValue("HII Regions.renderable.Enabled", false) + openspace.setPropertyValue("Abell Galaxy Clusters.renderable.Enabled", false) + openspace.setPropertyValue("2MASS Galaxies.renderable.Enabled", false) + openspace.setPropertyValue("6dF Galaxies.renderable.Enabled", false) + openspace.setPropertyValue("2dF Galaxies.renderable.Enabled", false) + openspace.setPropertyValue("Earth.RenderableGlobe.Atmosphere", true) openspace.setPropertyValue("Earth.RenderableGlobe.Debug.LevelByProjectedAreaElseDistance", false) @@ -132,10 +145,22 @@ return { "constellationbounds", "grids", "quasars/digitaluniverse", - "pulsars/digitaluniverse", "backgroundradiation/digitaluniverse", "globularclusters/digitaluniverse", - "kepler/digitaluniverse" + "kepler/digitaluniverse", + "pulsars/digitaluniverse", + "localdwarfs/digitaluniverse", + "exoplanets/digitaluniverse", + "sloandss/digitaluniverse", + "openclusters/digitaluniverse", + "obassociations/digitaluniverse", + "planetarynebulae/digitaluniverse", + "supernovaremnants/digitaluniverse", + "h2regions/digitaluniverse", + "abell/digitaluniverse", + "2mass/digitaluniverse", + "6dF/digitaluniverse", + "2dF/digitaluniverse", } } diff --git a/ext/ghoul b/ext/ghoul index 3fd891bcc8..5a840979c7 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 3fd891bcc8a7b31eee4021033e9a1dbc72846f1d +Subproject commit 5a840979c7065818df3159c8104a9440908e8db8 diff --git a/ext/sgct b/ext/sgct index d6e251c4b2..f1c7ddb602 160000 --- a/ext/sgct +++ b/ext/sgct @@ -1 +1 @@ -Subproject commit d6e251c4b25f286b6da315d1a461f313a5491c44 +Subproject commit f1c7ddb602148425424048285d457aeb7c57a7d6 diff --git a/modules/digitaluniverse/CMakeLists.txt b/modules/digitaluniverse/CMakeLists.txt index 4b22e65e5a..780ff98ec8 100644 --- a/modules/digitaluniverse/CMakeLists.txt +++ b/modules/digitaluniverse/CMakeLists.txt @@ -28,21 +28,34 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepointssprite.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepoints.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabledumeshes.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablebillboardscloud.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepointssprite.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablepoints.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabledumeshes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderabledumeshes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablebillboardscloud.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) set(SHADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/pointssprite_fs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/pointssprite_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_sprite_fs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_gs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/points_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_gs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard2_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard2_gs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboard2_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboardpolygon_fs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboardpolygon_gs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/billboardpolygon_vs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/dumesh_vs.glsl ${CMAKE_CURRENT_SOURCE_DIR}/shaders/dumesh_fs.glsl ) diff --git a/modules/digitaluniverse/digitaluniversemodule.cpp b/modules/digitaluniverse/digitaluniversemodule.cpp index 234afa704a..5a28bdac32 100644 --- a/modules/digitaluniverse/digitaluniversemodule.cpp +++ b/modules/digitaluniverse/digitaluniversemodule.cpp @@ -32,6 +32,7 @@ #include #include +#include //#include #include @@ -46,6 +47,7 @@ void DigitalUniverseModule::internalInitialize() { ghoul_assert(fRenderable, "Renderable factory was not created"); fRenderable->registerClass("RenderablePoints"); + fRenderable->registerClass("RenderableBillboardsCloud"); //fRenderable->registerClass("RenderablePointsSprite"); fRenderable->registerClass("RenderableDUMeshes"); } diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp new file mode 100644 index 0000000000..e47e89639b --- /dev/null +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp @@ -0,0 +1,1027 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace { + const char* _loggerCat = "RenderableBillboardsCloud"; + const char* KeyFile = "File"; + const char* keyColor = "Color"; + const char* keyUnit = "Unit"; + const char* MeterUnit = "m"; + const char* KilometerUnit = "Km"; + const char* ParsecUnit = "pc"; + const char* KiloparsecUnit = "Kpc"; + const char* MegaparsecUnit = "Mpc"; + const char* GigaparsecUnit = "Gpc"; + const char* GigalightyearUnit = "Gly"; + + const int8_t CurrentCacheVersion = 1; + const double PARSEC = 0.308567756E17; + + static const openspace::properties::Property::PropertyInfo SpriteTextureInfo = { + "Texture", + "Point Sprite Texture", + "The path to the texture that should be used as the point sprite." + }; + + static const openspace::properties::Property::PropertyInfo TransparencyInfo = { + "Transparency", + "Transparency", + "This value is a multiplicative factor that is applied to the transparency of " + "all points." + }; + + static const openspace::properties::Property::PropertyInfo ScaleFactorInfo = { + "ScaleFactor", + "Scale Factor", + "This value is used as a multiplicative factor that is applied to the apparent " + "size of each point." + }; + + static const openspace::properties::Property::PropertyInfo ColorInfo = { + "Color", + "Color", + "This value is used to define the color of the astronomical object." + }; + + static const openspace::properties::Property::PropertyInfo ColorMapInfo = { + "ColorMap", + "Color Map File", + "The path to the color map file of the astronomical onject." + }; + + static const openspace::properties::Property::PropertyInfo PolygonSidesInfo = { + "PolygonSides", + "Polygon Sides", + "The number of sides for the polygon used to represent the astronomical onject." + }; +} // namespace + +namespace openspace { + + documentation::Documentation RenderableBillboardsCloud::Documentation() { + using namespace documentation; + return { + "RenderableBillboardsCloud", + "digitaluniverse_RenderableBillboardsCloud", + { + { + "Type", + new StringEqualVerifier("RenderableBillboardsCloud"), + Optional::No + }, + { + KeyFile, + new StringVerifier, + Optional::No, + "The path to the SPECK file that contains information about the astronomical " + "object being rendered." + }, + { + keyColor, + new Vector3Verifier, + Optional::No, + "Astronomical Object Color (r,g,b)." + }, + { + SpriteTextureInfo.identifier, + new StringVerifier, + Optional::Yes, + SpriteTextureInfo.description + }, + { + TransparencyInfo.identifier, + new DoubleVerifier, + Optional::No, + TransparencyInfo.description + }, + { + ScaleFactorInfo.identifier, + new DoubleVerifier, + Optional::Yes, + ScaleFactorInfo.description + }, + { + ColorMapInfo.identifier, + new StringVerifier, + Optional::Yes, + ColorMapInfo.description + }, + { + PolygonSidesInfo.identifier, + new IntVerifier, + Optional::Yes, + PolygonSidesInfo.description + }, + + } + }; + } + + + RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _dataIsDirty(true) + , _hasSpriteTexture(false) + , _spriteTextureIsDirty(true) + , _hasColorMapFile(false) + , _hasPolygon(false) + , _polygonSides(0) + , _pTexture(0) + , _tTexture(0) + , _alphaValue(TransparencyInfo, 1.f, 0.f, 1.f) + , _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 600.f) + , _pointColor(ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.0f, 1.0f, 1.0f)) + , _spriteTexturePath(SpriteTextureInfo) + , _polygonTexture(nullptr) + , _spriteTexture(nullptr) + , _program(nullptr) + , _speckFile("") + , _colorMapFile("") + , _unit(Parsec) + , _nValuesPerAstronomicalObject(0) + , _vao(0) + , _vbo(0) + { + using File = ghoul::filesystem::File; + + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableBillboardsCloud" + ); + + _speckFile = absPath(dictionary.value(KeyFile)); + + if (dictionary.hasKey(keyUnit)) { + std::string unit = dictionary.value(keyUnit); + if (unit == MeterUnit) { + _unit = Meter; + } + else if (unit == KilometerUnit) { + _unit = Kilometer; + } + else if (unit == ParsecUnit) { + _unit = Parsec; + } + else if (unit == KiloparsecUnit) { + _unit = Kiloparsec; + } + else if (unit == MegaparsecUnit) { + _unit = Megaparsec; + } + else if (unit == GigaparsecUnit) { + _unit = Gigaparsec; + } + else if (unit == GigalightyearUnit) { + _unit = GigalightYears; + } + else { + LWARNING("No unit given for RenderableBillboardsCloud. Using meters as units."); + _unit = Meter; + } + } + + if (dictionary.hasKey(keyColor)) { + _pointColor = dictionary.value(keyColor); + } + addProperty(_pointColor); + + if (dictionary.hasKey(SpriteTextureInfo.identifier)) { + _spriteTexturePath = absPath(dictionary.value( + SpriteTextureInfo.identifier + )); + _spriteTextureFile = std::make_unique(_spriteTexturePath); + + _spriteTexturePath.onChange([&] { _spriteTextureIsDirty = true; }); + _spriteTextureFile->setCallback( + [&](const File&) { _spriteTextureIsDirty = true; } + ); + addProperty(_spriteTexturePath); + + _hasSpriteTexture = true; + } + + if (dictionary.hasKey(ColorMapInfo.identifier)) { + _colorMapFile = absPath(dictionary.value( + ColorMapInfo.identifier + )); + _hasColorMapFile = true; + } + + if (dictionary.hasKey(TransparencyInfo.identifier)) { + _alphaValue = static_cast( + dictionary.value(TransparencyInfo.identifier) + ); + } + addProperty(_alphaValue); + + if (dictionary.hasKey(ScaleFactorInfo.identifier)) { + _scaleFactor = static_cast( + dictionary.value(ScaleFactorInfo.identifier) + ); + } + addProperty(_scaleFactor); + + if (dictionary.hasKey(PolygonSidesInfo.identifier)) { + _polygonSides = static_cast( + dictionary.value(PolygonSidesInfo.identifier) + ); + _hasPolygon = true; + } + + } + + bool RenderableBillboardsCloud::isReady() const { + return (_program != nullptr) && (!_fullData.empty()); + } + + void RenderableBillboardsCloud::initialize() { + RenderEngine& renderEngine = OsEng.renderEngine(); + + _program = renderEngine.buildRenderProgram("RenderableBillboardsCloud", + "${MODULE_DIGITALUNIVERSE}/shaders/billboard2_vs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/billboard2_fs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/billboard2_gs.glsl"); + + bool success = loadData(); + if (!success) { + throw ghoul::RuntimeError("Error loading data"); + } + + if (_hasPolygon) { + createPolygonTexture(); + } + } + + void RenderableBillboardsCloud::deinitialize() { + glDeleteBuffers(1, &_vbo); + _vbo = 0; + glDeleteVertexArrays(1, &_vao); + _vao = 0; + + RenderEngine& renderEngine = OsEng.renderEngine(); + if (_program) { + renderEngine.removeRenderProgram(_program); + _program = nullptr; + } + + if (_hasSpriteTexture) { + _spriteTexture = nullptr; + } + + if (_hasPolygon) { + _polygonTexture = nullptr; + glDeleteTextures(1, &_pTexture); + } + } + + void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) { + glDepthMask(false); + + // Saving current OpenGL state + GLboolean blendEnabled = glIsEnabled(GL_BLEND); + GLenum blendEquationRGB; + GLenum blendEquationAlpha; + GLenum blendDestAlpha; + GLenum blendDestRGB; + GLenum blendSrcAlpha; + GLenum blendSrcRGB; + + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + _program->activate(); + + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + _program->setIgnoreUniformLocationError(IgnoreError::Yes); + + /*glm::dmat4 modelMatrix = glm::dmat4(1.0);*/ + + glm::dmat4 modelMatrix = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation + glm::dmat4(data.modelTransform.rotation) * // Spice rotation + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; + glm::mat4 viewMatrix = data.camera.viewMatrix(); + glm::mat4 projectionMatrix = data.camera.projectionMatrix(); + + _program->setUniform("screenSize", glm::vec2(OsEng.renderEngine().renderingResolution())); + _program->setUniform("projection", projectionMatrix); + _program->setUniform("modelViewTransform", modelViewMatrix); + _program->setUniform("modelViewProjectionTransform", glm::dmat4(projectionMatrix) * modelViewMatrix); + //_program->setUniform("campos", data.camera.positionVec3()); + + _program->setUniform("minBillboardSize", 1.f); // in pixels + _program->setUniform("color", _pointColor); + _program->setUniform("sides", 4); + _program->setUniform("alphaValue", _alphaValue); + _program->setUniform("scaleFactor", _scaleFactor); + + glm::vec3 lookup = data.camera.lookUpVectorWorldSpace(); + glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace(); + glm::vec3 right = glm::cross(viewDirection, lookup); + glm::vec3 up = glm::cross(right, viewDirection); + + glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix); + _program->setUniform("up", glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(up, 0.0)))); + _program->setUniform("right", glm::normalize(glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)))); + + ghoul::opengl::TextureUnit spriteTextureUnit; + if (_hasSpriteTexture) { + spriteTextureUnit.activate(); + _spriteTexture->bind(); + _program->setUniform("spriteTexture", spriteTextureUnit); + } + + ghoul::opengl::TextureUnit polygonTextureUnit; + if (_hasPolygon) { + polygonTextureUnit.activate(); + glBindTexture(GL_TEXTURE_2D, _pTexture); + _program->setUniform("polygonTexture", polygonTextureUnit); + _program->setUniform("hasPolygon", _hasPolygon); + } + + + if (_hasColorMapFile) { + _program->setUniform("hasColorMap", true); + } + else { + _program->setUniform("hasColorMap", false); + } + + glBindVertexArray(_vao); + const GLsizei nAstronomicalObjects = static_cast(_fullData.size() / _nValuesPerAstronomicalObject); + glDrawArrays(GL_POINTS, 0, nAstronomicalObjects); + + glBindVertexArray(0); + using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError; + _program->setIgnoreUniformLocationError(IgnoreError::No); + _program->deactivate(); + + // Restores blending state + glBlendEquationSeparate(blendEquationRGB, blendEquationAlpha); + glBlendFuncSeparate(blendSrcRGB, blendDestRGB, blendSrcAlpha, blendDestAlpha); + + if (!blendEnabled) { + glDisable(GL_BLEND); + } + + glDepthMask(true); + } + + void RenderableBillboardsCloud::update(const UpdateData&) { + if (_dataIsDirty) { + LDEBUG("Regenerating data"); + + createDataSlice(); + + int size = static_cast(_slicedData.size()); + + if (_vao == 0) { + glGenVertexArrays(1, &_vao); + LDEBUG("Generating Vertex Array id '" << _vao << "'"); + } + if (_vbo == 0) { + glGenBuffers(1, &_vbo); + LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); + } + + glBindVertexArray(_vao); + glBindBuffer(GL_ARRAY_BUFFER, _vbo); + glBufferData( + GL_ARRAY_BUFFER, + size * sizeof(float), + &_slicedData[0], + GL_STATIC_DRAW + ); + GLint positionAttrib = _program->attributeLocation("in_position"); + + if (_hasColorMapFile) { + + const size_t nAstronomicalObjects = _fullData.size() / _nValuesPerAstronomicalObject; + const size_t nValues = _slicedData.size() / nAstronomicalObjects; + GLsizei stride = static_cast(sizeof(float) * nValues); + + glEnableVertexAttribArray(positionAttrib); + glVertexAttribPointer( + positionAttrib, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(float)*8, + nullptr + ); + + GLint colorMapAttrib = _program->attributeLocation("in_colormap"); + glEnableVertexAttribArray(colorMapAttrib); + glVertexAttribPointer( + colorMapAttrib, + 4, + GL_FLOAT, + GL_FALSE, + sizeof(float) * 8, + reinterpret_cast(sizeof(float)*4) + ); + } + else { + glEnableVertexAttribArray(positionAttrib); + glVertexAttribPointer( + positionAttrib, + 4, + GL_FLOAT, + GL_FALSE, + 0, + nullptr + ); + } + + glBindVertexArray(0); + + _dataIsDirty = false; + } + + if (_hasSpriteTexture && _spriteTextureIsDirty) { + LDEBUG("Reloading Sprite Texture"); + _spriteTexture = nullptr; + if (_spriteTexturePath.value() != "") { + _spriteTexture = ghoul::io::TextureReader::ref().loadTexture(absPath(_spriteTexturePath)); + if (_spriteTexture) { + LDEBUG("Loaded texture from '" << absPath(_spriteTexturePath) << "'"); + _spriteTexture->uploadTexture(); + } + _spriteTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + + _spriteTextureFile = std::make_unique( + _spriteTexturePath); + _spriteTextureFile->setCallback( + [&](const ghoul::filesystem::File&) { _spriteTextureIsDirty = true; } + ); + } + _spriteTextureIsDirty = false; + } + } + + bool RenderableBillboardsCloud::loadData() { + std::string _file = _speckFile; + std::string cachedFile = FileSys.cacheManager()->cachedFilename( + _file, + ghoul::filesystem::CacheManager::Persistent::Yes + ); + + bool hasCachedFile = FileSys.fileExists(cachedFile); + if (hasCachedFile) { + LINFO("Cached file '" << cachedFile << "' used for Speck file '" << _file << "'"); + + bool success = loadCachedFile(cachedFile); + if (success) { + if (_hasColorMapFile) { + success &= readColorMapFile(); + } + return success; + } + else { + FileSys.cacheManager()->removeCacheFile(_file); + // Intentional fall-through to the 'else' computation to generate the cache + // file for the next run + } + } + else { + LINFO("Cache for Speck file '" << _file << "' not found"); + } + LINFO("Loading Speck file '" << _file << "'"); + + bool success = readSpeckFile(); + if (!success) { + return false; + } + + LINFO("Saving cache"); + success = saveCachedFile(cachedFile); + + if (_hasColorMapFile) { + success &= readColorMapFile(); + } + + return success; + } + + bool RenderableBillboardsCloud::readSpeckFile() { + std::string _file = _speckFile; + std::ifstream file(_file); + if (!file.good()) { + LERROR("Failed to open Speck file '" << _file << "'"); + return false; + } + + _nValuesPerAstronomicalObject = 0; + + // The beginning of the speck file has a header that either contains comments + // (signaled by a preceding '#') or information about the structure of the file + // (signaled by the keywords 'datavar', 'texturevar', and 'texture') + std::string line = ""; + while (true) { + std::streampos position = file.tellg(); + std::getline(file, line); + + if (line[0] == '#' || line.empty()) { + continue; + } + + if (line.substr(0, 7) != "datavar" && + line.substr(0, 10) != "texturevar" && + line.substr(0, 7) != "texture") + { + // we read a line that doesn't belong to the header, so we have to jump back + // before the beginning of the current line + file.seekg(position); + break; + } + + if (line.substr(0, 7) == "datavar") { + // datavar lines are structured as follows: + // datavar # description + // where # is the index of the data variable; so if we repeatedly overwrite + // the 'nValues' variable with the latest index, we will end up with the total + // number of values (+3 since X Y Z are not counted in the Speck file index) + std::stringstream str(line); + + std::string dummy; + str >> dummy; + str >> _nValuesPerAstronomicalObject; + _nValuesPerAstronomicalObject += 1; // We want the number, but the index is 0 based + } + } + + _nValuesPerAstronomicalObject += 3; // X Y Z are not counted in the Speck file indices + + do { + std::vector values(_nValuesPerAstronomicalObject); + + std::getline(file, line); + + if (line.size() == 0) + continue; + + std::stringstream str(line); + + for (int i = 0; i < _nValuesPerAstronomicalObject; ++i) { + str >> values[i]; + } + + _fullData.insert(_fullData.end(), values.begin(), values.end()); + } while (!file.eof()); + + return true; + } + + bool RenderableBillboardsCloud::readColorMapFile() { + std::string _file = _colorMapFile; + std::ifstream file(_file); + if (!file.good()) { + LERROR("Failed to open Color Map file '" << _file << "'"); + return false; + } + + std::size_t numberOfColors = 0; + + // The beginning of the speck file has a header that either contains comments + // (signaled by a preceding '#') or information about the structure of the file + // (signaled by the keywords 'datavar', 'texturevar', and 'texture') + std::string line = ""; + while (true) { + std::streampos position = file.tellg(); + std::getline(file, line); + + if (line[0] == '#' || line.empty()) { + continue; + } + + // Initial number of colors + std::locale loc; + if (std::isdigit(line[0], loc)) { + std::string::size_type sz; + numberOfColors = std::stoi(line, &sz); + break; + } + else if (file.eof()) { + return false; + } + } + + for (auto i = 0; i < numberOfColors; ++i) { + std::getline(file, line); + std::stringstream str(line); + + glm::vec4 color; + for (auto j = 0; j < 4; ++j) { + str >> color[j]; + } + + _colorMapData.push_back(color); + } + + return true; + } + + bool RenderableBillboardsCloud::loadCachedFile(const std::string& file) { + std::ifstream fileStream(file, std::ifstream::binary); + if (fileStream.good()) { + int8_t version = 0; + fileStream.read(reinterpret_cast(&version), sizeof(int8_t)); + if (version != CurrentCacheVersion) { + LINFO("The format of the cached file has changed: deleting old cache"); + fileStream.close(); + FileSys.deleteFile(file); + return false; + } + + int32_t nValues = 0; + fileStream.read(reinterpret_cast(&nValues), sizeof(int32_t)); + fileStream.read(reinterpret_cast(&_nValuesPerAstronomicalObject), sizeof(int32_t)); + + _fullData.resize(nValues); + fileStream.read(reinterpret_cast(&_fullData[0]), + nValues * sizeof(_fullData[0])); + + bool success = fileStream.good(); + return success; + } + else { + LERROR("Error opening file '" << file << "' for loading cache file"); + return false; + } + } + + bool RenderableBillboardsCloud::saveCachedFile(const std::string& file) const { + std::ofstream fileStream(file, std::ofstream::binary); + if (fileStream.good()) { + fileStream.write(reinterpret_cast(&CurrentCacheVersion), + sizeof(int8_t)); + + int32_t nValues = static_cast(_fullData.size()); + if (nValues == 0) { + LERROR("Error writing cache: No values were loaded"); + return false; + } + fileStream.write(reinterpret_cast(&nValues), sizeof(int32_t)); + + int32_t nValuesPerAstronomicalObject = static_cast(_nValuesPerAstronomicalObject); + fileStream.write(reinterpret_cast(&nValuesPerAstronomicalObject), sizeof(int32_t)); + + size_t nBytes = nValues * sizeof(_fullData[0]); + fileStream.write(reinterpret_cast(&_fullData[0]), nBytes); + + bool success = fileStream.good(); + return success; + } + else { + LERROR("Error opening file '" << file << "' for save cache file"); + return false; + } + } + + void RenderableBillboardsCloud::createDataSlice() { + _slicedData.clear(); + if (_hasColorMapFile) { + _slicedData.reserve(8 * (_fullData.size() / _nValuesPerAstronomicalObject)); + } + else { + _slicedData.reserve(4 * (_fullData.size()/_nValuesPerAstronomicalObject)); + } + + int colorIndex = 0; + for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) { + glm::vec3 p = glm::vec3(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2]); + + /* + // Converting untis + if (_unit == Kilometer) { + p *= 1E3; + } + else if (_unit == Parsec) { + p *= PARSEC; + } + else if (_unit == Kiloparsec) { + p *= 1E3 * PARSEC; + } + else if (_unit == Megaparsec) { + p *= 1E6 * PARSEC; + } + else if (_unit == Gigaparsec) { + p *= 1E9 * PARSEC; + } + else if (_unit == GigalightYears) { + p *= 306391534.73091 * PARSEC; + } + */ + + glm::vec4 position(p, static_cast(_unit)); + //glm::dvec4 position(p, 1.0); + + if (_hasColorMapFile) { + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(position[j]); + } + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(_colorMapData[colorIndex][j]); + } + } + else { + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(position[j]); + } + } + + colorIndex = (colorIndex == (_colorMapData.size() - 1)) ? 0 : colorIndex + 1; + } + } + + void RenderableBillboardsCloud::createPolygonTexture() { + LDEBUG("Creating Polygon Texture"); + + glGenTextures(1, &_pTexture); + glBindTexture(GL_TEXTURE_2D, _pTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // Stopped using a buffer object for GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, + 256, 0, GL_RGBA, GL_BYTE, nullptr); + + renderToTexture(std::bind(&openspace::RenderableBillboardsCloud::loadPolygonGeometryForRendering, + this), + std::bind(&openspace::RenderableBillboardsCloud::renderPolygonGeometry, + this, std::placeholders::_1), + _pTexture, 256, 256); + } + + void RenderableBillboardsCloud::createTextTexture() { + glGenTextures(1, &_tTexture); + glBindTexture(GL_TEXTURE_2D, _pTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + // Stopped using a buffer object for GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, + 256, 0, GL_RGBA, GL_BYTE, nullptr); + + renderToTexture(std::bind(&openspace::RenderableBillboardsCloud::loadTextGeometryForRendering, + this), + std::bind(&openspace::RenderableBillboardsCloud::renderTextgonGeometry, + this, std::placeholders::_1), + _pTexture, 256, 256); + } + + void RenderableBillboardsCloud::renderToTexture( + std::function geometryLoadingFunction, + std::function renderFunction, + GLuint textureToRenderTo, GLuint textureWidth, GLuint textureHeight) { + LDEBUG("Rendering to Texture"); + + // Saves initial Application's OpenGL State + GLint defaultFBO; + GLint viewport[4]; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &defaultFBO); + glGetIntegerv(GL_VIEWPORT, viewport); + + GLuint calcFBO; + glGenFramebuffers(1, &calcFBO); + glBindFramebuffer(GL_FRAMEBUFFER, calcFBO); + GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 }; + glDrawBuffers(1, drawBuffers); + + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureToRenderTo, 0); + if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + LERROR("Framework not built. Polygon Texture"); + GLenum fbErr = glCheckFramebufferStatus(GL_FRAMEBUFFER); + switch (fbErr) { + case GL_FRAMEBUFFER_UNDEFINED: + LERROR("Indefined framebuffer."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + LERROR("Incomplete, missing attachement."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + LERROR("Framebuffer doesn't have at least one image attached to it."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + LERROR("Returned if the value of GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE \ + for any color attachment point(s) named by GL_DRAW_BUFFERi."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + LERROR("Returned if GL_READ_BUFFER is not GL_NONE and the value of \ + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE for the color attachment point \ + named by GL_READ_BUFFER."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + LERROR("Returned if the combination of internal formats of the attached images \ + violates an implementation - dependent set of restrictions."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + LERROR("Returned if the value of GL_RENDERBUFFE_r_samples is not the same for all \ + attached renderbuffers; if the value of GL_TEXTURE_SAMPLES is the not same for all \ + attached textures; or , if the attached images are a mix of renderbuffers and textures, \ + the value of GL_RENDERBUFFE_r_samples does not match the value of GL_TEXTURE_SAMPLES."); + LERROR("Returned if the value of GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not the same \ + for all attached textures; or , if the attached images are a mix of renderbuffers and \ + textures, the value of GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not GL_TRUE for all attached textures."); + break; + case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + LERROR("Returned if any framebuffer attachment is layered, and any populated attachment \ + is not layered, or if all populated color attachments are not from textures of the same target."); + break; + default: + LDEBUG("No error found checking framebuffer: Polygon Texture"); + std::cout << "=== OK ===" << std::endl; + break; + } + } + glViewport(0, 0, textureWidth, textureHeight); + + RenderEngine& renderEngine = OsEng.renderEngine(); + + + GLuint pointVao = geometryLoadingFunction(); + renderFunction(pointVao); + + // Restores Applications' OpenGL State + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + + //glDeleteBuffers(1, &pointVbo); + glDeleteVertexArrays(1, &pointVao); + glDeleteFramebuffers(1, &calcFBO); + } + + GLuint RenderableBillboardsCloud::loadPolygonGeometryForRendering() { + GLuint pointVao, pointVbo; + glGenVertexArrays(1, &pointVao); + glGenBuffers(1, &pointVbo); + glBindVertexArray(pointVao); + glBindBuffer(GL_ARRAY_BUFFER, pointVbo); + + const GLfloat vertex_data[] = { + // x y z w + 0.0f, 0.0f, 0.0f, 1.0f, + }; + + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 4, reinterpret_cast(0)); + glEnableVertexAttribArray(0); + glBindVertexArray(0); + + return pointVao; + } + + void RenderableBillboardsCloud::renderPolygonGeometry(GLuint vao) { + RenderEngine& renderEngine = OsEng.renderEngine(); + + std::unique_ptr program = ghoul::opengl::ProgramObject::Build("RenderableBillboardsCloud_Polygon", + "${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_vs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_fs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/billboardpolygon_gs.glsl"); + + program->activate(); + static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + glClearBufferfv(GL_COLOR, 0, black); + + program->setUniform("sides", _polygonSides); + program->setUniform("polygonColor", _pointColor); + + glBindVertexArray(vao); + glDrawArrays(GL_POINTS, 0, 1); + glBindVertexArray(0); + + if (true) { + saveTextureToPPMFile(GL_COLOR_ATTACHMENT0, std::string("polygon_texture.ppm"), + 256, 256); + + } + program->deactivate(); + } + + GLuint RenderableBillboardsCloud::loadTextGeometryForRendering() { + GLuint textVao = 0; + return textVao; + } + + void RenderableBillboardsCloud::renderTextgonGeometry(GLuint vao) { + /* size_t _fontSize = 50; + std::shared_ptr _font = OsEng.fontManager().font("Mono", static_cast(_fontSize)); + _fontRenderer = std::unique_ptr(ghoul::fontrendering::FontRenderer::createDefault()); + _fontRenderer->setFramebufferSize(glm::vec2(256.0f,256.0f)); + + std::string unit = "m"; + glm::vec2 textPosition; + textPosition.x = 0; + textPosition.y = _fontSize / 2.f; + + glm::vec4 color(1.0, 1.0, 1.0, 1.0); + + ; + + _fontRenderer->render( + *_font, + textPosition, + color, + " %.0f %s", + 10.0, unit.c_str() + );*/ + } + + void RenderableBillboardsCloud::saveTextureToPPMFile(const GLenum color_buffer_attachment, + const std::string & fileName, const int width, const int height) const { + std::fstream ppmFile; + + ppmFile.open(fileName.c_str(), std::fstream::out); + if (ppmFile.is_open()) { + unsigned char * pixels = new unsigned char[width*height * 3]; + for (int t = 0; t < width*height * 3; ++t) + pixels[t] = 255; + + if (color_buffer_attachment != GL_DEPTH_ATTACHMENT) { + glReadBuffer(color_buffer_attachment); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + + } + else { + glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels); + } + + ppmFile << "P3" << std::endl; + ppmFile << width << " " << height << std::endl; + ppmFile << "255" << std::endl; + + std::cout << "\n\nFILE\n\n"; + int k = 0; + for (int i = 0; i < width; i++) { + for (int j = 0; j < height; j++) { + ppmFile << (unsigned int)pixels[k] << " " << (unsigned int)pixels[k + 1] << " " << (unsigned int)pixels[k + 2] << " "; + k += 3; + } + ppmFile << std::endl; + } + delete[] pixels; + + ppmFile.close(); + } + } + + +} // namespace openspace diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.h b/modules/digitaluniverse/rendering/renderablebillboardscloud.h new file mode 100644 index 0000000000..494e51cf10 --- /dev/null +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.h @@ -0,0 +1,139 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * 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_DIGITALUNIVERSE___RENDERABLEBILLBOARDSCLOUD___H__ +#define __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLEBILLBOARDSCLOUD___H__ + +#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 { + + namespace documentation { struct Documentation; } + + class RenderableBillboardsCloud : public Renderable { + public: + explicit RenderableBillboardsCloud(const ghoul::Dictionary& dictionary); + ~RenderableBillboardsCloud() = default; + + void initialize() override; + void deinitialize() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; + + static documentation::Documentation Documentation(); + + private: + + enum Unit { + Meter = 0, + Kilometer = 1, + Parsec = 2, + Kiloparsec = 3, + Megaparsec = 4, + Gigaparsec = 5, + + GigalightYears = 6 + }; + + void createDataSlice(); + void createPolygonTexture(); + void createTextTexture(); + void renderToTexture(std::function geometryLoadingFunction, + std::function renderFunction, + GLuint textureToRenderTo, GLuint textureWidth, GLuint textureHeight); + GLuint loadPolygonGeometryForRendering(); + void renderPolygonGeometry(GLuint vao); + GLuint loadTextGeometryForRendering(); + void renderTextgonGeometry(GLuint vao); + + bool loadData(); + bool readSpeckFile(); + bool readColorMapFile(); + bool loadCachedFile(const std::string& file); + bool saveCachedFile(const std::string& file) const; + void saveTextureToPPMFile(const GLenum color_buffer_attachment, + const std::string & fileName, const int width, const int height) const; + + bool _dataIsDirty; + bool _hasSpriteTexture; + bool _spriteTextureIsDirty; + bool _hasColorMapFile; + bool _hasPolygon; + + int _polygonSides; + GLuint _pTexture; + GLuint _tTexture; + + properties::FloatProperty _alphaValue; + properties::FloatProperty _scaleFactor; + properties::Vec3Property _pointColor; + properties::StringProperty _spriteTexturePath; + + std::unique_ptr _polygonTexture; + std::unique_ptr _spriteTexture; + std::unique_ptr _spriteTextureFile; + std::unique_ptr _program; + //std::unique_ptr _fontRenderer; + + std::string _speckFile; + std::string _colorMapFile; + + Unit _unit; + + std::vector _slicedData; + std::vector _fullData; + std::vector _colorMapData; + + int _nValuesPerAstronomicalObject; + + GLuint _vao; + GLuint _vbo; + }; + + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLEBILLBOARDSCLOUD___H__ diff --git a/modules/digitaluniverse/rendering/renderablepoints.cpp b/modules/digitaluniverse/rendering/renderablepoints.cpp index 3c2574f6b8..1acc217745 100644 --- a/modules/digitaluniverse/rendering/renderablepoints.cpp +++ b/modules/digitaluniverse/rendering/renderablepoints.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include namespace { const char* _loggerCat = "RenderablePoints"; @@ -56,6 +58,12 @@ namespace { const int8_t CurrentCacheVersion = 1; const double PARSEC = 0.308567756E17; + + static const openspace::properties::Property::PropertyInfo SpriteTextureInfo = { + "Texture", + "Point Sprite Texture", + "The path to the texture that should be used as the point sprite." + }; static const openspace::properties::Property::PropertyInfo TransparencyInfo = { "Transparency", @@ -75,7 +83,13 @@ namespace { "Color", "Color", "This value is used to define the color of the astronomical object." - }; + }; + + static const openspace::properties::Property::PropertyInfo ColorMapInfo = { + "ColorMap", + "Color Map File", + "The path to the color map file of the astronomical onject." + }; } // namespace namespace openspace { @@ -104,10 +118,16 @@ namespace openspace { Optional::No, "Astronomical Object Color (r,g,b)." }, + { + SpriteTextureInfo.identifier, + new StringVerifier, + Optional::Yes, + SpriteTextureInfo.description + }, { TransparencyInfo.identifier, new DoubleVerifier, - Optional::Yes, + Optional::No, TransparencyInfo.description }, { @@ -115,7 +135,14 @@ namespace openspace { new DoubleVerifier, Optional::Yes, ScaleFactorInfo.description - } + }, + { + ColorMapInfo.identifier, + new StringVerifier, + Optional::Yes, + ColorMapInfo.description + }, + } }; } @@ -124,11 +151,17 @@ namespace openspace { RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _dataIsDirty(true) + , _hasSpriteTexture(false) + , _spriteTextureIsDirty(true) + , _hasColorMapFile(false) , _alphaValue(TransparencyInfo, 1.f, 0.f, 1.f) , _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 64.f) , _pointColor(ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), glm::vec3(1.0f, 1.0f, 1.0f)) + , _spriteTexturePath(SpriteTextureInfo) + , _spriteTexture(nullptr) , _program(nullptr) , _speckFile("") + , _colorMapFile("") , _unit(Parsec) , _nValuesPerAstronomicalObject(0) , _vao(0) @@ -143,8 +176,7 @@ namespace openspace { ); _speckFile = absPath(dictionary.value(KeyFile)); - - + if (dictionary.hasKey(keyUnit)) { std::string unit = dictionary.value(keyUnit); if (unit == MeterUnit) { @@ -179,6 +211,28 @@ namespace openspace { } addProperty(_pointColor); + if (dictionary.hasKey(SpriteTextureInfo.identifier)) { + _spriteTexturePath = absPath(dictionary.value( + SpriteTextureInfo.identifier + )); + _spriteTextureFile = std::make_unique(_spriteTexturePath); + + _spriteTexturePath.onChange([&] { _spriteTextureIsDirty = true; }); + _spriteTextureFile->setCallback( + [&](const File&) { _spriteTextureIsDirty = true; } + ); + addProperty(_spriteTexturePath); + + _hasSpriteTexture = true; + } + + if (dictionary.hasKey(ColorMapInfo.identifier)) { + _colorMapFile = absPath(dictionary.value( + ColorMapInfo.identifier + )); + _hasColorMapFile = true; + } + if (dictionary.hasKey(TransparencyInfo.identifier)) { _alphaValue = static_cast( dictionary.value(TransparencyInfo.identifier) @@ -201,11 +255,18 @@ namespace openspace { void RenderablePoints::initialize() { RenderEngine& renderEngine = OsEng.renderEngine(); - _program = renderEngine.buildRenderProgram("RenderablePoints", - "${MODULE_DIGITALUNIVERSE}/shaders/points_vs.glsl", - "${MODULE_DIGITALUNIVERSE}/shaders/points_fs.glsl");// , - //"${MODULE_DIGITALUNIVERSE}/shaders/points_ge.glsl"); - + if (_hasSpriteTexture) { + _program = renderEngine.buildRenderProgram("RenderablePoints", + "${MODULE_DIGITALUNIVERSE}/shaders/points_vs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/points_sprite_fs.glsl"); + } + else { + _program = renderEngine.buildRenderProgram("RenderablePoints", + "${MODULE_DIGITALUNIVERSE}/shaders/points_vs.glsl", + "${MODULE_DIGITALUNIVERSE}/shaders/points_fs.glsl");// , + //"${MODULE_DIGITALUNIVERSE}/shaders/points_gs.glsl"); + } + bool success = loadData(); if (!success) { throw ghoul::RuntimeError("Error loading data"); @@ -223,6 +284,10 @@ namespace openspace { renderEngine.removeRenderProgram(_program); _program = nullptr; } + + if (_hasSpriteTexture) { + _spriteTexture = nullptr; + } } void RenderablePoints::render(const RenderData& data, RendererTasks&) { @@ -237,13 +302,24 @@ namespace openspace { data.camera.combinedViewMatrix() * modelMatrix); _program->setUniform("color", _pointColor); + _program->setUniform("sides", 4); _program->setUniform("alphaValue", _alphaValue); _program->setUniform("scaleFactor", _scaleFactor); - //setPscUniforms(*_program.get(), data.camera, data.position); - //_program->setUniform("scaling", scaling); - + if (_hasSpriteTexture) { + ghoul::opengl::TextureUnit spriteTextureUnit; + spriteTextureUnit.activate(); + _spriteTexture->bind(); + _program->setUniform("spriteTexture", spriteTextureUnit); + } + if (_hasColorMapFile) { + _program->setUniform("hasColorMap", true); + } + else { + _program->setUniform("hasColorMap", false); + } + glEnable(GL_PROGRAM_POINT_SIZE); glBindVertexArray(_vao); const GLsizei nAstronomicalObjects = static_cast(_fullData.size() / _nValuesPerAstronomicalObject); @@ -274,6 +350,7 @@ namespace openspace { glGenBuffers(1, &_vbo); LDEBUG("Generating Vertex Buffer Object id '" << _vbo << "'"); } + glBindVertexArray(_vao); glBindBuffer(GL_ARRAY_BUFFER, _vbo); glBufferData( @@ -282,28 +359,68 @@ namespace openspace { &_slicedData[0], GL_STATIC_DRAW ); - GLint positionAttrib = _program->attributeLocation("in_position"); - - const size_t nAstronomicalObjects = _fullData.size() / _nValuesPerAstronomicalObject; - const size_t nValues = _slicedData.size() / nAstronomicalObjects; - GLsizei stride = static_cast(sizeof(double) * nValues); + if (_hasColorMapFile) { + + const size_t nAstronomicalObjects = _fullData.size() / _nValuesPerAstronomicalObject; + const size_t nValues = _slicedData.size() / nAstronomicalObjects; + GLsizei stride = static_cast(sizeof(double) * nValues); + + glEnableVertexAttribArray(positionAttrib); + glVertexAttribLPointer( + positionAttrib, + 4, + GL_DOUBLE, + sizeof(double)*8, + nullptr + ); + + GLint colorMapAttrib = _program->attributeLocation("in_colormap"); + glEnableVertexAttribArray(colorMapAttrib); + glVertexAttribLPointer( + colorMapAttrib, + 4, + GL_DOUBLE, + sizeof(double) * 8, + reinterpret_cast(sizeof(double)*4) + ); + } + else { + glEnableVertexAttribArray(positionAttrib); + glVertexAttribLPointer( + positionAttrib, + 4, + GL_DOUBLE, + 0, + nullptr + ); + } - glEnableVertexAttribArray(positionAttrib); - glVertexAttribLPointer( - positionAttrib, - 4, - GL_DOUBLE, - 0, - nullptr - ); - - glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); _dataIsDirty = false; } + + if (_hasSpriteTexture && _spriteTextureIsDirty) { + LDEBUG("Reloading Sprite Texture"); + _spriteTexture = nullptr; + if (_spriteTexturePath.value() != "") { + _spriteTexture = ghoul::io::TextureReader::ref().loadTexture(absPath(_spriteTexturePath)); + if (_spriteTexture) { + LDEBUG("Loaded texture from '" << absPath(_spriteTexturePath) << "'"); + _spriteTexture->uploadTexture(); + } + _spriteTexture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + + _spriteTextureFile = std::make_unique( + _spriteTexturePath); + _spriteTextureFile->setCallback( + [&](const ghoul::filesystem::File&) { _spriteTextureIsDirty = true; } + ); + } + _spriteTextureIsDirty = false; + } } bool RenderablePoints::loadData() { @@ -319,7 +436,10 @@ namespace openspace { bool success = loadCachedFile(cachedFile); if (success) { - return true; + if (_hasColorMapFile) { + success &= readColorMapFile(); + } + return success; } else { FileSys.cacheManager()->removeCacheFile(_file); @@ -340,6 +460,10 @@ namespace openspace { LINFO("Saving cache"); success = saveCachedFile(cachedFile); + if (_hasColorMapFile) { + success &= readColorMapFile(); + } + return success; } @@ -408,6 +532,55 @@ namespace openspace { return true; } + bool RenderablePoints::readColorMapFile() { + std::string _file = _colorMapFile; + std::ifstream file(_file); + if (!file.good()) { + LERROR("Failed to open Color Map file '" << _file << "'"); + return false; + } + + std::size_t numberOfColors = 0; + + // The beginning of the speck file has a header that either contains comments + // (signaled by a preceding '#') or information about the structure of the file + // (signaled by the keywords 'datavar', 'texturevar', and 'texture') + std::string line = ""; + while (true) { + std::streampos position = file.tellg(); + std::getline(file, line); + + if (line[0] == '#' || line.empty()) { + continue; + } + + // Initial number of colors + std::locale loc; + if (std::isdigit(line[0], loc)) { + std::string::size_type sz; + numberOfColors = std::stoi(line, &sz); + break; + } + else if (file.eof()) { + return false; + } + } + + for (auto i = 0; i < numberOfColors; ++i) { + std::getline(file, line); + std::stringstream str(line); + + glm::vec4 color; + for (auto j = 0; j < 4; ++j) { + str >> color[j]; + } + + _colorMapData.push_back(color); + } + + return true; + } + bool RenderablePoints::loadCachedFile(const std::string& file) { std::ifstream fileStream(file, std::ifstream::binary); if (fileStream.good()) { @@ -467,7 +640,14 @@ namespace openspace { void RenderablePoints::createDataSlice() { _slicedData.clear(); + if (_hasColorMapFile) { + _slicedData.reserve(8 * (_fullData.size() / _nValuesPerAstronomicalObject)); + } + else { + _slicedData.reserve(4 * (_fullData.size()/_nValuesPerAstronomicalObject)); + } + int colorIndex = 0; for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) { glm::dvec3 p = glm::dvec3(_fullData[i + 0], _fullData[i + 1], _fullData[i + 2]); @@ -493,9 +673,21 @@ namespace openspace { glm::dvec4 position(p, 1.0); - for (auto j = 0; j < 4; ++j) { - _slicedData.push_back(position[j]); - } + if (_hasColorMapFile) { + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(position[j]); + } + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(_colorMapData[colorIndex][j]); + } + } + else { + for (auto j = 0; j < 4; ++j) { + _slicedData.push_back(position[j]); + } + } + + colorIndex = (colorIndex == (_colorMapData.size() - 1)) ? 0 : colorIndex + 1; } } diff --git a/modules/digitaluniverse/rendering/renderablepoints.h b/modules/digitaluniverse/rendering/renderablepoints.h index 07f83b8ae3..df22bef073 100644 --- a/modules/digitaluniverse/rendering/renderablepoints.h +++ b/modules/digitaluniverse/rendering/renderablepoints.h @@ -80,24 +80,33 @@ namespace openspace { bool loadData(); bool readSpeckFile(); + bool readColorMapFile(); bool loadCachedFile(const std::string& file); bool saveCachedFile(const std::string& file) const; bool _dataIsDirty; + bool _hasSpriteTexture; + bool _spriteTextureIsDirty; + bool _hasColorMapFile; properties::FloatProperty _alphaValue; properties::FloatProperty _scaleFactor; properties::Vec3Property _pointColor; + properties::StringProperty _spriteTexturePath; - + std::unique_ptr _spriteTexture; + std::unique_ptr _spriteTextureFile; std::unique_ptr _program; std::string _speckFile; + std::string _colorMapFile; Unit _unit; std::vector _slicedData; std::vector _fullData; + std::vector _colorMapData; + int _nValuesPerAstronomicalObject; GLuint _vao; diff --git a/modules/digitaluniverse/shaders/billboard2_fs.glsl b/modules/digitaluniverse/shaders/billboard2_fs.glsl new file mode 100644 index 0000000000..e1841e02b6 --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard2_fs.glsl @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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 gs_colorMap; +in float vs_screenSpaceDepth; +in vec2 texCoord; + +uniform float alphaValue; +uniform vec3 color; +uniform sampler2D spriteTexture; +uniform sampler2D polygonTexture; +uniform bool hasColorMap; +uniform bool hasPolygon; + +Fragment getFragment() { + + vec4 textureColor = texture(spriteTexture, texCoord); + + vec4 fullColor = vec4(1.0); + + if (hasColorMap) { + fullColor = vec4(gs_colorMap.rgb * textureColor.rgb, gs_colorMap.a * textureColor.a * alphaValue); + } else if (hasPolygon) { + vec4 polygon = texture(polygonTexture, texCoord); + fullColor = vec4(color.rgb * textureColor.rgb + polygon.rgb, textureColor.a * alphaValue); + } else { + fullColor = vec4(color.rgb * textureColor.rgb, textureColor.a * alphaValue); + } + + if (fullColor.a == 0.f) { + discard; + } + + Fragment frag; + frag.color = fullColor; + frag.depth = vs_screenSpaceDepth; + + return frag; +} diff --git a/modules/digitaluniverse/shaders/billboard2_gs.glsl b/modules/digitaluniverse/shaders/billboard2_gs.glsl new file mode 100644 index 0000000000..0cfa63a992 --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard2_gs.glsl @@ -0,0 +1,110 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "PowerScaling/powerScalingMath.hglsl" + +layout(points) in; +layout(triangle_strip, max_vertices = 6) out; + +uniform dmat4 modelViewProjectionTransform; +uniform float scaleFactor; +uniform vec3 up; +uniform vec3 right; + + +in vec4 colorMap[]; + +out vec4 gs_colorMap; +out vec2 texCoord; +out float vs_screenSpaceDepth; + +const double PARSEC = 0.308567756e17LF; + +const vec2 corners[4] = vec2[4]( + vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0), + vec2(0.0, 1.0) +); + + +void main() { + vec4 pos = gl_in[0].gl_Position; + gs_colorMap = colorMap[0]; + + // Temp: + double scaleMultiply = exp(scaleFactor/10); + dvec3 scaledRight = scaleMultiply * right/2.0f; + dvec3 scaledUp = scaleMultiply * up/2.0f; + + double unit = PARSEC; + + // Must be the same as the enum in RenderableBillboardsCloud.h + if (pos.w == 1.f) { + unit = 1E3; + } else if (pos.w == 2.f) { + unit = PARSEC; + } else if (pos.w == 3.f) { + unit = 1E3 * PARSEC; + } else if (pos.w == 4.f) { + unit = 1E6 * PARSEC; + } else if (pos.w == 5.f) { + unit = 1E9 * PARSEC; + } else if (pos.w == 6.f) { + unit = 306391534.73091 * PARSEC; + } + + dvec4 dpos = dvec4(dvec3(pos.xyz) * unit, 1.0); + + texCoord = corners[0]; + vec4 initialPosition = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz - scaledRight - scaledUp, dpos.w))); + vs_screenSpaceDepth = initialPosition.w; + gl_Position = initialPosition; + EmitVertex(); + + texCoord = corners[1]; + gl_Position = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledRight - scaledUp, dpos.w))); + EmitVertex(); + + texCoord = corners[2]; + vec4 crossCorner = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledUp + scaledRight, dpos.w))); + gl_Position = crossCorner; + EmitVertex(); + EndPrimitive(); // First Triangle + + texCoord = corners[0]; + gl_Position = initialPosition; + EmitVertex(); + + texCoord = corners[2]; + gl_Position = crossCorner; + EmitVertex(); + + texCoord = corners[3]; + gl_Position = z_normalization(vec4(modelViewProjectionTransform * dvec4(dpos.xyz + scaledUp - scaledRight, dpos.w))); + EmitVertex(); + EndPrimitive(); // Second Triangle +} diff --git a/modules/digitaluniverse/shaders/billboard2_vs.glsl b/modules/digitaluniverse/shaders/billboard2_vs.glsl new file mode 100644 index 0000000000..502b863ac2 --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard2_vs.glsl @@ -0,0 +1,37 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "PowerScaling/powerScaling_vs.hglsl" + +in vec4 in_position; +in vec4 in_colormap; + +out vec4 colorMap; + +void main() { + colorMap = in_colormap; + gl_Position = vec4(in_position); +} \ No newline at end of file diff --git a/modules/digitaluniverse/shaders/billboard_fs.glsl b/modules/digitaluniverse/shaders/billboard_fs.glsl new file mode 100644 index 0000000000..cdac0826bd --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard_fs.glsl @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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 gs_colorMap; +in float gs_screenSpaceDepth; +in vec2 texCoord; + +//uniform bool hasColorMap; +uniform float alphaValue; +uniform vec3 color; +uniform sampler2D spriteTexture; + +Fragment getFragment() { + + vec4 textureColor = texture(spriteTexture, texCoord); + vec4 fullColor = vec4(0.0); + + //if (hasColorMap) { + // fullColor = vec4(gs_colorMap.rgb * textureColor.rgb, textureColor.a); + // } + //else { + fullColor = vec4(color.rgb * textureColor.rgb, textureColor.a); + // } + + //fullColor.a *= alphaValue; + + //if (fullColor.a == 0) { + // discard; + //} + + //fullColor = vec4(textureColor.rgb, 1.0); + fullColor = vec4(1.0); + + Fragment frag; + frag.color = fullColor; + frag.depth = gs_screenSpaceDepth; + + return frag; +} diff --git a/modules/digitaluniverse/shaders/billboard_gs.glsl b/modules/digitaluniverse/shaders/billboard_gs.glsl new file mode 100644 index 0000000000..ed63ced931 --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard_gs.glsl @@ -0,0 +1,97 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "PowerScaling/powerScalingMath.hglsl" + +layout(points) in; +layout(triangle_strip, max_vertices = 4) out; +//layout(points, max_vertices = 1) out; + +in vec4 orig_position[]; +//in vec4 colorMap[]; +in float vs_screenSpaceDepth[]; + +out vec2 texCoord; +out float billboardSize; +out float gs_screenSpaceDepth; +//out vec4 gs_colorMap; + +uniform mat4 projection; +uniform float scaleFactor; +uniform float minBillboardSize; +uniform vec2 screenSize; + +const vec2 corners[4] = vec2[4]( + vec2(0.0, 1.0), + vec2(0.0, 0.0), + vec2(1.0, 1.0), + vec2(1.0, 0.0) +); + + +void main() { + gs_screenSpaceDepth = vs_screenSpaceDepth[0]; + //gs_colorMap = colorMap[0]; + + // if ((orig_position[0].x == 0.0) && + // (orig_position[0].y == 0.0) && + // (orig_position[0].z == 0.0)) + // { + // return; + // } + + //float modifiedSpriteSize = exp((-30.623 - 0.5) * 1.0) * scaleFactor * 2000; + + float modifiedSpriteSize = + exp((-30.623 - (-5.0)) * 0.462) * 1.0 * 2000; + + vec4 projPos[4]; + for (int i = 0; i < 4; ++i) { + vec4 p1 = gl_in[0].gl_Position; + p1.xy += vec2(modifiedSpriteSize * (corners[i] - vec2(0.5))); + projPos[i] = projection * p1; + } + + // Calculate the positions of the lower left and upper right corners of the + // billboard in screen-space + vec2 ll = (((projPos[1].xy / projPos[1].w) + 1.0) / 2.0) * screenSize; + vec2 ur = (((projPos[2].xy / projPos[2].w) + 1.0) / 2.0) * screenSize; + + // The billboard is smaller than one pixel, we can discard it + float sizeInPixels = length(ll - ur); + //if (sizeInPixels < minBillboardSize) { + // return; + //} + + for (int i = 0; i < 4; i++) { + gl_Position = projPos[i]; + texCoord = corners[i]; + billboardSize = sizeInPixels; + EmitVertex(); + } + + EndPrimitive(); +} diff --git a/modules/digitaluniverse/shaders/billboard_vs.glsl b/modules/digitaluniverse/shaders/billboard_vs.glsl new file mode 100644 index 0000000000..e92c5c6d0b --- /dev/null +++ b/modules/digitaluniverse/shaders/billboard_vs.glsl @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +#include "PowerScaling/powerScaling_vs.hglsl" + +in dvec4 in_position; +//in dvec4 in_colormap; + +uniform dmat4 modelViewTransform; +uniform mat4 projection; + +out float vs_screenSpaceDepth; +out vec4 orig_position; +//out vec4 colorMap; + +void main() { + orig_position = vec4(in_position); + //colorMap = vec4(in_colormap); + + vec4 positionViewSpace = vec4(modelViewTransform * in_position); + vec4 positionScreenSpace = vec4(z_normalization(projection * positionViewSpace)); + //vec4 positionScreenSpace = vec4(projection * positionViewSpace); + vs_screenSpaceDepth = positionScreenSpace.w; + + gl_Position = positionViewSpace; +} \ No newline at end of file diff --git a/modules/digitaluniverse/shaders/billboardpolygon_fs.glsl b/modules/digitaluniverse/shaders/billboardpolygon_fs.glsl new file mode 100644 index 0000000000..308c020742 --- /dev/null +++ b/modules/digitaluniverse/shaders/billboardpolygon_fs.glsl @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ +#version __CONTEXT__ + +out vec4 finalColor; + +uniform vec3 polygonColor; + +void main(void) { + + finalColor = vec4(polygonColor, 1.0 ); +} diff --git a/modules/digitaluniverse/shaders/billboardpolygon_gs.glsl b/modules/digitaluniverse/shaders/billboardpolygon_gs.glsl new file mode 100644 index 0000000000..dbb4611b6f --- /dev/null +++ b/modules/digitaluniverse/shaders/billboardpolygon_gs.glsl @@ -0,0 +1,74 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(points) in; +//layout(line_strip, max_vertices = 19) out; +layout(triangle_strip, max_vertices = 63) out; + +uniform int sides; + +const float PI = 3.1415926; + +void main() +{ + // for (int i = 0; i <= sides; i++) { + // // Angle between each side in radians + // float ang = PI * 2.0 / float(sides) * i; + + // // Offset from center of point (0.3 to accomodate for aspect ratio) + // //vec4 offset = vec4(cos(ang) * 0.003, -sin(ang) * 0.004, 0.0, 0.0); + // vec4 offset = vec4(cos(ang) * 0.8, -sin(ang) * 0.8, 0.0, 0.0); + // gl_Position = gl_in[0].gl_Position + offset; + + // // vec4 offset = vec4(cos(ang) * gl_in[0].gl_Position[0], -sin(ang) * gl_in[0].gl_Position[1], + // // gl_in[0].gl_Position[2] , gl_in[0].gl_Position[3]); + // // gl_Position = offset; + + // EmitVertex(); + // } + // EndPrimitive(); + + vec4 v0 = gl_in[0].gl_Position; + + for (int i = sides; i > 0; --i) { + // Angle between each side in radians + float ang = PI * 2.0 / float(sides) * i; + + gl_Position = v0; + EmitVertex(); + + vec4 vi = v0 + vec4(cos(ang) * 0.8, -sin(ang) * 0.8, 0.0, 0.0); + gl_Position = vi; + EmitVertex(); + + ang = PI * 2.0 / float(sides) * (i-1); + vec4 vii = v0 + vec4(cos(ang) * 0.8, -sin(ang) * 0.8, 0.0, 0.0); + gl_Position = vii; + EmitVertex(); + + EndPrimitive(); + } +} \ No newline at end of file diff --git a/modules/digitaluniverse/shaders/billboardpolygon_vs.glsl b/modules/digitaluniverse/shaders/billboardpolygon_vs.glsl new file mode 100644 index 0000000000..36582d7fac --- /dev/null +++ b/modules/digitaluniverse/shaders/billboardpolygon_vs.glsl @@ -0,0 +1,31 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 in_position; + +void main() { + gl_Position = in_position; +} diff --git a/modules/digitaluniverse/shaders/points_fs.glsl b/modules/digitaluniverse/shaders/points_fs.glsl index f8c0922ced..ec8e442eb0 100644 --- a/modules/digitaluniverse/shaders/points_fs.glsl +++ b/modules/digitaluniverse/shaders/points_fs.glsl @@ -24,11 +24,13 @@ #include "fragment.glsl" +//in float gs_screenSpaceDepth; in float vs_screenSpaceDepth; -flat in dvec4 test; +in vec4 colorMap; uniform vec3 color; uniform float alphaValue; +uniform bool hasColorMap; Fragment getFragment() { Fragment frag; @@ -37,7 +39,13 @@ Fragment getFragment() { discard; } - frag.color = vec4(color, alphaValue); + if (hasColorMap) { + frag.color = vec4(colorMap.xyz, alphaValue); + } else { + frag.color = vec4(color, alphaValue); + } + + //frag.depth = gs_screenSpaceDepth; frag.depth = vs_screenSpaceDepth; return frag; diff --git a/modules/digitaluniverse/shaders/points_gs.glsl b/modules/digitaluniverse/shaders/points_gs.glsl new file mode 100644 index 0000000000..e6a10dc371 --- /dev/null +++ b/modules/digitaluniverse/shaders/points_gs.glsl @@ -0,0 +1,64 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(points) in; +//layout(points, max_vertices = 13) out; +layout(line_strip, max_vertices = 13) out; + +in float vs_screenSpaceDepth[]; +in float vs_scaleFactor[]; +in vec4 colorMap[] + +uniform int sides; + +out float gs_screenSpaceDepth; + +const float PI = 3.1415926; + +void main() +{ + gs_screenSpaceDepth = vs_screenSpaceDepth[0]; + + for (int i = 0; i <= sides; i++) { + // Angle between each side in radians + float ang = PI * 2.0 / float(sides) * i; + + // Offset from center of point (0.3 to accomodate for aspect ratio) + //vec4 offset = vec4(cos(ang) * 0.003, -sin(ang) * 0.004, 0.0, 0.0); + //gl_Position = gl_in[0].gl_Position + offset; + + vec4 offset = vec4(cos(ang) * gl_in[0].gl_Position[0], -sin(ang) * gl_in[0].gl_Position[1], + gl_in[0].gl_Position[2] , gl_in[0].gl_Position[3]); + gl_Position = offset; + + EmitVertex(); + } + + //gl_Position = gl_in[0].gl_Position;// + offset; + //EmitVertex(); + + EndPrimitive(); +} \ No newline at end of file diff --git a/modules/digitaluniverse/shaders/points_sprite_fs.glsl b/modules/digitaluniverse/shaders/points_sprite_fs.glsl new file mode 100644 index 0000000000..adec29b29b --- /dev/null +++ b/modules/digitaluniverse/shaders/points_sprite_fs.glsl @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2017 * + * * + * 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 float gs_screenSpaceDepth; +in float vs_screenSpaceDepth; + +uniform vec3 color; +uniform float alphaValue; + +// Sprite +uniform sampler2D spriteTexture; + +Fragment getFragment() { + Fragment frag; + + if (alphaValue == 0.0) { + discard; + } + + frag.color = texture(spriteTexture, gl_PointCoord) * vec4(color, alphaValue); + //frag.depth = gs_screenSpaceDepth; + frag.depth = vs_screenSpaceDepth; + frag.blend = BLEND_MODE_ADDITIVE; + + return frag; +} diff --git a/modules/digitaluniverse/shaders/points_vs.glsl b/modules/digitaluniverse/shaders/points_vs.glsl index a3b2f0e64b..de7bdba519 100644 --- a/modules/digitaluniverse/shaders/points_vs.glsl +++ b/modules/digitaluniverse/shaders/points_vs.glsl @@ -27,21 +27,24 @@ #include "PowerScaling/powerScaling_vs.hglsl" in dvec4 in_position; +in dvec4 in_colormap; uniform dmat4 modelViewProjectionTransform; uniform float scaleFactor; out float vs_screenSpaceDepth; -out dvec4 test; +out float vs_scaleFactor; +out vec4 colorMap; void main() { - test = in_position; vec4 positionClipSpace = vec4(modelViewProjectionTransform * in_position); - //positionClipSpace = vec4( modelViewProjectionTransform * - //vec4(0,0,0,1)); + // positionClipSpace = vec4( modelViewProjectionTransform * + // vec4(0,0,0,1)); vec4 positionScreenSpace = vec4(z_normalization(positionClipSpace)); vs_screenSpaceDepth = positionScreenSpace.w; + vs_scaleFactor = scaleFactor; + colorMap = vec4(in_colormap); gl_PointSize = scaleFactor; gl_Position = positionScreenSpace; diff --git a/modules/kameleon/ext/kameleon b/modules/kameleon/ext/kameleon index 1b4549edc7..3de739a553 160000 --- a/modules/kameleon/ext/kameleon +++ b/modules/kameleon/ext/kameleon @@ -1 +1 @@ -Subproject commit 1b4549edc74ef371730ef9d39c1ffa0efe90a985 +Subproject commit 3de739a55387051fb6fdfd327ad761dffa317420 diff --git a/openspace.cfg b/openspace.cfg index 12db70bccb..5f8184f70c 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -7,10 +7,10 @@ return { -- occurs in a single window, a fisheye projection, or a dome cluster system -- A regular 1280x720 window - SGCTConfig = sgct.config.single{}, + --SGCTConfig = sgct.config.single{}, -- A regular 1920x1080 window - -- SGCTConfig = sgct.config.single{1920, 1080}, + SGCTConfig = sgct.config.single{1920, 1080}, -- A windowed 1920x1080 fullscreen -- SGCTConfig = sgct.config.single{1920, 1080, border=false, windowPos={0,0}, shared=true, name="WV_OBS_SPOUT1"},