mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-20 03:00:03 -06:00
258 lines
6.6 KiB
C++
258 lines
6.6 KiB
C++
|
|
// open space includes
|
|
#include "scenegraph/scenegraphnode.h"
|
|
#include "util/spice.h"
|
|
|
|
// ghoul includes
|
|
#include "ghoul/logging/logmanager.h"
|
|
#include "ghoul/logging/consolelog.h"
|
|
|
|
namespace openspace {
|
|
|
|
SceneGraphNode::SceneGraphNode() {
|
|
|
|
nodeName_ = "";
|
|
|
|
// init pointers with nullptr
|
|
renderable_ = nullptr;
|
|
parent_ = nullptr;
|
|
boundingSphereVisible_ = false;
|
|
renderableVisible_ = false;
|
|
|
|
// spice not used when spiceID_ is 0, 0 is the sun barycenter
|
|
spiceID_ = 0;
|
|
parentSpiceID_ = 0;
|
|
}
|
|
|
|
SceneGraphNode::~SceneGraphNode() {
|
|
// logger string
|
|
std::string _loggerCat = "SceneGraphNode::~SceneGraphNode()";
|
|
LDEBUG("Deallocating: " << nodeName_);
|
|
|
|
// deallocate the renderable
|
|
if(renderable_)
|
|
delete renderable_;
|
|
|
|
// deallocate the child nodes and delete them, iterate c++11 style
|
|
for( auto &child: children_) {
|
|
delete child;
|
|
}
|
|
|
|
// empty the vector
|
|
children_.erase (children_.begin(),children_.end());
|
|
}
|
|
|
|
// essential
|
|
void SceneGraphNode::update() {
|
|
|
|
if(spiceID_ > 0) {
|
|
double state[3];
|
|
//double orientation[3][3];
|
|
Spice::ref().spk_getPosition(spiceID_, parentSpiceID_, state);
|
|
|
|
// multiply with factor 1000, spice uses km as standard and Open Space uses m
|
|
position_ = psc::CreatePSC(state[0]*1000.0,state[1]*1000.0,state[2]*1000.0);
|
|
|
|
// update rotation
|
|
//if(Spice::ref().spk_getOrientation(spiceName_,orientation)) {
|
|
// printf("%s\n",spiceName_);
|
|
// printf("%.5f %.5f %.5f \n", orientation[0][0], orientation[0][1], orientation[0][2]);
|
|
// printf("%.5f %.5f %.5f \n", orientation[1][0], orientation[1][1], orientation[1][2]);
|
|
// printf("%.5f %.5f %.5f \n", orientation[2][0], orientation[2][1], orientation[2][2]);
|
|
//}
|
|
}
|
|
|
|
if(renderable_) {
|
|
renderable_->update();
|
|
}
|
|
}
|
|
|
|
void SceneGraphNode::evaluate(const Camera *camera, const psc & parentPosition) {
|
|
|
|
const psc thisPosition = parentPosition + position_;
|
|
const psc camPos = camera->getPosition();
|
|
const psc toCamera = thisPosition - camPos;
|
|
|
|
// init as not visible
|
|
boundingSphereVisible_ = true;
|
|
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;
|
|
}
|
|
|
|
}
|
|
boundingSphereVisible_ = true;
|
|
// inside boudningsphere or parts of the sphere is visible, individual children needs to be evaluated
|
|
|
|
// 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,thisPosition);
|
|
}
|
|
|
|
}
|
|
|
|
void SceneGraphNode::render(const Camera *camera, const psc & parentPosition) {
|
|
|
|
const psc thisPosition = parentPosition + position_;
|
|
|
|
// check if camera is outside the node boundingsphere
|
|
if( ! boundingSphereVisible_) {
|
|
return;
|
|
}
|
|
if(renderableVisible_) {
|
|
if (nodeName_ == "earth")
|
|
nodeName_ = nodeName_;
|
|
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;
|
|
}
|
|
|
|
void SceneGraphNode::setPosition(const psc &position) {
|
|
position_ = position;
|
|
}
|
|
|
|
void SceneGraphNode::setSpiceID(const int spiceID, const int parentSpiceID) {
|
|
spiceID_ = spiceID;
|
|
parentSpiceID_ = parentSpiceID;
|
|
update();
|
|
}
|
|
|
|
void SceneGraphNode::setSpiceName(const std::string &name) {
|
|
spiceName_ = name;
|
|
}
|
|
|
|
const int SceneGraphNode::getSpiceID() const {
|
|
return spiceID_;
|
|
}
|
|
|
|
const std::string & SceneGraphNode::getSpiceName() {
|
|
return spiceName_;
|
|
}
|
|
|
|
const psc &SceneGraphNode::getPosition() const {
|
|
return position_;
|
|
}
|
|
|
|
psc SceneGraphNode::getWorldPosition() const {
|
|
|
|
// recursive up the hierarchy if there are parents available
|
|
if(parent_) {
|
|
return position_ + parent_->getWorldPosition();
|
|
} else {
|
|
return 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;
|
|
|
|
// check if outside the maximum angle
|
|
if (nodeName_ == "earth") {
|
|
//psc tmp = s_pos - camera->getPosition();
|
|
|
|
//LINFOC("", "Angle: " << psc_camdir.angle(D));
|
|
//LINFOC("", "Pos: " << tmp.getVec4f()[0] << " " << tmp.getVec4f()[1] << " " << tmp.getVec4f()[2] << " " << tmp.getVec4f()[3]);
|
|
}
|
|
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
|