/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2018 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * * without restriction, including without limitation the rights to use, copy, modify, * * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to the following * * conditions: * * * * The above copyright notice and this permission notice shall be included in all copies * * or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include namespace { constexpr const char* keyStart = "StartTime"; constexpr const char* keyEnd = "EndTime"; constexpr const char* KeyType = "Type"; constexpr const char* KeyTag = "Tag"; static const openspace::properties::Property::PropertyInfo EnabledInfo = { "Enabled", "Is Enabled", "This setting determines whether this object will be visible or not." }; static const openspace::properties::Property::PropertyInfo OpacityInfo = { "Opacity", "Transparency", "This value determines the transparency of this object." }; } // namespace namespace openspace { documentation::Documentation Renderable::Documentation() { using namespace openspace::documentation; return { "Renderable", "renderable", { { KeyType, new StringAnnotationVerifier("A valid Renderable created by a factory"), Optional::No, "This key specifies the type of Renderable that gets created. It has to " "be one of the valid Renderables that are available for creation (see " "the FactoryDocumentation for a list of possible Renderables), which " "depends on the configration of the application" }, { EnabledInfo.identifier, new BoolVerifier, Optional::Yes, EnabledInfo.description }, { OpacityInfo.identifier, new DoubleInRangeVerifier(0.0, 1.0), Optional::Yes, OpacityInfo.description } } }; } std::unique_ptr Renderable::createFromDictionary( const ghoul::Dictionary& dictionary) { // The name is passed down from the SceneGraphNode ghoul_assert( dictionary.hasKeyAndValue(SceneGraphNode::KeyName), "The SceneGraphNode did not set the 'name' key" ); std::string name = dictionary.value(SceneGraphNode::KeyName); documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable"); std::string renderableType = dictionary.value(KeyType); auto factory = FactoryManager::ref().factory(); ghoul_assert(factory, "Renderable factory did not exist"); std::unique_ptr result = factory->create(renderableType, dictionary); return result; } Renderable::Renderable(const ghoul::Dictionary& dictionary) : properties::PropertyOwner({ "renderable" }) , _enabled(EnabledInfo, true) , _opacity(OpacityInfo, 1.f, 0.f, 1.f) , _renderBin(RenderBin::Opaque) , _startTime("") , _endTime("") , _hasTimeInterval(false) { ghoul_assert( dictionary.hasKeyAndValue(SceneGraphNode::KeyName), std::string("SceneGraphNode must specify '") + SceneGraphNode::KeyName + "'" ); dictionary.getValue(keyStart, _startTime); dictionary.getValue(keyEnd, _endTime); if (dictionary.hasKeyAndValue(KeyTag)) { std::string tagName = dictionary.value(KeyTag); if (!tagName.empty()) { addTag(std::move(tagName)); } } else if (dictionary.hasKeyAndValue(KeyTag)) { ghoul::Dictionary tagNames = dictionary.value(KeyTag); std::vector keys = tagNames.keys(); std::string tagName; for (const std::string& key : keys) { tagName = tagNames.value(key); if (!tagName.empty()) { addTag(std::move(tagName)); } } } if (!_startTime.empty() && !_endTime.empty()) { _hasTimeInterval = true; } if (dictionary.hasKey(EnabledInfo.identifier)) { _enabled = dictionary.value(EnabledInfo.identifier); } if (dictionary.hasKey(OpacityInfo.identifier)) { _opacity = static_cast(dictionary.value(OpacityInfo.identifier)); } addProperty(_enabled); } Renderable::~Renderable() {} void Renderable::initialize() {} void Renderable::initializeGL() {} void Renderable::deinitialize() {} void Renderable::deinitializeGL() {} void Renderable::setBoundingSphere(float boundingSphere) { _boundingSphere = boundingSphere; } float Renderable::boundingSphere() const { return _boundingSphere; } void Renderable::update(const UpdateData&) {} void Renderable::render(const RenderData&, RendererTasks&) {} SurfacePositionHandle Renderable::calculateSurfacePositionHandle( const glm::dvec3& targetModelSpace) { glm::dvec3 directionFromCenterToTarget = glm::normalize(targetModelSpace); return { directionFromCenterToTarget * static_cast(boundingSphere()), directionFromCenterToTarget, 0.0 }; } void Renderable::setPscUniforms(ghoul::opengl::ProgramObject& program, const Camera& camera, const PowerScaledCoordinate& position) { program.setUniform("campos", camera.position().vec4()); program.setUniform("objpos", position.vec4()); program.setUniform("camrot", glm::mat4(camera.viewRotationMatrix())); program.setUniform("scaling", camera.scaling()); } Renderable::RenderBin Renderable::renderBin() const { return _renderBin; } void Renderable::setRenderBin(RenderBin bin) { _renderBin = bin; } bool Renderable::matchesRenderBinMask(int binMask) { return binMask & static_cast(renderBin()); } bool Renderable::isVisible() const { return _enabled; } bool Renderable::hasTimeInterval() { return _hasTimeInterval; } bool Renderable::getInterval(double& start, double& end) { if (_startTime != "" && _endTime != "") { start = SpiceManager::ref().ephemerisTimeFromDate(_startTime); end = SpiceManager::ref().ephemerisTimeFromDate(_endTime); return true; } else { return false; } } bool Renderable::isReady() const { return true; } bool Renderable::isEnabled() const { return _enabled; } void Renderable::onEnabledChange(std::function callback) { _enabled.onChange([this, c{ std::move(callback) }]() { c(isEnabled()); }); } void Renderable::registerUpdateRenderBinFromOpacity() { _opacity.onChange([this](){ if (_opacity > 0.f && _opacity < 1.f) { setRenderBin(Renderable::RenderBin::Transparent); } else { setRenderBin(Renderable::RenderBin::Opaque); } }); } } // namespace openspace