erebus

view liberebus/src/scene.cc @ 19:6204e4d3f445

scene loading
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 27 May 2014 07:43:55 +0300
parents e2d9bf168a41
children ea95b62dbc87
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "scene.h"
5 #include "snode.h"
6 #include "object.h"
7 #include "geomobj.h"
9 // default enviromental parameters
10 Environment::Environment()
11 : bgcolor(0.01, 0.01, 0.01), ambient(0.01, 0.01, 0.01)
12 {
13 }
15 Scene::Scene()
16 {
17 active_cam = 0;
18 root = new SceneNode;
19 }
21 Scene::~Scene()
22 {
23 for(auto obj : objects) {
24 delete obj;
25 }
26 for(auto node : nodes) {
27 delete node;
28 }
29 delete root;
30 }
32 void Scene::set_env(const Environment &env)
33 {
34 this->env = env;
35 }
37 Environment &Scene::get_env()
38 {
39 return env;
40 }
42 const Environment &Scene::get_env() const
43 {
44 return env;
45 }
47 Color Scene::get_env_color() const
48 {
49 return env.bgcolor;
50 }
52 Color Scene::get_env_color(const Ray &ray) const
53 {
54 // TODO
55 return get_env_color();
56 }
58 void Scene::add_object(Object *obj)
59 {
60 objects.push_back(obj);
61 }
63 int Scene::get_object_count() const
64 {
65 return (int)objects.size();
66 }
68 Object *Scene::get_object(int idx) const
69 {
70 return objects[idx];
71 }
73 void Scene::add_node(SceneNode *node)
74 {
75 nodes.push_back(node);
77 if(!node->get_parent()) {
78 root->add_child(node);
79 }
80 }
82 int Scene::get_node_count() const
83 {
84 return (int)nodes.size();
85 }
87 SceneNode *Scene::get_node(int idx) const
88 {
89 return nodes[idx];
90 }
92 void Scene::use_camera(Camera *cam)
93 {
94 active_cam = cam;
95 }
97 Camera *Scene::get_active_camera() const
98 {
99 return active_cam;
100 }
102 void Scene::update(long msec)
103 {
104 root->update(msec);
105 }
107 bool Scene::intersect(const Ray &ray, RayHit *hit) const
108 {
109 return root->intersect(ray, hit);
110 }
112 bool Scene::load(const char *fname)
113 {
114 FILE *fp = fopen(fname, "r");
115 if(!fp) {
116 fprintf(stderr, "failed to open scene file: %s\n", fname);
117 return false;
118 }
120 bool res = load(fp);
121 fclose(fp);
122 return res;
123 }
125 static char *strip_wspace(char *str)
126 {
127 while(*str && isspace(*str)) str++;
128 return str;
129 }
131 bool Scene::load(FILE *fp)
132 {
133 char buf[256];
135 while(fgets(buf, sizeof buf, fp)) {
136 char *line = strip_wspace(buf);
137 if(!line || !*line || *line == '#') {
138 continue;
139 }
141 std::vector<char*> cmd;
143 char *tok = 0;
144 while((tok = strtok(tok ? 0 : line, " \t\v\n\r"))) {
145 printf("token: %s\n", tok);
146 cmd.push_back(tok);
147 }
148 cmd.push_back(0);
151 if(!proc_cmd((int)cmd.size() - 1, &cmd[0])) {
152 return false;
153 }
154 }
156 return true;
157 }
159 static int parse_vec(char **argv, float *vec)
160 {
161 int nelem = 0;
162 char *endp;
164 for(int i=0; i<4; i++) {
165 if(!argv[i]) break;
167 vec[nelem] = strtod(argv[i], &endp);
168 if(endp == argv[i]) {
169 break;
170 }
171 nelem++;
172 }
173 return nelem;
174 }
176 static SceneNode *proc_object(Object *obj, int argc, char **argv)
177 {
178 float vec[4];
179 SceneNode *node = new SceneNode(obj);
180 GeomObject *gobj = (GeomObject*)obj;
182 for(int i=1; i<argc; i++) {
183 if(strcmp(argv[i], "-position") == 0) {
184 int nelem = parse_vec(argv + i + 1, vec);
185 if(nelem < 3) {
186 fprintf(stderr, "-position must be followed by 3 numbers\n");
187 goto err;
188 }
189 node->set_position(Vector3(vec[0], vec[1], vec[2]));
190 i += 3;
192 } else if(strcmp(argv[i], "-rotation") == 0) {
193 int nelem = parse_vec(argv + i + 1, vec);
194 if(nelem < 4) {
195 fprintf(stderr, "-rotation must be followed by axis vector and angle\n");
196 goto err;
197 }
198 node->set_rotation(Quaternion(Vector3(vec[0], vec[1], vec[2]), vec[3]));
199 i += 4;
201 } else if(strcmp(argv[i], "-scaling") == 0) {
202 int nelem = parse_vec(argv + i + 1, vec);
203 Vector3 s;
204 if(nelem == 1) {
205 s.x = s.y = s.z = vec[0];
206 } else if(nelem == 3) {
207 s = Vector3(vec[0], vec[1], vec[2]);
208 } else {
209 fprintf(stderr, "-scaling must be followed by 1 or 3 numbers\n");
210 goto err;
211 }
212 node->set_scaling(s);
213 i += nelem;
215 } else if(strcmp(argv[i], "-diffuse") == 0) {
216 int nelem = parse_vec(argv + i + 1, vec);
217 if(nelem < 3) {
218 fprintf(stderr, "-diffuse must be followed by a color (r g b)\n");
219 goto err;
220 }
221 gobj->mtl.set_attrib("diffuse", Color(vec[0], vec[1], vec[2]));
222 i += 3;
224 } else if(strcmp(argv[i], "-specular") == 0) {
225 int nelem = parse_vec(argv + i + 1, vec);
226 if(nelem < 3) {
227 fprintf(stderr, "-specular must be followed by a color\n");
228 goto err;
229 }
230 gobj->mtl.set_attrib("specular", Color(vec[0], vec[1], vec[2]));
231 i += 3;
233 } else if(strcmp(argv[i], "-emissive") == 0) {
234 int nelem = parse_vec(argv + i + 1, vec);
235 Color emissive;
236 if(nelem == 1) {
237 emissive = Vector3(1, 1, 1);
238 } else if(nelem == 3) {
239 emissive = Vector3(vec[0], vec[1], vec[2]);
240 } else {
241 fprintf(stderr, "-emissive must be followed by an intensity or a color\n");
242 goto err;
243 }
244 i += nelem;
245 gobj->mtl.set_attrib("emissive", emissive);
247 } else {
248 fprintf(stderr, "unrecognized %s option: %s\n", argv[0], argv[i]);
249 goto err;
250 }
251 }
253 return node;
254 err:
255 delete node;
256 return 0;
257 }
259 static Camera *proc_camera(int argc, char **argv)
260 {
261 float vec[4];
262 TargetCamera *cam = new TargetCamera;
264 for(int i=1; i<argc; i++) {
265 if(strcmp(argv[i], "-position") == 0) {
266 int nelem = parse_vec(argv + i + 1, vec);
267 if(nelem < 3) {
268 fprintf(stderr, "-position must be followed by 3 numbers\n");
269 goto err;
270 }
271 cam->set_position(Vector3(vec[0], vec[1], vec[2]));
272 i += 3;
274 } else if(strcmp(argv[i], "-target") == 0) {
275 int nelem = parse_vec(argv + i + 1, vec);
276 if(nelem < 3) {
277 fprintf(stderr, "-target must be followed by 3 numbers\n");
278 goto err;
279 }
280 cam->set_target(Vector3(vec[0], vec[1], vec[2]));
281 i += 3;
283 } else if(strcmp(argv[i], "-fov") == 0) {
284 int nelem = parse_vec(argv + i + 1, vec);
285 if(nelem < 1) {
286 fprintf(stderr, "-fov must be followed by the field of view in degrees\n");
287 goto err;
288 }
289 cam->set_fov(vec[0]);
290 i += 1;
292 } else {
293 fprintf(stderr, "unrecognized camera option: %s\n", argv[i]);
294 goto err;
295 }
296 }
297 return cam;
299 err:
300 delete cam;
301 return 0;
302 }
304 bool Scene::proc_cmd(int argc, char **argv)
305 {
306 Object *obj = 0;
307 SceneNode *node = 0;
309 if(strcmp(argv[0], "sphere") == 0) {
310 obj = new Sphere;
311 node = proc_object(obj, argc, argv);
313 } else if(strcmp(argv[0], "box") == 0) {
314 obj = new Box;
315 node = proc_object(obj, argc, argv);
317 } else if(strcmp(argv[0], "mesh") == 0) {
318 fprintf(stderr, "meshes not implemented yet\n");
319 return false;
321 } else if(strcmp(argv[0], "camera") == 0) {
322 Camera *cam = proc_camera(argc, argv);
323 if(!cam) {
324 return false;
325 }
326 use_camera(cam);
328 } else {
329 fprintf(stderr, "unknown command: %s\n", argv[0]);
330 return false;
331 }
333 if(obj) {
334 if(!node) {
335 return false;
336 }
337 add_object(obj);
338 add_node(node);
339 }
341 return true;
342 }