erebus
view liberebus/src/snode.cc @ 21:e49f4d7ad04c
started adding BRDFs
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 28 May 2014 07:06:29 +0300 |
parents | e2d9bf168a41 |
children | c4d48a21bc4a |
line source
1 #include <float.h>
2 #include <assert.h>
3 #include <algorithm>
4 #include "snode.h"
6 SceneNode::SceneNode()
7 : scale(1, 1, 1)
8 {
9 parent = 0;
10 }
12 SceneNode::SceneNode(Object *obj)
13 : scale(1, 1, 1)
14 {
15 parent = 0;
16 add_object(obj);
17 }
19 void SceneNode::add_child(SceneNode *node)
20 {
21 if(node->parent) {
22 if(node->parent == this) {
23 return;
24 }
25 node->parent->remove_child(node);
26 }
28 children.push_back(node);
29 node->parent = this;
30 }
32 bool SceneNode::remove_child(SceneNode *node)
33 {
34 auto it = std::find(children.begin(), children.end(), node);
35 if(it != children.end()) {
36 assert(node->parent == this);
37 node->parent = 0;
38 return true;
39 }
40 return false;
41 }
43 int SceneNode::get_num_children() const
44 {
45 return (int)children.size();
46 }
48 SceneNode *SceneNode::get_child(int idx) const
49 {
50 return children[idx];
51 }
53 SceneNode *SceneNode::get_parent() const
54 {
55 return parent;
56 }
58 void SceneNode::add_object(Object *obj)
59 {
60 if(std::find(this->obj.begin(), this->obj.end(), obj) == this->obj.end()) {
61 this->obj.push_back(obj);
62 }
63 }
65 int SceneNode::get_num_objects() const
66 {
67 return (int)obj.size();
68 }
70 Object *SceneNode::get_object(int idx) const
71 {
72 return obj[idx];
73 }
75 void SceneNode::set_position(const Vector3 &pos)
76 {
77 this->pos = pos;
78 }
80 void SceneNode::set_rotation(const Quaternion &rot)
81 {
82 this->rot = rot;
83 }
85 void SceneNode::set_scaling(const Vector3 &scale)
86 {
87 this->scale = scale;
88 }
91 const Vector3 &SceneNode::get_node_position() const
92 {
93 return pos;
94 }
96 const Quaternion &SceneNode::get_node_rotation() const
97 {
98 return rot;
99 }
101 const Vector3 &SceneNode::get_node_scaling() const
102 {
103 return scale;
104 }
107 Vector3 SceneNode::get_position() const
108 {
109 return Vector3{0, 0, 0}.transformed(xform);
110 }
112 Quaternion SceneNode::get_rotation() const
113 {
114 return rot; // TODO
115 }
117 Vector3 SceneNode::get_scaling() const
118 {
119 return scale; // TODO
120 }
122 const Matrix4x4 &SceneNode::get_matrix() const
123 {
124 return xform;
125 }
127 const Matrix4x4 &SceneNode::get_inv_matrix() const
128 {
129 return inv_xform;
130 }
133 void SceneNode::update_node(long msec)
134 {
135 xform.reset_identity();
136 xform.translate(pos);
137 xform.rotate(rot);
138 xform.scale(scale);
140 if(parent) {
141 xform = parent->xform * xform;
142 }
143 inv_xform = xform.inverse();
144 }
146 void SceneNode::update(long msec)
147 {
148 update_node(msec);
150 for(size_t i=0; i<children.size(); i++) {
151 children[i]->update(msec);
152 }
153 }
156 bool SceneNode::intersect(const Ray &ray, RayHit *hit) const
157 {
158 Ray local_ray = ray.transformed(inv_xform);
160 RayHit nearest;
161 nearest.dist = FLT_MAX;
162 for(size_t i=0; i<obj.size(); i++) {
163 if(obj[i]->intersect(local_ray, hit)) {
164 if(!hit) return true;
165 if(hit->dist < nearest.dist) {
166 nearest = *hit;
167 nearest.node = this;
168 nearest.local_ray = local_ray;
169 }
170 }
171 }
173 for(size_t i=0; i<children.size(); i++) {
174 if(children[i]->intersect(ray, hit)) {
175 if(!hit) return true;
176 if(hit->dist < nearest.dist) {
177 nearest = *hit;
178 }
179 }
180 }
182 if(nearest.dist < FLT_MAX) {
183 *hit = nearest;
184 hit->world_ray = ray;
185 return true;
186 }
187 return false;
188 }