assimp
[laserbrain_demo] / src / snode.cc
1 #include <float.h>
2 #include <assert.h>
3 #include <algorithm>
4 #include "snode.h"
5
6 SceneNode::SceneNode()
7         : scale(1, 1, 1)
8 {
9         parent = 0;
10         name = 0;
11 }
12
13 SceneNode::SceneNode(Object *obj)
14         : scale(1, 1, 1)
15 {
16         parent = 0;
17         name = 0;
18         add_object(obj);
19 }
20
21 SceneNode::~SceneNode()
22 {
23         delete [] name;
24 }
25
26 void SceneNode::set_name(const char *s)
27 {
28         delete [] name;
29         name = new char[strlen(s) + 1];
30         strcpy(name, s);
31 }
32
33 const char *SceneNode::get_name() const
34 {
35         return name;
36 }
37
38 void SceneNode::add_child(SceneNode *node)
39 {
40         if(node->parent) {
41                 if(node->parent == this) {
42                         return;
43                 }
44                 node->parent->remove_child(node);
45         }
46
47         children.push_back(node);
48         node->parent = this;
49 }
50
51 bool SceneNode::remove_child(SceneNode *node)
52 {
53         auto it = std::find(children.begin(), children.end(), node);
54         if(it != children.end()) {
55                 assert(node->parent == this);
56                 node->parent = 0;
57                 return true;
58         }
59         return false;
60 }
61
62 int SceneNode::get_num_children() const
63 {
64         return (int)children.size();
65 }
66
67 SceneNode *SceneNode::get_child(int idx) const
68 {
69         return children[idx];
70 }
71
72 SceneNode *SceneNode::get_parent() const
73 {
74         return parent;
75 }
76
77 void SceneNode::add_object(Object *obj)
78 {
79         if(obj->node == this) return;
80
81         if(obj->node) {
82                 obj->node->remove_object(obj);
83         }
84
85         this->obj.push_back(obj);
86         obj->node = this;
87 }
88
89 bool SceneNode::remove_object(Object *o)
90 {
91         if(o->node != this) {
92                 return false;
93         }
94         o->node = 0;
95
96         auto it = std::find(obj.begin(), obj.end(), o);
97         if(it == obj.end()) {
98                 return false;
99         }
100         obj.erase(it);
101         return true;
102 }
103
104 int SceneNode::get_num_objects() const
105 {
106         return (int)obj.size();
107 }
108
109 Object *SceneNode::get_object(int idx) const
110 {
111         return obj[idx];
112 }
113
114 void SceneNode::set_position(const Vec3 &pos)
115 {
116         this->pos = pos;
117 }
118
119 void SceneNode::set_rotation(const Quat &rot)
120 {
121         this->rot = rot;
122 }
123
124 void SceneNode::set_scaling(const Vec3 &scale)
125 {
126         this->scale = scale;
127 }
128
129
130 const Vec3 &SceneNode::get_node_position() const
131 {
132         return pos;
133 }
134
135 const Quat &SceneNode::get_node_rotation() const
136 {
137         return rot;
138 }
139
140 const Vec3 &SceneNode::get_node_scaling() const
141 {
142         return scale;
143 }
144
145
146 Vec3 SceneNode::get_position() const
147 {
148         return xform * Vec3(0, 0, 0);
149 }
150
151 Quat SceneNode::get_rotation() const
152 {
153         return rot;     // TODO
154 }
155
156 Vec3 SceneNode::get_scaling() const
157 {
158         return scale;   // TODO
159 }
160
161 const Mat4 &SceneNode::get_matrix() const
162 {
163         return xform;
164 }
165
166 const Mat4 &SceneNode::get_inv_matrix() const
167 {
168         return inv_xform;
169 }
170
171
172 void SceneNode::update_node(float dt)
173 {
174         xform = Mat4::identity;
175         xform.pre_translate(pos);
176         xform.pre_rotate(rot);
177         xform.pre_scale(scale);
178
179         if(parent) {
180                 xform = parent->xform * xform;
181         }
182         inv_xform = inverse(xform);
183 }
184
185 void SceneNode::update(float dt)
186 {
187         update_node(dt);
188
189         for(size_t i=0; i<children.size(); i++) {
190                 children[i]->update(dt);
191         }
192 }
193
194
195 bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const
196 {
197         Ray local_ray = inv_xform * ray;
198
199         HitPoint nearest;
200         nearest.dist = FLT_MAX;
201         for(size_t i=0; i<obj.size(); i++) {
202                 if(obj[i]->intersect(local_ray, hit)) {
203                         if(!hit) return true;
204                         if(hit->dist < nearest.dist) {
205                                 nearest = *hit;
206                                 nearest.data = (void*)this;
207                                 nearest.local_ray = local_ray;
208                         }
209                 }
210         }
211
212         for(size_t i=0; i<children.size(); i++) {
213                 if(children[i]->intersect(ray, hit)) {
214                         if(!hit) return true;
215                         if(hit->dist < nearest.dist) {
216                                 nearest = *hit;
217                         }
218                 }
219         }
220
221         if(nearest.dist < FLT_MAX) {
222                 *hit = nearest;
223                 hit->ray = ray;
224                 return true;
225         }
226         return false;
227 }