c7580642c435a4d1e9eb1bf20ab08139c33f04de
[blender.git] / intern / cycles / app / cycles_xml.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include <stdio.h>
20
21 #include <sstream>
22 #include <algorithm>
23 #include <iterator>
24
25 #include "camera.h"
26 #include "film.h"
27 #include "graph.h"
28 #include "integrator.h"
29 #include "light.h"
30 #include "mesh.h"
31 #include "nodes.h"
32 #include "object.h"
33 #include "shader.h"
34 #include "scene.h"
35
36 #include "subd_mesh.h"
37 #include "subd_patch.h"
38 #include "subd_split.h"
39
40 #include "util_debug.h"
41 #include "util_foreach.h"
42 #include "util_path.h"
43 #include "util_transform.h"
44 #include "util_xml.h"
45
46 #include "cycles_xml.h"
47
48 CCL_NAMESPACE_BEGIN
49
50 /* XML reading state */
51
52 struct XMLReadState {
53         Scene *scene;           /* scene pointer */
54         Transform tfm;          /* current transform state */
55         bool smooth;            /* smooth normal state */
56         int shader;                     /* current shader */
57         string base;            /* base path to current file*/
58         float dicing_rate;      /* current dicing rate */
59         Mesh::DisplacementMethod displacement_method;
60 };
61
62 /* Attribute Reading */
63
64 static bool xml_read_bool(bool *value, pugi::xml_node node, const char *name)
65 {
66         pugi::xml_attribute attr = node.attribute(name);
67
68         if(attr) {
69                 *value = (string_iequals(attr.value(), "true")) || (atoi(attr.value()) != 0);
70                 return true;
71         }
72
73         return false;
74 }
75
76 static bool xml_read_int(int *value, pugi::xml_node node, const char *name)
77 {
78         pugi::xml_attribute attr = node.attribute(name);
79
80         if(attr) {
81                 *value = atoi(attr.value());
82                 return true;
83         }
84
85         return false;
86 }
87
88 static bool xml_read_int_array(vector<int>& value, pugi::xml_node node, const char *name)
89 {
90         pugi::xml_attribute attr = node.attribute(name);
91
92         if(attr) {
93                 vector<string> tokens;
94                 string_split(tokens, attr.value());
95
96                 foreach(const string& token, tokens)
97                         value.push_back(atoi(token.c_str()));
98
99                 return true;
100         }
101
102         return false;
103 }
104
105 static bool xml_read_float(float *value, pugi::xml_node node, const char *name)
106 {
107         pugi::xml_attribute attr = node.attribute(name);
108
109         if(attr) {
110                 *value = atof(attr.value());
111                 return true;
112         }
113
114         return false;
115 }
116
117 static bool xml_read_float_array(vector<float>& value, pugi::xml_node node, const char *name)
118 {
119         pugi::xml_attribute attr = node.attribute(name);
120
121         if(attr) {
122                 vector<string> tokens;
123                 string_split(tokens, attr.value());
124
125                 foreach(const string& token, tokens)
126                         value.push_back(atof(token.c_str()));
127
128                 return true;
129         }
130
131         return false;
132 }
133
134 static bool xml_read_float3(float3 *value, pugi::xml_node node, const char *name)
135 {
136         vector<float> array;
137
138         if(xml_read_float_array(array, node, name) && array.size() == 3) {
139                 *value = make_float3(array[0], array[1], array[2]);
140                 return true;
141         }
142
143         return false;
144 }
145
146 static bool xml_read_float3_array(vector<float3>& value, pugi::xml_node node, const char *name)
147 {
148         vector<float> array;
149
150         if(xml_read_float_array(array, node, name)) {
151                 for(size_t i = 0; i < array.size(); i += 3)
152                         value.push_back(make_float3(array[i+0], array[i+1], array[i+2]));
153
154                 return true;
155         }
156
157         return false;
158 }
159
160 static bool xml_read_float4(float4 *value, pugi::xml_node node, const char *name)
161 {
162         vector<float> array;
163
164         if(xml_read_float_array(array, node, name) && array.size() == 4) {
165                 *value = make_float4(array[0], array[1], array[2], array[3]);
166                 return true;
167         }
168
169         return false;
170 }
171
172 static bool xml_read_string(string *str, pugi::xml_node node, const char *name)
173 {
174         pugi::xml_attribute attr = node.attribute(name);
175
176         if(attr) {
177                 *str = attr.value();
178                 return true;
179         }
180
181         return false;
182 }
183
184 static bool xml_read_ustring(ustring *str, pugi::xml_node node, const char *name)
185 {
186         pugi::xml_attribute attr = node.attribute(name);
187
188         if(attr) {
189                 *str = ustring(attr.value());
190                 return true;
191         }
192
193         return false;
194 }
195
196 static bool xml_equal_string(pugi::xml_node node, const char *name, const char *value)
197 {
198         pugi::xml_attribute attr = node.attribute(name);
199
200         if(attr)
201                 return string_iequals(attr.value(), value);
202         
203         return false;
204 }
205
206 static bool xml_read_enum(ustring *str, ShaderEnum& enm, pugi::xml_node node, const char *name)
207 {
208         pugi::xml_attribute attr = node.attribute(name);
209
210         if(attr) {
211                 ustring ustr(attr.value());
212
213                 if(enm.exists(ustr)) {
214                         *str = ustr;
215                         return true;
216                 }
217                 else
218                         fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name);
219         }
220
221         return false;
222 }
223
224 /* Film */
225
226 static void xml_read_film(const XMLReadState& state, pugi::xml_node node)
227 {
228         Camera *cam = state.scene->camera;
229
230         xml_read_int(&cam->width, node, "width");
231         xml_read_int(&cam->height, node, "height");
232
233         float aspect = (float)cam->width/(float)cam->height;
234
235         if(cam->width >= cam->height) {
236                 cam->left = -aspect;
237                 cam->right = aspect;
238                 cam->bottom = -1.0f;
239                 cam->top = 1.0f;
240         }
241         else {
242                 cam->left = -1.0f;
243                 cam->right = 1.0f;
244                 cam->bottom = -1.0f/aspect;
245                 cam->top = 1.0f/aspect;
246         }
247
248         cam->need_update = true;
249         cam->update();
250 }
251
252 /* Integrator */
253
254 static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
255 {
256         Integrator *integrator = state.scene->integrator;
257
258         xml_read_int(&integrator->min_bounce, node, "min_bounce");
259         xml_read_int(&integrator->max_bounce, node, "max_bounce");
260         xml_read_bool(&integrator->no_caustics, node, "no_caustics");
261         xml_read_float(&integrator->blur_caustics, node, "blur_caustics");
262 }
263
264 /* Camera */
265
266 static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
267 {
268         Camera *cam = state.scene->camera;
269
270         if(xml_read_float(&cam->fov, node, "fov"))
271                 cam->fov *= M_PI/180.0f;
272
273         xml_read_float(&cam->nearclip, node, "nearclip");
274         xml_read_float(&cam->farclip, node, "farclip");
275         xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop
276         xml_read_float(&cam->focaldistance, node, "focaldistance");
277         xml_read_float(&cam->shutteropen, node, "shutteropen");
278         xml_read_float(&cam->shutterclose, node, "shutterclose");
279
280         if(xml_equal_string(node, "type", "orthographic"))
281                 cam->ortho = true;
282         else if(xml_equal_string(node, "type", "perspective"))
283                 cam->ortho = false;
284
285         cam->matrix = state.tfm;
286
287         cam->need_update = true;
288         cam->update();
289 }
290
291 /* Shader */
292
293 static string xml_socket_name(const char *name)
294 {
295         string sname = name;
296         size_t i;
297
298         while((i = sname.find(" ")) != string::npos)
299                 sname.replace(i, 1, "");
300         
301         return sname;
302 }
303
304 static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pugi::xml_node graph_node)
305 {
306         ShaderGraph *graph = new ShaderGraph();
307
308         map<string, ShaderNode*> nodemap;
309
310         nodemap["output"] = graph->output();
311
312         for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
313                 ShaderNode *snode = NULL;
314
315                 if(string_iequals(node.name(), "image_texture")) {
316                         ImageTextureNode *img = new ImageTextureNode();
317
318                         xml_read_string(&img->filename, node, "src");
319                         img->filename = path_join(state.base, img->filename);
320
321                         snode = img;
322                 }
323                 else if(string_iequals(node.name(), "environment_texture")) {
324                         EnvironmentTextureNode *env = new EnvironmentTextureNode();
325
326                         xml_read_string(&env->filename, node, "src");
327                         env->filename = path_join(state.base, env->filename);
328
329                         snode = env;
330                 }
331                 else if(string_iequals(node.name(), "sky_texture")) {
332                         SkyTextureNode *sky = new SkyTextureNode();
333
334                         xml_read_float3(&sky->sun_direction, node, "sun_direction");
335                         xml_read_float(&sky->turbidity, node, "turbidity");
336                         
337                         snode = sky;
338                 }
339                 else if(string_iequals(node.name(), "noise_texture")) {
340                         snode = new NoiseTextureNode();
341                 }
342                 else if(string_iequals(node.name(), "blend_texture")) {
343                         BlendTextureNode *blend = new BlendTextureNode();
344                         xml_read_enum(&blend->progression, BlendTextureNode::progression_enum, node, "progression");
345                         xml_read_enum(&blend->axis, BlendTextureNode::axis_enum, node, "axis");
346                         snode = blend;
347                 }
348                 else if(string_iequals(node.name(), "clouds_texture")) {
349                         CloudsTextureNode *clouds = new CloudsTextureNode();
350                         xml_read_bool(&clouds->hard, node, "hard");
351                         xml_read_int(&clouds->depth, node, "depth");
352                         xml_read_enum(&clouds->basis, CloudsTextureNode::basis_enum, node, "basis");
353                         snode = clouds;
354                 }
355                 else if(string_iequals(node.name(), "voronoi_texture")) {
356                         VoronoiTextureNode *voronoi = new VoronoiTextureNode();
357                         xml_read_enum(&voronoi->distance_metric, VoronoiTextureNode::distance_metric_enum, node, "distance_metric");
358                         xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring");
359                         snode = voronoi;
360                 }
361                 else if(string_iequals(node.name(), "musgrave_texture")) {
362                         MusgraveTextureNode *musgrave = new MusgraveTextureNode();
363                         xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type");
364                         xml_read_enum(&musgrave->basis, MusgraveTextureNode::basis_enum, node, "basis");
365                         snode = musgrave;
366                 }
367                 else if(string_iequals(node.name(), "marble_texture")) {
368                         MarbleTextureNode *marble = new MarbleTextureNode();
369                         xml_read_enum(&marble->type, MarbleTextureNode::type_enum, node, "type");
370                         xml_read_enum(&marble->wave, MarbleTextureNode::wave_enum, node, "wave");
371                         xml_read_enum(&marble->basis, MarbleTextureNode::basis_enum, node, "basis");
372                         xml_read_bool(&marble->hard, node, "hard");
373                         xml_read_int(&marble->depth, node, "depth");
374                         snode = marble;
375                 }
376                 else if(string_iequals(node.name(), "magic_texture")) {
377                         MagicTextureNode *magic = new MagicTextureNode();
378                         xml_read_int(&magic->depth, node, "depth");
379                         snode = magic;
380                 }
381                 else if(string_iequals(node.name(), "stucci_texture")) {
382                         StucciTextureNode *stucci = new StucciTextureNode();
383                         xml_read_enum(&stucci->type, StucciTextureNode::type_enum, node, "type");
384                         xml_read_enum(&stucci->basis, StucciTextureNode::basis_enum, node, "basis");
385                         xml_read_bool(&stucci->hard, node, "hard");
386                         snode = stucci;
387                 }
388                 else if(string_iequals(node.name(), "distorted_noise_texture")) {
389                         DistortedNoiseTextureNode *dist = new DistortedNoiseTextureNode();
390                         xml_read_enum(&dist->basis, DistortedNoiseTextureNode::basis_enum, node, "basis");
391                         xml_read_enum(&dist->distortion_basis, DistortedNoiseTextureNode::basis_enum, node, "distortion_basis");
392                         snode = dist;
393                 }
394                 else if(string_iequals(node.name(), "wood_texture")) {
395                         WoodTextureNode *wood = new WoodTextureNode();
396                         xml_read_enum(&wood->type, WoodTextureNode::type_enum, node, "type");
397                         xml_read_enum(&wood->wave, WoodTextureNode::wave_enum, node, "wave");
398                         xml_read_enum(&wood->basis, WoodTextureNode::basis_enum, node, "basis");
399                         xml_read_bool(&wood->hard, node, "hard");
400                         snode = wood;
401                 }
402                 else if(string_iequals(node.name(), "mapping")) {
403                         snode = new MappingNode();
404                 }
405                 else if(string_iequals(node.name(), "ward_bsdf")) {
406                         snode = new WardBsdfNode();
407                 }
408                 else if(string_iequals(node.name(), "diffuse_bsdf")) {
409                         snode = new DiffuseBsdfNode();
410                 }
411                 else if(string_iequals(node.name(), "translucent_bsdf")) {
412                         snode = new TranslucentBsdfNode();
413                 }
414                 else if(string_iequals(node.name(), "transparent_bsdf")) {
415                         snode = new TransparentBsdfNode();
416                 }
417                 else if(string_iequals(node.name(), "velvet_bsdf")) {
418                         snode = new VelvetBsdfNode();
419                 }
420                 else if(string_iequals(node.name(), "glossy_bsdf")) {
421                         GlossyBsdfNode *glossy = new GlossyBsdfNode();
422                         xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution");
423                         snode = glossy;
424                 }
425                 else if(string_iequals(node.name(), "glass_bsdf")) {
426                         GlassBsdfNode *diel = new GlassBsdfNode();
427                         xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution");
428                         snode = diel;
429                 }
430                 else if(string_iequals(node.name(), "emission")) {
431                         EmissionNode *emission = new EmissionNode();
432                         xml_read_bool(&emission->total_power, node, "total_power");
433                         snode = emission;
434                 }
435                 else if(string_iequals(node.name(), "background")) {
436                         snode = new BackgroundNode();
437                 }
438                 else if(string_iequals(node.name(), "geometry")) {
439                         snode = new GeometryNode();
440                 }
441                 else if(string_iequals(node.name(), "texture_coordinate")) {
442                         snode = new TextureCoordinateNode();
443                 }
444                 else if(string_iequals(node.name(), "lightPath")) {
445                         snode = new LightPathNode();
446                 }
447                 else if(string_iequals(node.name(), "value")) {
448                         ValueNode *value = new ValueNode();
449                         xml_read_float(&value->value, node, "value");
450                         snode = value;
451                 }
452                 else if(string_iequals(node.name(), "color")) {
453                         ColorNode *color = new ColorNode();
454                         xml_read_float3(&color->value, node, "value");
455                         snode = color;
456                 }
457                 else if(string_iequals(node.name(), "mix_closure")) {
458                         snode = new MixClosureNode();
459                 }
460                 else if(string_iequals(node.name(), "add_closure")) {
461                         snode = new AddClosureNode();
462                 }
463                 else if(string_iequals(node.name(), "mix")) {
464                         MixNode *mix = new MixNode();
465                         xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
466                         snode = mix;
467                 }
468                 else if(string_iequals(node.name(), "attribute")) {
469                         AttributeNode *attr = new AttributeNode();
470                         xml_read_ustring(&attr->attribute, node, "attribute");
471                         snode = attr;
472                 }
473                 else if(string_iequals(node.name(), "fresnel")) {
474                         snode = new FresnelNode();
475                 }
476                 else if(string_iequals(node.name(), "math")) {
477                         MathNode *math = new MathNode();
478                         xml_read_enum(&math->type, MathNode::type_enum, node, "type");
479                         snode = math;
480                 }
481                 else if(string_iequals(node.name(), "vector_math")) {
482                         VectorMathNode *vmath = new VectorMathNode();
483                         xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type");
484                         snode = vmath;
485                 }
486                 else if(string_iequals(node.name(), "connect")) {
487                         /* connect nodes */
488                         vector<string> from_tokens, to_tokens;
489
490                         string_split(from_tokens, node.attribute("from").value());
491                         string_split(to_tokens, node.attribute("to").value());
492
493                         if(from_tokens.size() == 2 && to_tokens.size() == 2) {
494                                 /* find nodes and sockets */
495                                 ShaderOutput *output = NULL;
496                                 ShaderInput *input = NULL;
497
498                                 if(nodemap.find(from_tokens[0]) != nodemap.end()) {
499                                         ShaderNode *fromnode = nodemap[from_tokens[0]];
500
501                                         foreach(ShaderOutput *out, fromnode->outputs)
502                                                 if(string_iequals(xml_socket_name(out->name), from_tokens[1]))
503                                                         output = out;
504
505                                         if(!output)
506                                                 fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_tokens[1].c_str(), from_tokens[0].c_str());
507                                 }
508                                 else
509                                         fprintf(stderr, "Unknown shader node name \"%s\".\n", from_tokens[0].c_str());
510
511                                 if(nodemap.find(to_tokens[0]) != nodemap.end()) {
512                                         ShaderNode *tonode = nodemap[to_tokens[0]];
513
514                                         foreach(ShaderInput *in, tonode->inputs)
515                                                 if(string_iequals(xml_socket_name(in->name), to_tokens[1]))
516                                                         input = in;
517
518                                         if(!input)
519                                                 fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_tokens[1].c_str(), to_tokens[0].c_str());
520                                 }
521                                 else
522                                         fprintf(stderr, "Unknown shader node name \"%s\".\n", to_tokens[0].c_str());
523
524                                 /* connect */
525                                 if(output && input)
526                                         graph->connect(output, input);
527                         }
528                         else
529                                 fprintf(stderr, "Invalid from or to value for connect node.\n");
530                 }
531                 else
532                         fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
533
534                 if(snode) {
535                         /* add to graph */
536                         graph->add(snode);
537
538                         /* add to map for name lookups */
539                         string name = "";
540                         xml_read_string(&name, node, "name");
541
542                         nodemap[name] = snode;
543
544                         /* read input values */
545                         for(pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
546                                 foreach(ShaderInput *in, snode->inputs) {
547                                         if(string_iequals(in->name, attr.name())) {
548                                                 switch(in->type) {
549                                                         case SHADER_SOCKET_FLOAT:
550                                                                 xml_read_float(&in->value.x, node, attr.name());
551                                                                 break;
552                                                         case SHADER_SOCKET_COLOR:
553                                                         case SHADER_SOCKET_VECTOR:
554                                                         case SHADER_SOCKET_POINT:
555                                                         case SHADER_SOCKET_NORMAL:
556                                                                 xml_read_float3(&in->value, node, attr.name());
557                                                                 break;
558                                                         default:
559                                                                 break;
560                                                 }
561                                         }
562                                 }
563                         }
564                 }
565         }
566
567         shader->set_graph(graph);
568         shader->tag_update(state.scene);
569 }
570
571 static void xml_read_shader(const XMLReadState& state, pugi::xml_node node)
572 {
573         Shader *shader = new Shader();
574         xml_read_string(&shader->name, node, "name");
575         xml_read_shader_graph(state, shader, node);
576         state.scene->shaders.push_back(shader);
577 }
578
579 /* Background */
580
581 static void xml_read_background(const XMLReadState& state, pugi::xml_node node)
582 {
583         Shader *shader = state.scene->shaders[state.scene->default_background];
584
585         xml_read_shader_graph(state, shader, node);
586 }
587
588 /* Mesh */
589
590 static Mesh *xml_add_mesh(Scene *scene, const Transform& tfm)
591 {
592         /* create mesh */
593         Mesh *mesh = new Mesh();
594         scene->meshes.push_back(mesh);
595
596         /* create object*/
597         Object *object = new Object();
598         object->mesh = mesh;
599         object->tfm = tfm;
600         scene->objects.push_back(object);
601
602         return mesh;
603 }
604
605 static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
606 {
607         /* add mesh */
608         Mesh *mesh = xml_add_mesh(state.scene, state.tfm);
609         mesh->used_shaders.push_back(state.shader);
610
611         /* read state */
612         int shader = state.shader;
613         bool smooth = state.smooth;
614
615         mesh->displacement_method = state.displacement_method;
616
617         /* read vertices and polygons, RIB style */
618         vector<float3> P;
619         vector<int> verts, nverts;
620
621         xml_read_float3_array(P, node, "P");
622         xml_read_int_array(verts, node, "verts");
623         xml_read_int_array(nverts, node, "nverts");
624
625         if(xml_equal_string(node, "subdivision", "catmull-clark")) {
626                 /* create subd mesh */
627                 SubdMesh sdmesh;
628
629                 /* create subd vertices */
630                 for(size_t i = 0; i < P.size(); i++)
631                         sdmesh.add_vert(P[i]);
632
633                 /* create subd faces */
634                 int index_offset = 0;
635
636                 for(size_t i = 0; i < nverts.size(); i++) {
637                         if(nverts[i] == 4) {
638                                 int v0 = verts[index_offset + 0];
639                                 int v1 = verts[index_offset + 1];
640                                 int v2 = verts[index_offset + 2];
641                                 int v3 = verts[index_offset + 3];
642
643                                 sdmesh.add_face(v0, v1, v2, v3);
644                         }
645                         else {
646                                 for(int j = 0; j < nverts[i]-2; j++) {
647                                         int v0 = verts[index_offset];
648                                         int v1 = verts[index_offset + j + 1];
649                                         int v2 = verts[index_offset + j + 2];;
650
651                                         sdmesh.add_face(v0, v1, v2);
652                                 }
653                         }
654
655                         index_offset += nverts[i];
656                 }
657
658                 /* finalize subd mesh */
659                 sdmesh.link_boundary();
660
661                 /* subdivide */
662                 DiagSplit dsplit;
663                 //dsplit.camera = state.scene->camera;
664                 //dsplit.dicing_rate = 5.0f;
665                 dsplit.dicing_rate = state.dicing_rate;
666                 xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
667                 sdmesh.tesselate(&dsplit, false, mesh, shader, smooth);
668         }
669         else {
670                 /* create vertices */
671                 mesh->verts = P;
672
673                 /* create triangles */
674                 int index_offset = 0;
675
676                 for(size_t i = 0; i < nverts.size(); i++) {
677                         for(int j = 0; j < nverts[i]-2; j++) {
678                                 int v0 = verts[index_offset];
679                                 int v1 = verts[index_offset + j + 1];
680                                 int v2 = verts[index_offset + j + 2];
681
682                                 assert(v0 < (int)P.size());
683                                 assert(v1 < (int)P.size());
684                                 assert(v2 < (int)P.size());
685
686                                 mesh->add_triangle(v0, v1, v2, shader, smooth);
687                         }
688
689                         index_offset += nverts[i];
690                 }
691         }
692
693         /* temporary for test compatibility */
694         mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL);
695 }
696
697 /* Patch */
698
699 static void xml_read_patch(const XMLReadState& state, pugi::xml_node node)
700 {
701         /* read patch */
702         Patch *patch = NULL;
703
704         vector<float3> P;
705         xml_read_float3_array(P, node, "P");
706
707         if(xml_equal_string(node, "type", "bilinear")) {
708                 /* bilinear patch */
709                 if(P.size() == 4) {
710                         LinearQuadPatch *bpatch = new LinearQuadPatch();
711
712                         for(int i = 0; i < 4; i++)
713                                 P[i] = transform(&state.tfm, P[i]);
714                         memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull));
715
716                         patch = bpatch;
717                 }
718                 else
719                         fprintf(stderr, "Invalid number of control points for bilinear patch.\n");
720         }
721         else if(xml_equal_string(node, "type", "bicubic")) {
722                 /* bicubic patch */
723                 if(P.size() == 16) {
724                         BicubicPatch *bpatch = new BicubicPatch();
725
726                         for(int i = 0; i < 16; i++)
727                                 P[i] = transform(&state.tfm, P[i]);
728                         memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull));
729
730                         patch = bpatch;
731                 }
732                 else
733                         fprintf(stderr, "Invalid number of control points for bicubic patch.\n");
734         }
735         else
736                 fprintf(stderr, "Unknown patch type.\n");
737
738         if(patch) {
739                 /* add mesh */
740                 Mesh *mesh = xml_add_mesh(state.scene, transform_identity());
741
742                 mesh->used_shaders.push_back(state.shader);
743
744                 /* split */
745                 DiagSplit dsplit;
746                 //dsplit.camera = state.scene->camera;
747                 //dsplit.dicing_rate = 5.0f;
748                 dsplit.dicing_rate = state.dicing_rate;
749                 xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
750                 dsplit.split_quad(mesh, patch, state.shader, state.smooth);
751
752                 delete patch;
753
754                 /* temporary for test compatibility */
755                 mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL);
756         }
757 }
758
759 /* Light */
760
761 static void xml_read_light(const XMLReadState& state, pugi::xml_node node)
762 {
763         Light *light = new Light();
764         light->shader = state.shader;
765         xml_read_float3(&light->co, node, "P");
766         light->co = transform(&state.tfm, light->co);
767
768         state.scene->lights.push_back(light);
769 }
770
771 /* Transform */
772
773 static void xml_read_transform(pugi::xml_node node, Transform& tfm)
774 {
775         if(node.attribute("matrix")) {
776                 vector<float> matrix;
777                 if(xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16)
778                         tfm = tfm * transform_transpose((*(Transform*)&matrix[0]));
779         }
780
781         if(node.attribute("translate")) {
782                 float3 translate = make_float3(0.0f, 0.0f, 0.0f);
783                 xml_read_float3(&translate, node, "translate");
784                 tfm = tfm * transform_translate(translate);
785         }
786
787         if(node.attribute("rotate")) {
788                 float4 rotate = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
789                 xml_read_float4(&rotate, node, "rotate");
790                 tfm = tfm * transform_rotate(rotate.x*M_PI/180.0f, make_float3(rotate.y, rotate.z, rotate.w));
791         }
792
793         if(node.attribute("scale")) {
794                 float3 scale = make_float3(0.0f, 0.0f, 0.0f);
795                 xml_read_float3(&scale, node, "scale");
796                 tfm = tfm * transform_scale(scale);
797         }
798 }
799
800 /* State */
801
802 static void xml_read_state(XMLReadState& state, pugi::xml_node node)
803 {
804         /* read shader */
805         string shadername;
806
807         if(xml_read_string(&shadername, node, "shader")) {
808                 int i = 0;
809                 bool found = false;
810
811                 foreach(Shader *shader, state.scene->shaders) {
812                         if(shader->name == shadername) {
813                                 state.shader = i;
814                                 found = true;
815                                 break;
816                         }
817
818                         i++;
819                 }
820
821                 if(!found)
822                         fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str());
823         }
824
825         xml_read_float(&state.dicing_rate, node, "dicing_rate");
826
827         /* read smooth/flat */
828         if(xml_equal_string(node, "interpolation", "smooth"))
829                 state.smooth = true;
830         else if(xml_equal_string(node, "interpolation", "flat"))
831                 state.smooth = false;
832
833         /* read displacement method */
834         if(xml_equal_string(node, "displacement_method", "true"))
835                 state.displacement_method = Mesh::DISPLACE_TRUE;
836         else if(xml_equal_string(node, "displacement_method", "bump"))
837                 state.displacement_method = Mesh::DISPLACE_BUMP;
838         else if(xml_equal_string(node, "displacement_method", "both"))
839                 state.displacement_method = Mesh::DISPLACE_BOTH;
840 }
841
842 /* Scene */
843
844 static void xml_read_include(const XMLReadState& state, const string& src);
845
846 static void xml_read_scene(const XMLReadState& state, pugi::xml_node scene_node)
847 {
848         for(pugi::xml_node node = scene_node.first_child(); node; node = node.next_sibling()) {
849                 if(string_iequals(node.name(), "film")) {
850                         xml_read_film(state, node);
851                 }
852                 else if(string_iequals(node.name(), "integrator")) {
853                         xml_read_integrator(state, node);
854                 }
855                 else if(string_iequals(node.name(), "camera")) {
856                         xml_read_camera(state, node);
857                 }
858                 else if(string_iequals(node.name(), "shader")) {
859                         xml_read_shader(state, node);
860                 }
861                 else if(string_iequals(node.name(), "background")) {
862                         xml_read_background(state, node);
863                 }
864                 else if(string_iequals(node.name(), "mesh")) {
865                         xml_read_mesh(state, node);
866                 }
867                 else if(string_iequals(node.name(), "patch")) {
868                         xml_read_patch(state, node);
869                 }
870                 else if(string_iequals(node.name(), "light")) {
871                         xml_read_light(state, node);
872                 }
873                 else if(string_iequals(node.name(), "transform")) {
874                         XMLReadState substate = state;
875
876                         xml_read_transform(node, substate.tfm);
877                         xml_read_scene(substate, node);
878                 }
879                 else if(string_iequals(node.name(), "state")) {
880                         XMLReadState substate = state;
881
882                         xml_read_state(substate, node);
883                         xml_read_scene(substate, node);
884                 }
885                 else if(string_iequals(node.name(), "include")) {
886                         string src;
887
888                         if(xml_read_string(&src, node, "src"))
889                                 xml_read_include(state, src);
890                 }
891                 else
892                         fprintf(stderr, "Unknown node \"%s\".\n", node.name());
893         }
894 }
895
896 /* Include */
897
898 static void xml_read_include(const XMLReadState& state, const string& src)
899 {
900         /* open XML document */
901         pugi::xml_document doc;
902         pugi::xml_parse_result parse_result;
903
904         string path = path_join(state.base, src);
905         parse_result = doc.load_file(path.c_str());
906
907         if(parse_result) {
908                 XMLReadState substate = state;
909                 substate.base = path_dirname(path);
910
911                 xml_read_scene(substate, doc);
912         }
913         else
914                 fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description());
915 }
916
917 /* File */
918
919 void xml_read_file(Scene *scene, const char *filepath)
920 {
921         XMLReadState state;
922
923         state.scene = scene;
924         state.tfm = transform_identity();
925         state.shader = scene->default_surface;
926         state.smooth = false;
927         state.dicing_rate = 0.1f;
928         state.base = path_dirname(filepath);
929
930         xml_read_include(state, path_filename(filepath));
931
932         scene->params.bvh_type = SceneParams::BVH_STATIC;
933 }
934
935 CCL_NAMESPACE_END
936