X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=laserbrain_demo;a=blobdiff_plain;f=src%2Fsnode.cc;fp=src%2Fsnode.cc;h=fac6c650b9c7e69b29d410bff6e7e29a9a5b38e1;hp=0000000000000000000000000000000000000000;hb=b7c92831285013b2a0783bccaf3d900545ebb5ba;hpb=a58455a92c7ecab980cbe1b7e282aeb6bfe7e889 diff --git a/src/snode.cc b/src/snode.cc new file mode 100644 index 0000000..fac6c65 --- /dev/null +++ b/src/snode.cc @@ -0,0 +1,227 @@ +#include +#include +#include +#include "snode.h" + +SceneNode::SceneNode() + : scale(1, 1, 1) +{ + parent = 0; + name = 0; +} + +SceneNode::SceneNode(Object *obj) + : scale(1, 1, 1) +{ + parent = 0; + name = 0; + add_object(obj); +} + +SceneNode::~SceneNode() +{ + delete [] name; +} + +void SceneNode::set_name(const char *s) +{ + delete [] name; + name = new char[strlen(s) + 1]; + strcpy(name, s); +} + +const char *SceneNode::get_name() const +{ + return name; +} + +void SceneNode::add_child(SceneNode *node) +{ + if(node->parent) { + if(node->parent == this) { + return; + } + node->parent->remove_child(node); + } + + children.push_back(node); + node->parent = this; +} + +bool SceneNode::remove_child(SceneNode *node) +{ + auto it = std::find(children.begin(), children.end(), node); + if(it != children.end()) { + assert(node->parent == this); + node->parent = 0; + return true; + } + return false; +} + +int SceneNode::get_num_children() const +{ + return (int)children.size(); +} + +SceneNode *SceneNode::get_child(int idx) const +{ + return children[idx]; +} + +SceneNode *SceneNode::get_parent() const +{ + return parent; +} + +void SceneNode::add_object(Object *obj) +{ + if(obj->node == this) return; + + if(obj->node) { + obj->node->remove_object(obj); + } + + this->obj.push_back(obj); + obj->node = this; +} + +bool SceneNode::remove_object(Object *o) +{ + if(o->node != this) { + return false; + } + o->node = 0; + + auto it = std::find(obj.begin(), obj.end(), o); + if(it == obj.end()) { + return false; + } + obj.erase(it); + return true; +} + +int SceneNode::get_num_objects() const +{ + return (int)obj.size(); +} + +Object *SceneNode::get_object(int idx) const +{ + return obj[idx]; +} + +void SceneNode::set_position(const Vec3 &pos) +{ + this->pos = pos; +} + +void SceneNode::set_rotation(const Quat &rot) +{ + this->rot = rot; +} + +void SceneNode::set_scaling(const Vec3 &scale) +{ + this->scale = scale; +} + + +const Vec3 &SceneNode::get_node_position() const +{ + return pos; +} + +const Quat &SceneNode::get_node_rotation() const +{ + return rot; +} + +const Vec3 &SceneNode::get_node_scaling() const +{ + return scale; +} + + +Vec3 SceneNode::get_position() const +{ + return xform * Vec3(0, 0, 0); +} + +Quat SceneNode::get_rotation() const +{ + return rot; // TODO +} + +Vec3 SceneNode::get_scaling() const +{ + return scale; // TODO +} + +const Mat4 &SceneNode::get_matrix() const +{ + return xform; +} + +const Mat4 &SceneNode::get_inv_matrix() const +{ + return inv_xform; +} + + +void SceneNode::update_node(float dt) +{ + xform = Mat4::identity; + xform.pre_translate(pos); + xform.pre_rotate(rot); + xform.pre_scale(scale); + + if(parent) { + xform = parent->xform * xform; + } + inv_xform = inverse(xform); +} + +void SceneNode::update(float dt) +{ + update_node(dt); + + for(size_t i=0; iupdate(dt); + } +} + + +bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const +{ + Ray local_ray = inv_xform * ray; + + HitPoint nearest; + nearest.dist = FLT_MAX; + for(size_t i=0; iintersect(local_ray, hit)) { + if(!hit) return true; + if(hit->dist < nearest.dist) { + nearest = *hit; + nearest.data = (void*)this; + nearest.local_ray = local_ray; + } + } + } + + for(size_t i=0; iintersect(ray, hit)) { + if(!hit) return true; + if(hit->dist < nearest.dist) { + nearest = *hit; + } + } + } + + if(nearest.dist < FLT_MAX) { + *hit = nearest; + hit->ray = ray; + return true; + } + return false; +}