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