gpuray_glsl
view src/scene_load.cc @ 2:6e3a4daf3159
adding cones
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Sun, 09 Nov 2014 14:39:01 +0200 |
parents | |
children | 2ed3da7dc0bc |
line source
1 #include <stdio.h>
2 #include <math.h>
3 #include <map>
4 #include "scene.h"
5 #include "sphere.h"
6 #include "plane.h"
7 #include "box.h"
8 #include "light.h"
9 #include "camera.h"
10 #include "texture.h"
12 static bool parse_material(char **argv, Material *mtl, std::string *name);
13 static Object *parse_sphere(char **argv, const std::map<std::string, Material> &materials);
14 static Object *parse_plane(char **argv, const std::map<std::string, Material> &materials);
15 static Object *parse_box(char **argv, const std::map<std::string, Material> &materials);
16 static Light *parse_light(char **argv);
17 static Camera *parse_camera(char **argv);
18 static bool parse_env(char **argv, Scene *scn);
19 static bool parse_xform(char **argv, Scene *scn);
20 static bool parse_vec(char **argv, Vector3 *vptr);
22 static char *strip_space(char *s);
23 static char **split_args(char *args);
25 bool load_scene_file(Scene *scn, const char *fname)
26 {
27 FILE *fp;
28 if(!(fp = fopen(fname, "rb"))) {
29 fprintf(stderr, "%s: failed to open scene file: %s: %s\n", __FUNCTION__, fname, strerror(errno));
30 return false;
31 }
33 char buf[512];
34 std::map<std::string, Material> materials;
36 int lineno = 0;
37 while(fgets(buf, sizeof buf, fp)) {
38 char *line = strip_space(buf);
40 lineno++;
42 if(!*line || *line == '\n' || *line == '#') {
43 continue;
44 }
46 if(strstr(line, "material") == line) {
47 Material mtl;
48 std::string name;
50 char *args = strip_space(line + strlen("material"));
51 if(!parse_material(split_args(args), &mtl, &name)) {
52 goto err;
53 }
54 materials[name] = mtl;
56 } else if(strstr(line, "sphere") == line) {
57 char *args = strip_space(line + strlen("sphere"));
58 Object *obj = parse_sphere(split_args(args), materials);
59 if(!obj) {
60 goto err;
61 }
62 scn->add_object(obj);
64 } else if(strstr(line, "plane") == line) {
65 char *args = strip_space(line + strlen("plane"));
66 Object *obj = parse_plane(split_args(args), materials);
67 if(!obj) {
68 goto err;
69 }
70 scn->add_object(obj);
72 } else if(strstr(line, "box") == line) {
73 char *args = strip_space(line + strlen("box"));
74 Object *obj = parse_box(split_args(args), materials);
75 if(!obj) {
76 goto err;
77 }
78 scn->add_object(obj);
80 } else if(strstr(line, "light") == line) {
81 char *args = strip_space(line + strlen("light"));
82 Light *lt = parse_light(split_args(args));
83 if(!lt) {
84 goto err;
85 }
86 scn->add_light(lt);
88 } else if(strstr(line, "camera") == line) {
89 char *args = strip_space(line + strlen("camera"));
90 Camera *cam = parse_camera(split_args(args));
91 if(!cam) {
92 goto err;
93 }
94 scn->set_camera(cam);
96 } else if(strstr(line, "environment") == line) {
97 char *args = strip_space(line + strlen("environment"));
98 if(!parse_env(split_args(args), scn)) {
99 goto err;
100 }
102 } else if(strstr(line, "xform") == line) {
103 char *args = strip_space(line + strlen("xform"));
104 if(!parse_xform(split_args(args), scn)) {
105 goto err;
106 }
108 } else {
109 fprintf(stderr, "%s error %s:%d: unknown command: %s\n", __FUNCTION__, fname, lineno, line);
110 goto err;
111 }
113 }
115 fclose(fp);
116 return true;
118 err:
119 fclose(fp);
120 return false;
121 }
123 bool save_scene_file(const Scene *scn, const char *fname)
124 {
125 FILE *fp;
126 if(!(fp = fopen(fname, "wb"))) {
127 fprintf(stderr, "%s: failed to save scene file: %s: %s\n", __FUNCTION__, fname, strerror(errno));
128 return false;
129 }
131 for(int i=0; i<scn->get_object_count(); i++) {
132 // first write the material
133 const Object *obj = scn->get_object(i);
134 const Material *mat = &obj->material;
136 char name[128];
137 sprintf(name, "mat%d", i);
139 fprintf(fp, "material -name %s", name);
140 fprintf(fp, " -diffuse %.3f %.3f %.3f", mat->diffuse.x, mat->diffuse.y, mat->diffuse.z);
141 fprintf(fp, " -specular %.3f %.3f %.3f", mat->specular.x, mat->specular.y, mat->specular.z);
142 fprintf(fp, " -shininess %.3f", mat->shininess);
143 fprintf(fp, " -emission %.3f %.3f %.3f", mat->emission.x, mat->emission.y, mat->emission.z);
144 fprintf(fp, " -reflect %.3f", mat->reflectivity);
145 fprintf(fp, " -trans %.3f", mat->transparency);
146 fprintf(fp, " -ior %.3f", mat->ior);
147 if(mat->tex) {
148 fprintf(fp, " -texture %s", mat->tex->get_name());
149 }
150 fputc('\n', fp);
152 // then write the object
153 const Sphere *sph;
154 const Plane *plane;
155 const Box *box;
156 if((sph = dynamic_cast<const Sphere*>(obj))) {
157 fprintf(fp, "sphere -material %s", name);
158 fprintf(fp, " -center %.3f %.3f %.3f", sph->pos.x, sph->pos.y, sph->pos.z);
159 fprintf(fp, " -radius %.3f\n", sph->radius);
160 } else if((plane = dynamic_cast<const Plane*>(obj))) {
161 fprintf(fp, "plane -material %s", name);
162 fprintf(fp, " -normal %.3f %.3f %.3f", plane->normal.x, plane->normal.y, plane->normal.z);
163 fprintf(fp, " -distance %.3f\n", plane->dist);
164 } else if((box = dynamic_cast<const Box*>(obj))) {
165 fprintf(fp, "box -material %s", name);
166 fprintf(fp, " -min %.3f %.3f %.3f", box->min.x, box->min.y, box->min.z);
167 fprintf(fp, " -max %.3f %.3f %.3f\n", box->max.x, box->max.y, box->max.z);
168 }
169 }
171 for(int i=0; i<scn->get_light_count(); i++) {
172 const Light *lt = scn->get_light(i);
174 fprintf(fp, "light -position %.3f %.3f %.3f", lt->pos.x, lt->pos.y, lt->pos.z);
175 fprintf(fp, " -color %.3f %.3f %.3f\n", lt->color.x, lt->color.y, lt->color.z);
176 }
178 const TargetCamera *tcam = dynamic_cast<const TargetCamera*>(scn->get_camera());
179 if(tcam) {
180 Vector3 pos = tcam->get_position();
181 fprintf(fp, "camera -position %.3f %.3f %.3f", pos.x, pos.y, pos.z);
182 Vector3 targ = tcam->get_target();
183 fprintf(fp, " -target %.3f %.3f %.3f", targ.x, targ.y, targ.z);
184 fprintf(fp, " -fov %.3f\n", tcam->get_fov());
185 }
188 fclose(fp);
189 return true;
190 }
192 #define ARGERR(n) \
193 do { fprintf(stderr, "failed to parse %s argument\n", (n)); return false; } while(0)
195 static bool parse_material(char **argv, Material *mtl, std::string *name)
196 {
197 char *endp;
199 for(int i=0; argv[i]; i++) {
200 if(strcmp(argv[i], "-name") == 0) {
201 *name = argv[++i];
202 } else if(strcmp(argv[i], "-diffuse") == 0) {
203 if(!parse_vec(argv + i + 1, &mtl->diffuse)) {
204 ARGERR("diffuse");
205 }
206 argv += 3;
208 } else if(strcmp(argv[i], "-specular") == 0) {
209 if(!parse_vec(argv + i + 1, &mtl->specular)) {
210 ARGERR("specular");
211 }
212 argv += 3;
214 } else if(strcmp(argv[i], "-emission") == 0) {
215 if(!parse_vec(argv + i + 1, &mtl->emission)) {
216 ARGERR("emission");
217 }
218 argv += 3;
220 } else if(strcmp(argv[i], "-shininess") == 0) {
221 mtl->shininess = strtod(argv[++i], &endp);
222 if(endp == argv[i]) {
223 ARGERR("shininess");
224 }
226 } else if(strcmp(argv[i], "-reflect") == 0) {
227 mtl->reflectivity = strtod(argv[++i], &endp);
228 if(endp == argv[i]) {
229 ARGERR("reflect");
230 }
232 } else if(strcmp(argv[i], "-trans") == 0) {
233 mtl->transparency = strtod(argv[++i], &endp);
234 if(endp == argv[i]) {
235 ARGERR("trans");
236 }
238 } else if(strcmp(argv[i], "-ior") == 0) {
239 mtl->ior = strtod(argv[++i], &endp);
240 if(endp == argv[i]) {
241 ARGERR("ior");
242 }
244 } else if(strcmp(argv[i], "-texture") == 0) {
245 if(!(mtl->tex = load_texture(argv[++i]))) {
246 return false;
247 }
249 } else {
250 fprintf(stderr, "invalid material option: %s\n", argv[i]);
251 return false;
252 }
253 }
254 return true;
255 }
257 static Object *parse_sphere(char **argv, const std::map<std::string, Material> &materials)
258 {
259 char *endp;
260 Sphere *sph = new Sphere;
262 for(int i=0; argv[i]; i++) {
263 if(strcmp(argv[i], "-name") == 0) {
264 sph->set_name(argv[++i]);
266 } else if(strcmp(argv[i], "-center") == 0) {
267 if(!parse_vec(argv + i + 1, &sph->pos)) {
268 fprintf(stderr, "failed to parse sphere center vector\n");
269 return 0;
270 }
271 argv += 3;
273 } else if(strcmp(argv[i], "-radius") == 0) {
274 sph->radius = strtod(argv[++i], &endp);
275 if(endp == argv[i]) {
276 fprintf(stderr, "failed to parse sphere radius\n");
277 return 0;
278 }
280 } else if(strcmp(argv[i], "-material") == 0) {
281 auto it = materials.find(argv[++i]);
282 if(it == materials.end()) {
283 fprintf(stderr, "material %s not found\n", argv[i]);
284 return 0;
285 }
287 sph->material = it->second;
288 } else {
289 fprintf(stderr, "invalid sphere option: %s\n", argv[i]);
290 return 0;
291 }
292 }
294 return sph;
295 }
297 static Object *parse_plane(char **argv, const std::map<std::string, Material> &materials)
298 {
299 char *endp;
300 Plane *plane = new Plane;
302 for(int i=0; argv[i]; i++) {
303 if(strcmp(argv[i], "-name") == 0) {
304 plane->set_name(argv[++i]);
306 } else if(strcmp(argv[i], "-normal") == 0) {
307 if(!parse_vec(argv + i + 1, &plane->normal)) {
308 fprintf(stderr, "failed to parse plane normal\n");
309 return 0;
310 }
311 plane->normal.normalize();
312 argv += 3;
314 } else if(strcmp(argv[i], "-distance") == 0) {
315 plane->dist = strtod(argv[++i], &endp);
316 if(endp == argv[i]) {
317 fprintf(stderr, "failed to parse plane distance\n");
318 return 0;
319 }
321 } else if(strcmp(argv[i], "-material") == 0) {
322 auto it = materials.find(argv[++i]);
323 if(it == materials.end()) {
324 fprintf(stderr, "material %s not found\n", argv[i]);
325 return 0;
326 }
328 plane->material = it->second;
329 } else {
330 fprintf(stderr, "invalid plane option: %s\n", argv[i]);
331 return 0;
332 }
333 }
335 return plane;
336 }
338 static Object *parse_box(char **argv, const std::map<std::string, Material> &materials)
339 {
340 Box *box = new Box;
342 for(int i=0; argv[i]; i++) {
343 if(strcmp(argv[i], "-name") == 0) {
344 box->set_name(argv[++i]);
346 } else if(strcmp(argv[i], "-min") == 0) {
347 if(!parse_vec(argv + i + 1, &box->min)) {
348 fprintf(stderr, "failed to parse box min\n");
349 return 0;
350 }
351 argv += 3;
353 } else if(strcmp(argv[i], "-max") == 0) {
354 if(!parse_vec(argv + i + 1, &box->max)) {
355 fprintf(stderr, "failed to parse box max\n");
356 return 0;
357 }
358 argv += 3;
360 } else if(strcmp(argv[i], "-material") == 0) {
361 auto it = materials.find(argv[++i]);
362 if(it == materials.end()) {
363 fprintf(stderr, "material %s not found\n", argv[i]);
364 return 0;
365 }
367 box->material = it->second;
368 } else {
369 fprintf(stderr, "invalid box option: %s\n", argv[i]);
370 return 0;
371 }
372 }
374 return box;
375 }
377 static Light *parse_light(char **argv)
378 {
379 Light *lt = new Light;
381 for(int i=0; argv[i]; i++) {
382 if(strcmp(argv[i], "-position") == 0) {
383 if(!parse_vec(argv + i + 1, <->pos)) {
384 fprintf(stderr, "failed to parse light position\n");
385 return 0;
386 }
387 argv += 3;
389 } else if(strcmp(argv[i], "-color") == 0) {
390 if(!parse_vec(argv + i + 1, <->color)) {
391 fprintf(stderr, "failed to parse light color\n");
392 return 0;
393 }
394 argv += 3;
396 } else {
397 fprintf(stderr, "invalid light option: %s\n", argv[i]);
398 return 0;
399 }
400 }
402 return lt;
403 }
405 static Camera *parse_camera(char **argv)
406 {
407 char *endp;
408 TargetCamera *cam = new TargetCamera;
410 for(int i=0; argv[i]; i++) {
411 if(strcmp(argv[i], "-position") == 0) {
412 Vector3 pos;
413 if(!parse_vec(argv + i + 1, &pos)) {
414 fprintf(stderr, "failed to parse camera position\n");
415 return 0;
416 }
417 argv += 3;
418 cam->set_position(pos);
420 } else if(strcmp(argv[i], "-target") == 0) {
421 Vector3 targ;
422 if(!parse_vec(argv + i + 1, &targ)) {
423 fprintf(stderr, "failed to parse camera target\n");
424 return 0;
425 }
426 argv += 3;
427 cam->set_target(targ);
429 } else if(strcmp(argv[i], "-fov") == 0) {
430 float fov = strtod(argv[++i], &endp);
431 if(endp == argv[i]) {
432 fprintf(stderr, "failed to parse camera fov\n");
433 return 0;
434 }
435 cam->set_fov(M_PI * fov / 180.0);
437 } else {
438 fprintf(stderr, "invalid camera option: %s\n", argv[i]);
439 return 0;
440 }
441 }
443 return cam;
444 }
446 static bool parse_env(char **argv, Scene *scn)
447 {
448 char *endp;
450 TextureCube *env_tex = 0;
451 TextureCube *conv_tex = 0;
453 float fog_start = -1;
454 float fog_end = -1;
456 for(int i=0; argv[i]; i++) {
457 if(strcmp(argv[i], "-color") == 0) {
458 Color bgcolor;
459 if(!parse_vec(argv + i + 1, &bgcolor)) {
460 fprintf(stderr, "failed to parse environment color\n");
461 return false;
462 }
463 i += 3;
464 scn->set_background_color(bgcolor);
466 } else if(strcmp(argv[i], "-fog-start") == 0) {
467 fog_start = strtod(argv[++i], &endp);
468 if(endp == argv[i]) {
469 fprintf(stderr, "failed to parse environment fog start\n");
470 return false;
471 }
473 } else if(strcmp(argv[i], "-fog-end") == 0) {
474 fog_end = strtod(argv[++i], &endp);
475 if(endp == argv[i]) {
476 fprintf(stderr, "failed to parse environment fog end\n");
477 return false;
478 }
480 } else if(strcmp(argv[i], "-texture") == 0 || strcmp(argv[i], "-texture-conv") == 0) {
481 Texture *tex = load_texture(argv[++i]);
482 if(!tex || !dynamic_cast<TextureCube*>(tex)) {
483 fprintf(stderr, "failed to load environment cubemap: %s\n", argv[i]);
484 delete tex;
485 return false;
486 }
488 if(strstr(argv[i - 1], "-conv")) {
489 conv_tex = (TextureCube*)tex;
490 } else {
491 env_tex = (TextureCube*)tex;
492 }
494 } else {
495 fprintf(stderr, "invalid environment option: %s\n", argv[i]);
496 return false;
497 }
498 }
500 if(env_tex || conv_tex) {
501 scn->set_environment_map(env_tex, conv_tex);
502 }
504 if(fog_start > 0.0 && fog_end > 0.0) {
505 scn->set_fog(fog_start, fog_end);
506 }
508 return true;
509 }
511 static bool parse_xform(char **argv, Scene *scn)
512 {
513 char *endp, *name = 0;
514 Vector3 pos, rot_axis, scale;
515 float rot_angle = 0;
516 long tm = 0;
517 Extrap extrap = EXTRAP_REPEAT;
519 bool have_pos = false;
520 bool have_rot_axis = false;
521 bool have_rot_angle = false;
522 bool have_scale = false;
523 bool have_extrap = false;
525 for(int i=0; argv[i]; i++) {
526 if(strcmp(argv[i], "-name") == 0) {
527 name = argv[++i];
529 } else if(strcmp(argv[i], "-pos") == 0) {
530 if(!parse_vec(argv + i + 1, &pos)) {
531 fprintf(stderr, "failed to parse xform position\n");
532 return false;
533 }
534 have_pos = true;
535 i += 3;
537 } else if(strcmp(argv[i], "-rot-axis") == 0) {
538 if(!parse_vec(argv + i + 1, &rot_axis)) {
539 fprintf(stderr, "failed to parse xform rotation axis\n");
540 return false;
541 }
542 have_rot_axis = true;
543 i += 3;
545 } else if(strcmp(argv[i], "-rot-angle") == 0) {
546 rot_angle = strtod(argv[++i], &endp);
547 if(endp == argv[i]) {
548 fprintf(stderr, "failed to parse xform rotation angle\n");
549 return false;
550 }
551 rot_angle = M_PI * rot_angle / 180.0;
552 have_rot_angle = true;
554 } else if(strcmp(argv[i], "-scale") == 0) {
555 if(!parse_vec(argv + i + 1, &scale)) {
556 fprintf(stderr, "failed to parse xform scale\n");
557 return false;
558 }
559 have_scale = true;
560 i += 3;
562 } else if(strcmp(argv[i], "-time") == 0) {
563 float tm_sec = strtod(argv[++i], &endp);
564 if(endp == argv[i]) {
565 fprintf(stderr, "failed to parse xform time\n");
566 return false;
567 }
568 tm = (long)(tm_sec * 1000.0f);
570 } else if(strcmp(argv[i], "-extrapolation") == 0) {
571 if(strcmp(argv[++i], "extend") == 0) {
572 extrap = EXTRAP_EXTEND;
573 } else if(strcmp(argv[i], "clamp") == 0) {
574 extrap = EXTRAP_CLAMP;
575 } else if(strcmp(argv[i], "repeat") == 0) {
576 extrap = EXTRAP_REPEAT;
577 } else if(strcmp(argv[i], "pingpong") == 0) {
578 extrap = EXTRAP_PINGPONG;
579 } else {
580 fprintf(stderr, "failed to parse xform extrapolation, invalid mode: %s\n", argv[i]);
581 return false;
582 }
583 have_extrap = true;
585 } else {
586 fprintf(stderr, "invalid xform option: %s\n", argv[i]);
587 return false;
588 }
589 }
591 if(!name) {
592 fprintf(stderr, "invalid xform command, missing -name option\n");
593 return false;
594 }
595 if(have_rot_angle != have_rot_axis) {
596 fprintf(stderr, "invalid xform command, must have both -rot-angle and -rot-axis or neither\n");
597 return false;
598 }
600 Object *obj = 0;
602 int nobj = scn->get_object_count();
603 for(int i=0; i<nobj; i++) {
604 Object *tmp = scn->get_object(i);
605 if(strcmp(tmp->get_name(), name) == 0) {
606 obj = tmp;
607 break;
608 }
609 }
611 if(!obj) {
612 fprintf(stderr, "invalid xform, refers to nonexistent object: %s\n", name);
613 return false;
614 }
616 if(have_pos) {
617 obj->set_position(pos, tm);
618 }
619 if(have_rot_angle) {
620 obj->set_rotation(Quaternion(rot_axis, rot_angle), tm);
621 }
622 if(have_scale) {
623 obj->set_scaling(scale, tm);
624 }
626 if(have_extrap) {
627 obj->set_extrapolator(extrap);
628 }
629 return true;
630 }
632 static bool parse_vec(char **argv, Vector3 *vptr)
633 {
634 char *endp;
636 vptr->x = strtod(argv[0], &endp);
637 if(endp == argv[0])
638 return false;
639 vptr->y = strtod(argv[1], &endp);
640 if(endp == argv[1])
641 return false;
642 vptr->z = strtod(argv[2], &endp);
643 if(endp == argv[2])
644 return false;
646 return true;
647 }
650 static char *strip_space(char *s)
651 {
652 while(*s && isspace(*s)) s++;
654 if(!*s)
655 return s;
657 char *endp = s + strlen(s) - 1;
658 while(isspace(*endp)) endp--;
659 endp[1] = 0;
661 if((endp = strrchr(s, '#'))) {
662 *endp = 0;
663 }
665 return s;
666 }
668 static char **split_args(char *args)
669 {
670 static std::vector<char*> argv;
671 char *tok = 0;
673 argv.clear();
675 while((tok = strtok(tok ? 0 : args, " \t\v\n\r"))) {
676 argv.push_back(tok);
677 }
678 argv.push_back(0);
680 return &argv[0];
681 }