rev |
line source |
nuclear@5
|
1 #include <string.h>
|
nuclear@17
|
2 #include <float.h>
|
nuclear@1
|
3 #include "scene.h"
|
nuclear@12
|
4 #include "min3d.h"
|
nuclear@1
|
5
|
nuclear@1
|
6 Scene::Scene()
|
nuclear@1
|
7 {
|
nuclear@1
|
8 name = 0;
|
nuclear@6
|
9 active_cam = 0;
|
nuclear@17
|
10
|
nuclear@17
|
11 fog_exp = 1.0;
|
nuclear@17
|
12
|
nuclear@17
|
13 set_ambient(Vector3(0.05, 0.05, 0.05));
|
nuclear@17
|
14
|
nuclear@17
|
15 set_background(Vector3(0.4, 0.3, 0.05), SCN_BG_LOW);
|
nuclear@17
|
16 set_background(Vector3(0.6, 0.6, 0.6), SCN_BG_MID);
|
nuclear@17
|
17 set_background(Vector3(0.1, 0.5, 1.0), SCN_BG_HIGH);
|
nuclear@1
|
18 }
|
nuclear@1
|
19
|
nuclear@1
|
20 Scene::~Scene()
|
nuclear@1
|
21 {
|
nuclear@1
|
22 clear();
|
nuclear@1
|
23 }
|
nuclear@1
|
24
|
nuclear@1
|
25 void Scene::clear()
|
nuclear@1
|
26 {
|
nuclear@1
|
27 delete [] name;
|
nuclear@1
|
28
|
nuclear@1
|
29 size_t i;
|
nuclear@1
|
30 for(i=0; i<objects.size(); i++) {
|
nuclear@1
|
31 delete objects[i];
|
nuclear@1
|
32 }
|
nuclear@1
|
33 for(i=0; i<lights.size(); i++) {
|
nuclear@1
|
34 delete lights[i];
|
nuclear@1
|
35 }
|
nuclear@1
|
36 for(i=0; i<cameras.size(); i++) {
|
nuclear@1
|
37 delete cameras[i];
|
nuclear@1
|
38 }
|
nuclear@1
|
39 }
|
nuclear@1
|
40
|
nuclear@1
|
41 void Scene::set_name(const char *name)
|
nuclear@1
|
42 {
|
nuclear@1
|
43 delete [] this->name;
|
nuclear@1
|
44 this->name = new char[strlen(name) + 1];
|
nuclear@1
|
45 strcpy(this->name, name);
|
nuclear@1
|
46 }
|
nuclear@1
|
47
|
nuclear@1
|
48 const char *Scene::get_name() const
|
nuclear@1
|
49 {
|
nuclear@1
|
50 return name ? name : "<unknown>";
|
nuclear@1
|
51 }
|
nuclear@1
|
52
|
nuclear@17
|
53 void Scene::set_background(const Vector3 &col, int idx)
|
nuclear@17
|
54 {
|
nuclear@17
|
55 if(idx == -1) {
|
nuclear@17
|
56 bg[0] = bg[1] = bg[2] = col;
|
nuclear@17
|
57 } else {
|
nuclear@17
|
58 bg[idx] = col;
|
nuclear@17
|
59 }
|
nuclear@17
|
60 }
|
nuclear@17
|
61
|
nuclear@17
|
62 const Vector3 &Scene::get_background(int idx) const
|
nuclear@17
|
63 {
|
nuclear@17
|
64 return bg[idx == -1 ? 0 : idx];
|
nuclear@17
|
65 }
|
nuclear@17
|
66
|
nuclear@17
|
67 #define LERP(a, b, t) ((a) + ((b) - (a)) * t)
|
nuclear@17
|
68
|
nuclear@17
|
69 Vector3 Scene::get_background(const Ray &ray) const
|
nuclear@17
|
70 {
|
nuclear@17
|
71 Vector3 dir = normalize(ray.dir);
|
nuclear@17
|
72
|
nuclear@17
|
73 float v;
|
nuclear@17
|
74 if(dir.z == 0.0) {
|
nuclear@17
|
75 v = dir.y > 0.0 ? 1.0 : -1.0;
|
nuclear@17
|
76 } else {
|
nuclear@17
|
77 float angle = atan2(dir.z, dir.y);
|
nuclear@17
|
78 v = angle / M_PI;
|
nuclear@17
|
79 }
|
nuclear@17
|
80
|
nuclear@17
|
81 float r = v >= 0.0 ? LERP(bg[1].x, bg[2].x, v) : LERP(bg[1].x, bg[0].x, -v);
|
nuclear@17
|
82 float g = v >= 0.0 ? LERP(bg[1].y, bg[2].y, v) : LERP(bg[1].y, bg[0].y, -v);
|
nuclear@17
|
83 float b = v >= 0.0 ? LERP(bg[1].z, bg[2].z, v) : LERP(bg[1].z, bg[0].z, -v);
|
nuclear@17
|
84 return Vector3(r, g, b);
|
nuclear@17
|
85 }
|
nuclear@17
|
86
|
nuclear@17
|
87 void Scene::set_ambient(const Vector3 &col)
|
nuclear@17
|
88 {
|
nuclear@17
|
89 ambient = col;
|
nuclear@17
|
90 }
|
nuclear@17
|
91
|
nuclear@17
|
92 const Vector3 &Scene::get_ambient() const
|
nuclear@17
|
93 {
|
nuclear@17
|
94 return ambient;
|
nuclear@17
|
95 }
|
nuclear@17
|
96
|
nuclear@17
|
97
|
nuclear@12
|
98 void Scene::add(SceneNode *node)
|
nuclear@6
|
99 {
|
nuclear@12
|
100 nodes.push_back(node);
|
nuclear@12
|
101
|
nuclear@12
|
102 switch(node->get_type()) {
|
nuclear@12
|
103 case NODE_OBJECT:
|
nuclear@12
|
104 objects.push_back((Object*)node);
|
nuclear@12
|
105 break;
|
nuclear@12
|
106
|
nuclear@12
|
107 case NODE_LIGHT:
|
nuclear@12
|
108 lights.push_back((Light*)node);
|
nuclear@12
|
109 break;
|
nuclear@12
|
110
|
nuclear@12
|
111 case NODE_CAMERA:
|
nuclear@12
|
112 cameras.push_back((Camera*)node);
|
nuclear@12
|
113 break;
|
nuclear@12
|
114
|
nuclear@12
|
115 default:
|
nuclear@12
|
116 break;
|
nuclear@12
|
117 }
|
nuclear@12
|
118
|
nuclear@12
|
119 sel.clear();
|
nuclear@6
|
120 }
|
nuclear@6
|
121
|
nuclear@12
|
122 int Scene::get_node_count() const
|
nuclear@6
|
123 {
|
nuclear@12
|
124 return (int)nodes.size();
|
nuclear@6
|
125 }
|
nuclear@6
|
126
|
nuclear@6
|
127 int Scene::get_object_count() const
|
nuclear@6
|
128 {
|
nuclear@6
|
129 return (int)objects.size();
|
nuclear@6
|
130 }
|
nuclear@6
|
131
|
nuclear@6
|
132 int Scene::get_light_count() const
|
nuclear@6
|
133 {
|
nuclear@6
|
134 return (int)lights.size();
|
nuclear@6
|
135 }
|
nuclear@6
|
136
|
nuclear@6
|
137 int Scene::get_camera_count() const
|
nuclear@6
|
138 {
|
nuclear@6
|
139 return (int)cameras.size();
|
nuclear@6
|
140 }
|
nuclear@6
|
141
|
nuclear@12
|
142 SceneNode *Scene::get_node(int idx)
|
nuclear@12
|
143 {
|
nuclear@12
|
144 return nodes[idx];
|
nuclear@12
|
145 }
|
nuclear@12
|
146
|
nuclear@12
|
147 const SceneNode *Scene::get_node(int idx) const
|
nuclear@12
|
148 {
|
nuclear@12
|
149 return nodes[idx];
|
nuclear@12
|
150 }
|
nuclear@6
|
151
|
nuclear@6
|
152 Object *Scene::get_object(int idx)
|
nuclear@6
|
153 {
|
nuclear@6
|
154 return objects[idx];
|
nuclear@6
|
155 }
|
nuclear@6
|
156
|
nuclear@6
|
157 const Object *Scene::get_object(int idx) const
|
nuclear@6
|
158 {
|
nuclear@6
|
159 return objects[idx];
|
nuclear@6
|
160 }
|
nuclear@6
|
161
|
nuclear@6
|
162 Light *Scene::get_light(int idx)
|
nuclear@6
|
163 {
|
nuclear@6
|
164 return lights[idx];
|
nuclear@6
|
165 }
|
nuclear@6
|
166
|
nuclear@6
|
167 const Light *Scene::get_light(int idx) const
|
nuclear@6
|
168 {
|
nuclear@6
|
169 return lights[idx];
|
nuclear@6
|
170 }
|
nuclear@6
|
171
|
nuclear@6
|
172 Camera *Scene::get_camera(int idx)
|
nuclear@6
|
173 {
|
nuclear@6
|
174 return cameras[idx];
|
nuclear@6
|
175 }
|
nuclear@6
|
176
|
nuclear@6
|
177 const Camera *Scene::get_camera(int idx) const
|
nuclear@6
|
178 {
|
nuclear@6
|
179 return cameras[idx];
|
nuclear@6
|
180 }
|
nuclear@6
|
181
|
nuclear@15
|
182 void Scene::set_active_camera(Camera *cam)
|
nuclear@15
|
183 {
|
nuclear@15
|
184 active_cam = cam;
|
nuclear@15
|
185 }
|
nuclear@15
|
186
|
nuclear@15
|
187 Camera *Scene::get_active_camera() const
|
nuclear@15
|
188 {
|
nuclear@15
|
189 return active_cam;
|
nuclear@15
|
190 }
|
nuclear@15
|
191
|
nuclear@1
|
192 void Scene::draw() const
|
nuclear@1
|
193 {
|
nuclear@6
|
194 if(active_cam) {
|
nuclear@6
|
195 // TODO
|
nuclear@6
|
196 }
|
nuclear@6
|
197
|
nuclear@12
|
198 int num_nodes = get_node_count();
|
nuclear@12
|
199 for(int i=0; i<num_nodes; i++) {
|
nuclear@12
|
200 bool selected = false;
|
nuclear@12
|
201
|
nuclear@12
|
202 for(size_t j=0; j<sel.size(); j++) {
|
nuclear@12
|
203 if(sel[j] == i) {
|
nuclear@12
|
204 selected = true;
|
nuclear@12
|
205 break;
|
nuclear@12
|
206 }
|
nuclear@12
|
207 }
|
nuclear@12
|
208
|
nuclear@14
|
209 nodes[i]->draw(selected);
|
nuclear@6
|
210 }
|
nuclear@1
|
211 }
|
nuclear@12
|
212
|
nuclear@12
|
213 void Scene::select(int s)
|
nuclear@12
|
214 {
|
nuclear@12
|
215 for(size_t i=0; i<sel.size(); i++) {
|
nuclear@12
|
216 if(sel[i] == s) {
|
nuclear@12
|
217 return;
|
nuclear@12
|
218 }
|
nuclear@12
|
219 }
|
nuclear@12
|
220 sel.push_back(s);
|
nuclear@12
|
221 }
|
nuclear@12
|
222
|
nuclear@12
|
223 void Scene::clear_selection()
|
nuclear@12
|
224 {
|
nuclear@12
|
225 sel.clear();
|
nuclear@12
|
226 }
|
nuclear@12
|
227
|
nuclear@12
|
228 int Scene::get_selection_count() const
|
nuclear@12
|
229 {
|
nuclear@12
|
230 return (int)sel.size();
|
nuclear@12
|
231 }
|
nuclear@12
|
232
|
nuclear@12
|
233 int Scene::get_selection(int idx) const
|
nuclear@12
|
234 {
|
nuclear@12
|
235 return idx >= 0 && idx < (int)sel.size() ? sel[idx] : -1;
|
nuclear@12
|
236 }
|
nuclear@17
|
237
|
nuclear@17
|
238 bool Scene::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@17
|
239 {
|
nuclear@17
|
240 if(hit) {
|
nuclear@17
|
241 hit->dist = FLT_MAX;
|
nuclear@17
|
242 hit->obj = 0;
|
nuclear@17
|
243 }
|
nuclear@17
|
244
|
nuclear@17
|
245 int num_obj = (int)objects.size();
|
nuclear@17
|
246 for(int i=0; i<num_obj; i++) {
|
nuclear@17
|
247 RayHit tmphit;
|
nuclear@17
|
248 if(objects[i]->intersect(ray, hit ? &tmphit : 0)) {
|
nuclear@17
|
249 if(!hit) return true;
|
nuclear@17
|
250 if(tmphit.dist < hit->dist) {
|
nuclear@17
|
251 *hit = tmphit;
|
nuclear@17
|
252 }
|
nuclear@17
|
253 }
|
nuclear@17
|
254 }
|
nuclear@17
|
255 return hit && hit->obj;
|
nuclear@17
|
256 }
|