gpuray_glsl
view src/scene_load.cc @ 5:000017955721
fixed the cone normal
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 11 Nov 2014 20:25:59 +0200 |
parents | f234630e38ff |
children |
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 "cone.h"
9 #include "light.h"
10 #include "camera.h"
11 #include "texture.h"
13 static bool parse_material(char **argv, Material *mtl, std::string *name);
14 static Object *parse_sphere(char **argv, const std::map<std::string, Material> &materials);
15 static Object *parse_plane(char **argv, const std::map<std::string, Material> &materials);
16 static Object *parse_box(char **argv, const std::map<std::string, Material> &materials);
17 static Object *parse_cone(char **argv, const std::map<std::string, Material> &materials);
18 static Light *parse_light(char **argv);
19 static Camera *parse_camera(char **argv);
20 static bool parse_env(char **argv, Scene *scn);
21 static bool parse_xform(char **argv, Scene *scn);
22 static bool parse_vec(char **argv, Vector3 *vptr);
24 static char *strip_space(char *s);
25 static char **split_args(char *args);
27 bool load_scene_file(Scene *scn, const char *fname)
28 {
29 FILE *fp;
30 if(!(fp = fopen(fname, "rb"))) {
31 fprintf(stderr, "%s: failed to open scene file: %s: %s\n", __FUNCTION__, fname, strerror(errno));
32 return false;
33 }
35 char buf[512];
36 std::map<std::string, Material> materials;
38 int lineno = 0;
39 while(fgets(buf, sizeof buf, fp)) {
40 char *line = strip_space(buf);
42 lineno++;
44 if(!*line || *line == '\n' || *line == '#') {
45 continue;
46 }
48 if(strstr(line, "material") == line) {
49 Material mtl;
50 std::string name;
52 char *args = strip_space(line + strlen("material"));
53 if(!parse_material(split_args(args), &mtl, &name)) {
54 goto err;
55 }
56 materials[name] = mtl;
58 } else if(strstr(line, "sphere") == line) {
59 char *args = strip_space(line + strlen("sphere"));
60 Object *obj = parse_sphere(split_args(args), materials);
61 if(!obj) {
62 goto err;
63 }
64 scn->add_object(obj);
66 } else if(strstr(line, "plane") == line) {
67 char *args = strip_space(line + strlen("plane"));
68 Object *obj = parse_plane(split_args(args), materials);
69 if(!obj) {
70 goto err;
71 }
72 scn->add_object(obj);
74 } else if(strstr(line, "box") == line) {
75 char *args = strip_space(line + strlen("box"));
76 Object *obj = parse_box(split_args(args), materials);
77 if(!obj) {
78 goto err;
79 }
80 scn->add_object(obj);
82 } else if(strstr(line, "cone") == line) {
83 char *args = strip_space(line + strlen("cone"));
84 Object *obj = parse_cone(split_args(args), materials);
85 if(!obj) {
86 goto err;
87 }
88 scn->add_object(obj);
90 } else if(strstr(line, "light") == line) {
91 char *args = strip_space(line + strlen("light"));
92 Light *lt = parse_light(split_args(args));
93 if(!lt) {
94 goto err;
95 }
96 scn->add_light(lt);
98 } else if(strstr(line, "camera") == line) {
99 char *args = strip_space(line + strlen("camera"));
100 Camera *cam = parse_camera(split_args(args));
101 if(!cam) {
102 goto err;
103 }
104 scn->set_camera(cam);
106 } else if(strstr(line, "environment") == line) {
107 char *args = strip_space(line + strlen("environment"));
108 if(!parse_env(split_args(args), scn)) {
109 goto err;
110 }
112 } else if(strstr(line, "xform") == line) {
113 char *args = strip_space(line + strlen("xform"));
114 if(!parse_xform(split_args(args), scn)) {
115 goto err;
116 }
118 } else {
119 fprintf(stderr, "%s error %s:%d: unknown command: %s\n", __FUNCTION__, fname, lineno, line);
120 goto err;
121 }
123 }
125 fclose(fp);
126 return true;
128 err:
129 fclose(fp);
130 return false;
131 }
133 bool save_scene_file(const Scene *scn, const char *fname)
134 {
135 FILE *fp;
136 if(!(fp = fopen(fname, "wb"))) {
137 fprintf(stderr, "%s: failed to save scene file: %s: %s\n", __FUNCTION__, fname, strerror(errno));
138 return false;
139 }
141 for(int i=0; i<scn->get_object_count(); i++) {
142 // first write the material
143 const Object *obj = scn->get_object(i);
144 const Material *mat = &obj->material;
146 char name[128];
147 sprintf(name, "mat%d", i);
149 fprintf(fp, "material -name %s", name);
150 fprintf(fp, " -diffuse %.3f %.3f %.3f", mat->diffuse.x, mat->diffuse.y, mat->diffuse.z);
151 fprintf(fp, " -specular %.3f %.3f %.3f", mat->specular.x, mat->specular.y, mat->specular.z);
152 fprintf(fp, " -shininess %.3f", mat->shininess);
153 fprintf(fp, " -emission %.3f %.3f %.3f", mat->emission.x, mat->emission.y, mat->emission.z);
154 fprintf(fp, " -reflect %.3f", mat->reflectivity);
155 fprintf(fp, " -trans %.3f", mat->transparency);
156 fprintf(fp, " -ior %.3f", mat->ior);
157 if(mat->tex) {
158 fprintf(fp, " -texture %s", mat->tex->get_name());
159 }
160 fputc('\n', fp);
162 // then write the object
163 const Sphere *sph;
164 const Plane *plane;
165 const Box *box;
166 const Cone *cone;
167 if((sph = dynamic_cast<const Sphere*>(obj))) {
168 fprintf(fp, "sphere -material %s", name);
169 fprintf(fp, " -center %.3f %.3f %.3f", sph->pos.x, sph->pos.y, sph->pos.z);
170 fprintf(fp, " -radius %.3f\n", sph->radius);
171 } else if((plane = dynamic_cast<const Plane*>(obj))) {
172 fprintf(fp, "plane -material %s", name);
173 fprintf(fp, " -normal %.3f %.3f %.3f", plane->normal.x, plane->normal.y, plane->normal.z);
174 fprintf(fp, " -distance %.3f\n", plane->dist);
175 } else if((box = dynamic_cast<const Box*>(obj))) {
176 fprintf(fp, "box -material %s", name);
177 fprintf(fp, " -min %.3f %.3f %.3f", box->min.x, box->min.y, box->min.z);
178 fprintf(fp, " -max %.3f %.3f %.3f\n", box->max.x, box->max.y, box->max.z);
179 } else if((cone = dynamic_cast<const Cone*>(obj))) {
180 fprintf(fp, "cone -material %s", name);
181 fprintf(fp, " -angle %g", RAD_TO_DEG(cone->angle));
182 fprintf(fp, " -start %g -end %g\n", cone->ymin, cone->ymax);
183 }
184 }
186 for(int i=0; i<scn->get_light_count(); i++) {
187 const Light *lt = scn->get_light(i);
189 fprintf(fp, "light -position %.3f %.3f %.3f", lt->pos.x, lt->pos.y, lt->pos.z);
190 fprintf(fp, " -color %.3f %.3f %.3f\n", lt->color.x, lt->color.y, lt->color.z);
191 }
193 const TargetCamera *tcam = dynamic_cast<const TargetCamera*>(scn->get_camera());
194 if(tcam) {
195 Vector3 pos = tcam->get_position();
196 fprintf(fp, "camera -position %.3f %.3f %.3f", pos.x, pos.y, pos.z);
197 Vector3 targ = tcam->get_target();
198 fprintf(fp, " -target %.3f %.3f %.3f", targ.x, targ.y, targ.z);
199 fprintf(fp, " -fov %.3f\n", tcam->get_fov());
200 }
203 fclose(fp);
204 return true;
205 }
207 #define ARGERR(n) \
208 do { fprintf(stderr, "failed to parse %s argument\n", (n)); return false; } while(0)
210 static bool parse_material(char **argv, Material *mtl, std::string *name)
211 {
212 char *endp;
214 for(int i=0; argv[i]; i++) {
215 if(strcmp(argv[i], "-name") == 0) {
216 *name = argv[++i];
217 } else if(strcmp(argv[i], "-diffuse") == 0) {
218 if(!parse_vec(argv + i + 1, &mtl->diffuse)) {
219 ARGERR("diffuse");
220 }
221 argv += 3;
223 } else if(strcmp(argv[i], "-specular") == 0) {
224 if(!parse_vec(argv + i + 1, &mtl->specular)) {
225 ARGERR("specular");
226 }
227 argv += 3;
229 } else if(strcmp(argv[i], "-emission") == 0) {
230 if(!parse_vec(argv + i + 1, &mtl->emission)) {
231 ARGERR("emission");
232 }
233 argv += 3;
235 } else if(strcmp(argv[i], "-shininess") == 0) {
236 mtl->shininess = strtod(argv[++i], &endp);
237 if(endp == argv[i]) {
238 ARGERR("shininess");
239 }
241 } else if(strcmp(argv[i], "-reflect") == 0) {
242 mtl->reflectivity = strtod(argv[++i], &endp);
243 if(endp == argv[i]) {
244 ARGERR("reflect");
245 }
247 } else if(strcmp(argv[i], "-trans") == 0) {
248 mtl->transparency = strtod(argv[++i], &endp);
249 if(endp == argv[i]) {
250 ARGERR("trans");
251 }
253 } else if(strcmp(argv[i], "-ior") == 0) {
254 mtl->ior = strtod(argv[++i], &endp);
255 if(endp == argv[i]) {
256 ARGERR("ior");
257 }
259 } else if(strcmp(argv[i], "-texture") == 0) {
260 if(!(mtl->tex = load_texture(argv[++i]))) {
261 return false;
262 }
264 } else {
265 fprintf(stderr, "invalid material option: %s\n", argv[i]);
266 return false;
267 }
268 }
269 return true;
270 }
272 static Object *parse_sphere(char **argv, const std::map<std::string, Material> &materials)
273 {
274 char *endp;
275 Sphere *sph = new Sphere;
277 for(int i=0; argv[i]; i++) {
278 if(strcmp(argv[i], "-name") == 0) {
279 sph->set_name(argv[++i]);
281 } else if(strcmp(argv[i], "-center") == 0) {
282 if(!parse_vec(argv + i + 1, &sph->pos)) {
283 fprintf(stderr, "failed to parse sphere center vector\n");
284 return 0;
285 }
286 argv += 3;
288 } else if(strcmp(argv[i], "-radius") == 0) {
289 sph->radius = strtod(argv[++i], &endp);
290 if(endp == argv[i]) {
291 fprintf(stderr, "failed to parse sphere radius\n");
292 return 0;
293 }
295 } else if(strcmp(argv[i], "-material") == 0) {
296 auto it = materials.find(argv[++i]);
297 if(it == materials.end()) {
298 fprintf(stderr, "material %s not found\n", argv[i]);
299 return 0;
300 }
302 sph->material = it->second;
303 } else {
304 fprintf(stderr, "invalid sphere option: %s\n", argv[i]);
305 return 0;
306 }
307 }
309 return sph;
310 }
312 static Object *parse_plane(char **argv, const std::map<std::string, Material> &materials)
313 {
314 char *endp;
315 Plane *plane = new Plane;
317 for(int i=0; argv[i]; i++) {
318 if(strcmp(argv[i], "-name") == 0) {
319 plane->set_name(argv[++i]);
321 } else if(strcmp(argv[i], "-normal") == 0) {
322 if(!parse_vec(argv + i + 1, &plane->normal)) {
323 fprintf(stderr, "failed to parse plane normal\n");
324 return 0;
325 }
326 plane->normal.normalize();
327 argv += 3;
329 } else if(strcmp(argv[i], "-distance") == 0) {
330 plane->dist = strtod(argv[++i], &endp);
331 if(endp == argv[i]) {
332 fprintf(stderr, "failed to parse plane distance\n");
333 return 0;
334 }
336 } else if(strcmp(argv[i], "-material") == 0) {
337 auto it = materials.find(argv[++i]);
338 if(it == materials.end()) {
339 fprintf(stderr, "material %s not found\n", argv[i]);
340 return 0;
341 }
343 plane->material = it->second;
344 } else {
345 fprintf(stderr, "invalid plane option: %s\n", argv[i]);
346 return 0;
347 }
348 }
350 return plane;
351 }
353 static Object *parse_box(char **argv, const std::map<std::string, Material> &materials)
354 {
355 Box *box = new Box;
357 for(int i=0; argv[i]; i++) {
358 if(strcmp(argv[i], "-name") == 0) {
359 box->set_name(argv[++i]);
361 } else if(strcmp(argv[i], "-min") == 0) {
362 if(!parse_vec(argv + i + 1, &box->min)) {
363 fprintf(stderr, "failed to parse box min\n");
364 return 0;
365 }
366 argv += 3;
368 } else if(strcmp(argv[i], "-max") == 0) {
369 if(!parse_vec(argv + i + 1, &box->max)) {
370 fprintf(stderr, "failed to parse box max\n");
371 return 0;
372 }
373 argv += 3;
375 } else if(strcmp(argv[i], "-material") == 0) {
376 auto it = materials.find(argv[++i]);
377 if(it == materials.end()) {
378 fprintf(stderr, "material %s not found\n", argv[i]);
379 return 0;
380 }
382 box->material = it->second;
383 } else {
384 fprintf(stderr, "invalid box option: %s\n", argv[i]);
385 return 0;
386 }
387 }
389 return box;
390 }
392 static Object *parse_cone(char **argv, const std::map<std::string, Material> &materials)
393 {
394 char *endp;
395 Cone *cone = new Cone;
397 for(int i=0; argv[i]; i++) {
398 if(strcmp(argv[i], "-name") == 0) {
399 cone->set_name(argv[++i]);
401 } else if(strcmp(argv[i], "-angle") == 0) {
402 cone->angle = DEG_TO_RAD(strtod(argv[++i], &endp));
403 if(endp == argv[i]) {
404 fprintf(stderr, "failed to parse cone angle\n");
405 return 0;
406 }
408 } else if(strcmp(argv[i], "-start") == 0) {
409 cone->ymin = strtod(argv[++i], &endp);
410 if(endp == argv[i]) {
411 fprintf(stderr, "failed to parse cone start\n");
412 return 0;
413 }
415 } else if(strcmp(argv[i], "-end") == 0) {
416 cone->ymax = strtod(argv[++i], &endp);
417 if(endp == argv[i]) {
418 fprintf(stderr, "failed to parse cone end\n");
419 return 0;
420 }
422 } else if(strcmp(argv[i], "-material") == 0) {
423 auto it = materials.find(argv[++i]);
424 if(it == materials.end()) {
425 fprintf(stderr, "material %s not found\n", argv[i]);
426 return 0;
427 }
429 cone->material = it->second;
430 } else {
431 fprintf(stderr, "invalid box option: %s\n", argv[i]);
432 return 0;
433 }
434 }
436 return cone;
437 }
439 static Light *parse_light(char **argv)
440 {
441 Light *lt = new Light;
443 for(int i=0; argv[i]; i++) {
444 if(strcmp(argv[i], "-position") == 0) {
445 if(!parse_vec(argv + i + 1, <->pos)) {
446 fprintf(stderr, "failed to parse light position\n");
447 return 0;
448 }
449 argv += 3;
451 } else if(strcmp(argv[i], "-color") == 0) {
452 if(!parse_vec(argv + i + 1, <->color)) {
453 fprintf(stderr, "failed to parse light color\n");
454 return 0;
455 }
456 argv += 3;
458 } else {
459 fprintf(stderr, "invalid light option: %s\n", argv[i]);
460 return 0;
461 }
462 }
464 return lt;
465 }
467 static Camera *parse_camera(char **argv)
468 {
469 char *endp;
470 TargetCamera *cam = new TargetCamera;
472 for(int i=0; argv[i]; i++) {
473 if(strcmp(argv[i], "-position") == 0) {
474 Vector3 pos;
475 if(!parse_vec(argv + i + 1, &pos)) {
476 fprintf(stderr, "failed to parse camera position\n");
477 return 0;
478 }
479 argv += 3;
480 cam->set_position(pos);
482 } else if(strcmp(argv[i], "-target") == 0) {
483 Vector3 targ;
484 if(!parse_vec(argv + i + 1, &targ)) {
485 fprintf(stderr, "failed to parse camera target\n");
486 return 0;
487 }
488 argv += 3;
489 cam->set_target(targ);
491 } else if(strcmp(argv[i], "-fov") == 0) {
492 float fov = strtod(argv[++i], &endp);
493 if(endp == argv[i]) {
494 fprintf(stderr, "failed to parse camera fov\n");
495 return 0;
496 }
497 cam->set_fov(M_PI * fov / 180.0);
499 } else {
500 fprintf(stderr, "invalid camera option: %s\n", argv[i]);
501 return 0;
502 }
503 }
505 return cam;
506 }
508 static bool parse_env(char **argv, Scene *scn)
509 {
510 char *endp;
512 TextureCube *env_tex = 0;
513 TextureCube *conv_tex = 0;
515 float fog_start = -1;
516 float fog_end = -1;
518 for(int i=0; argv[i]; i++) {
519 if(strcmp(argv[i], "-color") == 0) {
520 Color bgcolor;
521 if(!parse_vec(argv + i + 1, &bgcolor)) {
522 fprintf(stderr, "failed to parse environment color\n");
523 return false;
524 }
525 i += 3;
526 scn->set_background_color(bgcolor);
528 } else if(strcmp(argv[i], "-fog-start") == 0) {
529 fog_start = strtod(argv[++i], &endp);
530 if(endp == argv[i]) {
531 fprintf(stderr, "failed to parse environment fog start\n");
532 return false;
533 }
535 } else if(strcmp(argv[i], "-fog-end") == 0) {
536 fog_end = strtod(argv[++i], &endp);
537 if(endp == argv[i]) {
538 fprintf(stderr, "failed to parse environment fog end\n");
539 return false;
540 }
542 } else if(strcmp(argv[i], "-texture") == 0 || strcmp(argv[i], "-texture-conv") == 0) {
543 Texture *tex = load_texture(argv[++i]);
544 if(!tex || !dynamic_cast<TextureCube*>(tex)) {
545 fprintf(stderr, "failed to load environment cubemap: %s\n", argv[i]);
546 delete tex;
547 return false;
548 }
550 if(strstr(argv[i - 1], "-conv")) {
551 conv_tex = (TextureCube*)tex;
552 } else {
553 env_tex = (TextureCube*)tex;
554 }
556 } else {
557 fprintf(stderr, "invalid environment option: %s\n", argv[i]);
558 return false;
559 }
560 }
562 if(env_tex || conv_tex) {
563 scn->set_environment_map(env_tex, conv_tex);
564 }
566 if(fog_start > 0.0 && fog_end > 0.0) {
567 scn->set_fog(fog_start, fog_end);
568 }
570 return true;
571 }
573 static bool parse_xform(char **argv, Scene *scn)
574 {
575 char *endp, *name = 0;
576 Vector3 pos, rot_axis, scale;
577 float rot_angle = 0;
578 long tm = 0;
579 Extrap extrap = EXTRAP_REPEAT;
581 bool have_pos = false;
582 bool have_rot_axis = false;
583 bool have_rot_angle = false;
584 bool have_scale = false;
585 bool have_extrap = false;
587 for(int i=0; argv[i]; i++) {
588 if(strcmp(argv[i], "-name") == 0) {
589 name = argv[++i];
591 } else if(strcmp(argv[i], "-pos") == 0) {
592 if(!parse_vec(argv + i + 1, &pos)) {
593 fprintf(stderr, "failed to parse xform position\n");
594 return false;
595 }
596 have_pos = true;
597 i += 3;
599 } else if(strcmp(argv[i], "-rot-axis") == 0) {
600 if(!parse_vec(argv + i + 1, &rot_axis)) {
601 fprintf(stderr, "failed to parse xform rotation axis\n");
602 return false;
603 }
604 have_rot_axis = true;
605 i += 3;
607 } else if(strcmp(argv[i], "-rot-angle") == 0) {
608 rot_angle = strtod(argv[++i], &endp);
609 if(endp == argv[i]) {
610 fprintf(stderr, "failed to parse xform rotation angle\n");
611 return false;
612 }
613 rot_angle = M_PI * rot_angle / 180.0;
614 have_rot_angle = true;
616 } else if(strcmp(argv[i], "-scale") == 0) {
617 if(!parse_vec(argv + i + 1, &scale)) {
618 fprintf(stderr, "failed to parse xform scale\n");
619 return false;
620 }
621 have_scale = true;
622 i += 3;
624 } else if(strcmp(argv[i], "-time") == 0) {
625 float tm_sec = strtod(argv[++i], &endp);
626 if(endp == argv[i]) {
627 fprintf(stderr, "failed to parse xform time\n");
628 return false;
629 }
630 tm = (long)(tm_sec * 1000.0f);
632 } else if(strcmp(argv[i], "-extrapolation") == 0) {
633 if(strcmp(argv[++i], "extend") == 0) {
634 extrap = EXTRAP_EXTEND;
635 } else if(strcmp(argv[i], "clamp") == 0) {
636 extrap = EXTRAP_CLAMP;
637 } else if(strcmp(argv[i], "repeat") == 0) {
638 extrap = EXTRAP_REPEAT;
639 } else if(strcmp(argv[i], "pingpong") == 0) {
640 extrap = EXTRAP_PINGPONG;
641 } else {
642 fprintf(stderr, "failed to parse xform extrapolation, invalid mode: %s\n", argv[i]);
643 return false;
644 }
645 have_extrap = true;
647 } else {
648 fprintf(stderr, "invalid xform option: %s\n", argv[i]);
649 return false;
650 }
651 }
653 if(!name) {
654 fprintf(stderr, "invalid xform command, missing -name option\n");
655 return false;
656 }
657 if(have_rot_angle != have_rot_axis) {
658 fprintf(stderr, "invalid xform command, must have both -rot-angle and -rot-axis or neither\n");
659 return false;
660 }
662 Object *obj = 0;
664 int nobj = scn->get_object_count();
665 for(int i=0; i<nobj; i++) {
666 Object *tmp = scn->get_object(i);
667 if(strcmp(tmp->get_name(), name) == 0) {
668 obj = tmp;
669 break;
670 }
671 }
673 if(!obj) {
674 fprintf(stderr, "invalid xform, refers to nonexistent object: %s\n", name);
675 return false;
676 }
678 if(have_pos) {
679 obj->set_position(pos, tm);
680 }
681 if(have_rot_angle) {
682 obj->set_rotation(Quaternion(rot_axis, rot_angle), tm);
683 }
684 if(have_scale) {
685 obj->set_scaling(scale, tm);
686 }
688 if(have_extrap) {
689 obj->set_extrapolator(extrap);
690 }
691 return true;
692 }
694 static bool parse_vec(char **argv, Vector3 *vptr)
695 {
696 char *endp;
698 vptr->x = strtod(argv[0], &endp);
699 if(endp == argv[0])
700 return false;
701 vptr->y = strtod(argv[1], &endp);
702 if(endp == argv[1])
703 return false;
704 vptr->z = strtod(argv[2], &endp);
705 if(endp == argv[2])
706 return false;
708 return true;
709 }
712 static char *strip_space(char *s)
713 {
714 while(*s && isspace(*s)) s++;
716 if(!*s)
717 return s;
719 char *endp = s + strlen(s) - 1;
720 while(isspace(*endp)) endp--;
721 endp[1] = 0;
723 if((endp = strrchr(s, '#'))) {
724 *endp = 0;
725 }
727 return s;
728 }
730 static char **split_args(char *args)
731 {
732 static std::vector<char*> argv;
733 char *tok = 0;
735 argv.clear();
737 while((tok = strtok(tok ? 0 : args, " \t\v\n\r"))) {
738 argv.push_back(tok);
739 }
740 argv.push_back(0);
742 return &argv[0];
743 }