rev |
line source |
nuclear@3
|
1 #include <float.h>
|
nuclear@3
|
2 #include <assert.h>
|
nuclear@3
|
3 #include <algorithm>
|
nuclear@3
|
4 #include "snode.h"
|
nuclear@3
|
5
|
nuclear@3
|
6 SceneNode::SceneNode()
|
nuclear@3
|
7 : scale(1, 1, 1)
|
nuclear@3
|
8 {
|
nuclear@3
|
9 parent = 0;
|
nuclear@3
|
10 }
|
nuclear@3
|
11
|
nuclear@3
|
12 SceneNode::SceneNode(Object *obj)
|
nuclear@3
|
13 : scale(1, 1, 1)
|
nuclear@3
|
14 {
|
nuclear@3
|
15 parent = 0;
|
nuclear@3
|
16 add_object(obj);
|
nuclear@3
|
17 }
|
nuclear@3
|
18
|
nuclear@3
|
19 void SceneNode::add_child(SceneNode *node)
|
nuclear@3
|
20 {
|
nuclear@3
|
21 if(node->parent) {
|
nuclear@3
|
22 if(node->parent == this) {
|
nuclear@3
|
23 return;
|
nuclear@3
|
24 }
|
nuclear@3
|
25 node->parent->remove_child(node);
|
nuclear@3
|
26 }
|
nuclear@3
|
27
|
nuclear@3
|
28 children.push_back(node);
|
nuclear@3
|
29 node->parent = this;
|
nuclear@3
|
30 }
|
nuclear@3
|
31
|
nuclear@3
|
32 bool SceneNode::remove_child(SceneNode *node)
|
nuclear@3
|
33 {
|
nuclear@3
|
34 for(size_t i=0; i<children.size(); i++) {
|
nuclear@3
|
35 if(children[i] == node) {
|
nuclear@3
|
36 assert(node->parent == this);
|
nuclear@3
|
37 node->parent = 0;
|
nuclear@3
|
38 return true;
|
nuclear@3
|
39 }
|
nuclear@3
|
40 }
|
nuclear@3
|
41 return false;
|
nuclear@3
|
42 }
|
nuclear@3
|
43
|
nuclear@3
|
44 int SceneNode::get_num_children() const
|
nuclear@3
|
45 {
|
nuclear@3
|
46 return (int)children.size();
|
nuclear@3
|
47 }
|
nuclear@3
|
48
|
nuclear@3
|
49 SceneNode *SceneNode::get_child(int idx) const
|
nuclear@3
|
50 {
|
nuclear@3
|
51 return children[idx];
|
nuclear@3
|
52 }
|
nuclear@3
|
53
|
nuclear@3
|
54 SceneNode *SceneNode::get_parent() const
|
nuclear@3
|
55 {
|
nuclear@3
|
56 return parent;
|
nuclear@3
|
57 }
|
nuclear@3
|
58
|
nuclear@3
|
59 void SceneNode::add_object(Object *obj)
|
nuclear@3
|
60 {
|
nuclear@3
|
61 if(std::find(this->obj.begin(), this->obj.end(), obj) == this->obj.end()) {
|
nuclear@3
|
62 this->obj.push_back(obj);
|
nuclear@3
|
63 }
|
nuclear@3
|
64 }
|
nuclear@3
|
65
|
nuclear@3
|
66 int SceneNode::get_num_objects() const
|
nuclear@3
|
67 {
|
nuclear@3
|
68 return (int)obj.size();
|
nuclear@3
|
69 }
|
nuclear@3
|
70
|
nuclear@3
|
71 Object *SceneNode::get_object(int idx) const
|
nuclear@3
|
72 {
|
nuclear@3
|
73 return obj[idx];
|
nuclear@3
|
74 }
|
nuclear@3
|
75
|
nuclear@3
|
76 void SceneNode::set_position(const Vector3 &pos)
|
nuclear@3
|
77 {
|
nuclear@3
|
78 this->pos = pos;
|
nuclear@3
|
79 }
|
nuclear@3
|
80
|
nuclear@3
|
81 void SceneNode::set_rotation(const Quaternion &rot)
|
nuclear@3
|
82 {
|
nuclear@3
|
83 this->rot = rot;
|
nuclear@3
|
84 }
|
nuclear@3
|
85
|
nuclear@3
|
86 void SceneNode::set_scaling(const Vector3 &scale)
|
nuclear@3
|
87 {
|
nuclear@3
|
88 this->scale = scale;
|
nuclear@3
|
89 }
|
nuclear@3
|
90
|
nuclear@3
|
91
|
nuclear@3
|
92 const Vector3 &SceneNode::get_node_position() const
|
nuclear@3
|
93 {
|
nuclear@3
|
94 return pos;
|
nuclear@3
|
95 }
|
nuclear@3
|
96
|
nuclear@3
|
97 const Quaternion &SceneNode::get_node_rotation() const
|
nuclear@3
|
98 {
|
nuclear@3
|
99 return rot;
|
nuclear@3
|
100 }
|
nuclear@3
|
101
|
nuclear@3
|
102 const Vector3 &SceneNode::get_node_scaling() const
|
nuclear@3
|
103 {
|
nuclear@3
|
104 return scale;
|
nuclear@3
|
105 }
|
nuclear@3
|
106
|
nuclear@3
|
107
|
nuclear@3
|
108 Vector3 SceneNode::get_position() const
|
nuclear@3
|
109 {
|
nuclear@3
|
110 return Vector3(0, 0, 0).transformed(xform);
|
nuclear@3
|
111 }
|
nuclear@3
|
112
|
nuclear@3
|
113 Quaternion SceneNode::get_rotation() const
|
nuclear@3
|
114 {
|
nuclear@3
|
115 return rot; // TODO
|
nuclear@3
|
116 }
|
nuclear@3
|
117
|
nuclear@3
|
118 Vector3 SceneNode::get_scaling() const
|
nuclear@3
|
119 {
|
nuclear@3
|
120 return scale; // TODO
|
nuclear@3
|
121 }
|
nuclear@3
|
122
|
nuclear@3
|
123 const Matrix4x4 &SceneNode::get_matrix() const
|
nuclear@3
|
124 {
|
nuclear@3
|
125 return xform;
|
nuclear@3
|
126 }
|
nuclear@3
|
127
|
nuclear@3
|
128 const Matrix4x4 &SceneNode::get_inv_matrix() const
|
nuclear@3
|
129 {
|
nuclear@3
|
130 return inv_xform;
|
nuclear@3
|
131 }
|
nuclear@3
|
132
|
nuclear@3
|
133
|
nuclear@3
|
134 void SceneNode::update_node(long msec)
|
nuclear@3
|
135 {
|
nuclear@3
|
136 xform.reset_identity();
|
nuclear@3
|
137 xform.translate(pos);
|
nuclear@3
|
138 xform.rotate(rot);
|
nuclear@3
|
139 xform.scale(scale);
|
nuclear@3
|
140
|
nuclear@3
|
141 if(parent) {
|
nuclear@3
|
142 xform = parent->xform * xform;
|
nuclear@3
|
143 }
|
nuclear@3
|
144 inv_xform = xform.inverse();
|
nuclear@3
|
145 }
|
nuclear@3
|
146
|
nuclear@3
|
147 void SceneNode::update(long msec)
|
nuclear@3
|
148 {
|
nuclear@3
|
149 update_node(msec);
|
nuclear@3
|
150
|
nuclear@3
|
151 for(size_t i=0; i<children.size(); i++) {
|
nuclear@3
|
152 children[i]->update(msec);
|
nuclear@3
|
153 }
|
nuclear@3
|
154 }
|
nuclear@3
|
155
|
nuclear@3
|
156
|
nuclear@3
|
157 bool SceneNode::intersect(const Ray &ray, HitPoint *hit) const
|
nuclear@3
|
158 {
|
nuclear@3
|
159 Ray local_ray = ray.transformed(inv_xform);
|
nuclear@3
|
160
|
nuclear@3
|
161 HitPoint nearest;
|
nuclear@3
|
162 nearest.dist = FLT_MAX;
|
nuclear@3
|
163 for(size_t i=0; i<obj.size(); i++) {
|
nuclear@3
|
164 if(obj[i]->intersect(local_ray, hit)) {
|
nuclear@3
|
165 if(!hit) return true;
|
nuclear@3
|
166 if(hit->dist < nearest.dist) {
|
nuclear@3
|
167 nearest = *hit;
|
nuclear@3
|
168 nearest.node = this;
|
nuclear@3
|
169 }
|
nuclear@3
|
170 }
|
nuclear@3
|
171 }
|
nuclear@3
|
172
|
nuclear@3
|
173 for(size_t i=0; i<children.size(); i++) {
|
nuclear@3
|
174 if(children[i]->intersect(ray, hit)) {
|
nuclear@3
|
175 if(!hit) return true;
|
nuclear@3
|
176 if(hit->dist < nearest.dist) {
|
nuclear@3
|
177 nearest = *hit;
|
nuclear@3
|
178 }
|
nuclear@3
|
179 }
|
nuclear@3
|
180 }
|
nuclear@3
|
181
|
nuclear@3
|
182 if(nearest.dist < FLT_MAX) {
|
nuclear@3
|
183 *hit = nearest;
|
nuclear@3
|
184 hit->ray = ray;
|
nuclear@3
|
185 return true;
|
nuclear@3
|
186 }
|
nuclear@3
|
187 return false;
|
nuclear@3
|
188 }
|