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