mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-20 03:00:03 -06:00
- Refactored several files - Implemented PositionInformation subclasses - Added standard shaders in the shader directory - Removed SceneGraphLoader, now integrated in the SceneGraph - TODO: Further testing and improvements to the PowerScale coordinate system
308 lines
9.9 KiB
C++
308 lines
9.9 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014 *
|
|
* *
|
|
* 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. *
|
|
****************************************************************************************/
|
|
|
|
// open space includes
|
|
#include "scenegraph/scenegraphnode.h"
|
|
#include "util/spice.h"
|
|
|
|
// ghoul includes
|
|
#include <ghoul/logging/logmanager.h>
|
|
#include <ghoul/logging/consolelog.h>
|
|
#include <ghoul/filesystem/filesystem.h>
|
|
#include <ghoul/opengl/shadermanager.h>
|
|
#include <ghoul/opengl/programobject.h>
|
|
#include <ghoul/opengl/shaderobject.h>
|
|
|
|
#include <scenegraph/constantpositioninformation.h>
|
|
#include <openspaceengine.h>
|
|
|
|
namespace {
|
|
std::string _loggerCat = "SceneGraphNode";
|
|
}
|
|
|
|
namespace openspace {
|
|
|
|
SceneGraphNode::SceneGraphNode(): _parent(nullptr), _nodeName("Unnamed OpenSpace SceneGraphNode"),
|
|
_position(nullptr), _renderable(nullptr),
|
|
_renderableVisible(false), _boundingSphereVisible(false) {}
|
|
|
|
SceneGraphNode::~SceneGraphNode() {
|
|
LDEBUG("Deallocating: " << _nodeName);
|
|
|
|
// deallocate the renderable
|
|
if(_renderable != nullptr)
|
|
delete _renderable;
|
|
|
|
// deallocate the child nodes and delete them, iterate c++11 style
|
|
for( auto child: _children)
|
|
delete child;
|
|
}
|
|
|
|
bool SceneGraphNode::_initialize() {
|
|
using ghoul::opengl::ShaderObject;
|
|
using ghoul::opengl::ProgramObject;
|
|
using ghoul::opengl::ShaderManager;
|
|
ShaderObject* powerscale_vs = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex,
|
|
absPath("${SHADERS}/pscstandard_vs.glsl"),
|
|
"PS Vertex"
|
|
);
|
|
ShaderObject* powerscale_fs = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment,
|
|
absPath("${SHADERS}/pscstandard_fs.glsl"),
|
|
"PS Fragment"
|
|
);
|
|
|
|
ProgramObject* po = new ProgramObject;
|
|
po->attachObject(powerscale_vs);
|
|
po->attachObject(powerscale_fs);
|
|
|
|
if( ! po->compileShaderObjects())
|
|
return false;
|
|
if( ! po->linkProgramObject())
|
|
return false;
|
|
|
|
OsEng.ref().configurationManager().setValue("pscShader", po);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool SceneGraphNode::initialize() {
|
|
|
|
if( ! _initialize()) {
|
|
return false;
|
|
}
|
|
|
|
_position = new ConstantPositionInformation;
|
|
_position->initializeWithDictionary(nullptr);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SceneGraphNode::initializeWithDictionary(ghoul::Dictionary* dictionary) {
|
|
|
|
if( ! _initialize()) {
|
|
return false;
|
|
}
|
|
|
|
// set the _nodeName if available
|
|
dictionary->getValue("Name", _nodeName);
|
|
|
|
std::string path;
|
|
dictionary->getValue("Path", path);
|
|
|
|
if(dictionary->hasKey("Renderable")) {
|
|
if(safeInitializeWithDictionary<Renderable>(&_renderable, "Renderable", dictionary, path)) {
|
|
LDEBUG("Successful initialization of renderable!");
|
|
if ( ! _renderable) {
|
|
LFATAL("But the renderable is not initialized for " << _nodeName);
|
|
}
|
|
} else {
|
|
LDEBUG("Failed to initialize renderable!");
|
|
}
|
|
}
|
|
if(dictionary->hasKey("Position")) {
|
|
if(safeInitializeWithDictionary<PositionInformation>(&_position, "Position", dictionary, path)) {
|
|
LDEBUG("Successful initialization of position!");
|
|
if ( ! _position) {
|
|
LFATAL("But the position is not initialized for " << _nodeName);
|
|
}
|
|
} else {
|
|
LDEBUG("Failed to initialize position!");
|
|
}
|
|
}
|
|
|
|
if (_position == nullptr) {
|
|
_position = new ConstantPositionInformation;
|
|
_position->initializeWithDictionary(nullptr);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// essential
|
|
void SceneGraphNode::update() {
|
|
_position->update();
|
|
}
|
|
|
|
void SceneGraphNode::evaluate(const Camera *camera, const psc& parentPosition) {
|
|
|
|
const psc thisPosition = parentPosition + _position->position();
|
|
const psc camPos = camera->getPosition();
|
|
const psc toCamera = thisPosition - camPos;
|
|
|
|
// init as not visible
|
|
_boundingSphereVisible = false;
|
|
_renderableVisible = false;
|
|
|
|
// check if camera is outside the node boundingsphere
|
|
if(toCamera.length() > _boundingSphere) {
|
|
|
|
// check if the boudningsphere is visible before avaluating children
|
|
if( ! sphereInsideFrustum(thisPosition, _boundingSphere, camera)) {
|
|
// the node is completely outside of the camera view, stop evaluating this node
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
// inside boudningsphere or parts of the sphere is visible, individual
|
|
// children needs to be evaluated
|
|
_boundingSphereVisible = true;
|
|
|
|
// this node has an renderable
|
|
if(_renderable) {
|
|
|
|
// check if the renderable boundingsphere is visible
|
|
_renderableVisible = sphereInsideFrustum(thisPosition, _renderable->getBoundingSphere(), camera);
|
|
}
|
|
|
|
// evaluate all the children, tail-recursive function(?)
|
|
for(auto &child: _children) {
|
|
child->evaluate(camera,psc());
|
|
}
|
|
|
|
}
|
|
|
|
void SceneGraphNode::render(const Camera *camera, const psc & parentPosition) {
|
|
|
|
const psc thisPosition = parentPosition + _position->position();
|
|
|
|
// check if camera is outside the node boundingsphere
|
|
if( ! _boundingSphereVisible) {
|
|
return;
|
|
}
|
|
if(_renderableVisible) {
|
|
_renderable->render(camera,thisPosition);
|
|
}
|
|
|
|
// evaluate all the children, tail-recursive function(?)
|
|
|
|
for(auto &child: _children) {
|
|
child->render(camera,thisPosition);
|
|
}
|
|
|
|
}
|
|
|
|
// set & get
|
|
void SceneGraphNode::addNode(SceneGraphNode *child) {
|
|
// add a child node and set this node to be the parent
|
|
|
|
child->setParent(this);
|
|
_children.push_back(child);
|
|
}
|
|
|
|
void SceneGraphNode::setName(const std::string &name) {
|
|
_nodeName = name;
|
|
}
|
|
|
|
void SceneGraphNode::setParent(SceneGraphNode *parent) {
|
|
_parent = parent;
|
|
}
|
|
|
|
const psc &SceneGraphNode::getPosition() const {
|
|
return _position->position();
|
|
}
|
|
|
|
psc SceneGraphNode::getWorldPosition() const {
|
|
|
|
// recursive up the hierarchy if there are parents available
|
|
if(_parent) {
|
|
return _position->position() + _parent->getWorldPosition();
|
|
} else {
|
|
return _position->position();
|
|
}
|
|
}
|
|
|
|
// bounding sphere
|
|
pss SceneGraphNode::calculateBoundingSphere() {
|
|
|
|
// set the vounding sphere to 0.0
|
|
_boundingSphere = 0.0;
|
|
|
|
if(_children.size() > 0) { // node
|
|
pss maxChild;
|
|
|
|
// loop though all children and find the one furthest away/with the largest bounding sphere
|
|
for(size_t i = 0; i < _children.size(); ++i) {
|
|
|
|
// when positions is dynamix, change this part to fins the most distant position
|
|
pss child = _children.at(i)->getPosition().length() +
|
|
_children.at(i)->calculateBoundingSphere();
|
|
if(child > maxChild) {
|
|
maxChild = child;
|
|
}
|
|
}
|
|
_boundingSphere += maxChild;
|
|
} else { // leaf
|
|
|
|
// if has a renderable, use that boundingsphere
|
|
if(_renderable)
|
|
_boundingSphere += _renderable->getBoundingSphere();
|
|
}
|
|
|
|
return _boundingSphere;
|
|
}
|
|
|
|
// renderable
|
|
void SceneGraphNode::setRenderable(Renderable *renderable) {
|
|
_renderable = renderable;
|
|
update();
|
|
}
|
|
|
|
const Renderable * SceneGraphNode::getRenderable() const{
|
|
return _renderable;
|
|
}
|
|
|
|
// private helper methods
|
|
bool SceneGraphNode::sphereInsideFrustum(const psc s_pos, const pss & s_rad, const Camera *camera) {
|
|
|
|
// direction the camera is looking at in power scale
|
|
psc psc_camdir = psc(camera->getViewDirection());
|
|
|
|
// the position of the camera, moved backwards in the view direction to encapsulate the sphere radius
|
|
psc U = camera->getPosition() - psc_camdir * s_rad * ( 1.0 / camera->getSinMaxFov());
|
|
|
|
// the vector to the object from the new position
|
|
psc D = s_pos - U;
|
|
|
|
const double a = psc_camdir.angle(D);
|
|
if ( a < camera->getMaxFov())
|
|
{
|
|
// center is inside K''
|
|
D = s_pos - camera->getPosition();
|
|
if ( D.length()* psc_camdir.length() *camera->getSinMaxFov() <= -psc_camdir.dot(D)) {
|
|
// center is inside K'' and inside K'
|
|
return D.length() <= s_rad;
|
|
} else {
|
|
// center is inside K'' and outside K'
|
|
return true;
|
|
}
|
|
} else {
|
|
// outside the maximum angle
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace openspace
|