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