Blender V2.61 - r43446

cycles_xml.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <stdio.h>
00020 
00021 #include <sstream>
00022 #include <algorithm>
00023 #include <iterator>
00024 
00025 #include "camera.h"
00026 #include "film.h"
00027 #include "graph.h"
00028 #include "integrator.h"
00029 #include "light.h"
00030 #include "mesh.h"
00031 #include "nodes.h"
00032 #include "object.h"
00033 #include "shader.h"
00034 #include "scene.h"
00035 
00036 #include "subd_mesh.h"
00037 #include "subd_patch.h"
00038 #include "subd_split.h"
00039 
00040 #include "util_debug.h"
00041 #include "util_foreach.h"
00042 #include "util_path.h"
00043 #include "util_transform.h"
00044 #include "util_xml.h"
00045 
00046 #include "cycles_xml.h"
00047 
00048 CCL_NAMESPACE_BEGIN
00049 
00050 /* XML reading state */
00051 
00052 struct XMLReadState {
00053     Scene *scene;       /* scene pointer */
00054     Transform tfm;      /* current transform state */
00055     bool smooth;        /* smooth normal state */
00056     int shader;         /* current shader */
00057     string base;        /* base path to current file*/
00058     float dicing_rate;  /* current dicing rate */
00059     Mesh::DisplacementMethod displacement_method;
00060 };
00061 
00062 /* Attribute Reading */
00063 
00064 static bool xml_read_bool(bool *value, pugi::xml_node node, const char *name)
00065 {
00066     pugi::xml_attribute attr = node.attribute(name);
00067 
00068     if(attr) {
00069         *value = (string_iequals(attr.value(), "true")) || (atoi(attr.value()) != 0);
00070         return true;
00071     }
00072 
00073     return false;
00074 }
00075 
00076 static bool xml_read_int(int *value, pugi::xml_node node, const char *name)
00077 {
00078     pugi::xml_attribute attr = node.attribute(name);
00079 
00080     if(attr) {
00081         *value = atoi(attr.value());
00082         return true;
00083     }
00084 
00085     return false;
00086 }
00087 
00088 static bool xml_read_int_array(vector<int>& value, pugi::xml_node node, const char *name)
00089 {
00090     pugi::xml_attribute attr = node.attribute(name);
00091 
00092     if(attr) {
00093         vector<string> tokens;
00094         string_split(tokens, attr.value());
00095 
00096         foreach(const string& token, tokens)
00097             value.push_back(atoi(token.c_str()));
00098 
00099         return true;
00100     }
00101 
00102     return false;
00103 }
00104 
00105 static bool xml_read_float(float *value, pugi::xml_node node, const char *name)
00106 {
00107     pugi::xml_attribute attr = node.attribute(name);
00108 
00109     if(attr) {
00110         *value = atof(attr.value());
00111         return true;
00112     }
00113 
00114     return false;
00115 }
00116 
00117 static bool xml_read_float_array(vector<float>& value, pugi::xml_node node, const char *name)
00118 {
00119     pugi::xml_attribute attr = node.attribute(name);
00120 
00121     if(attr) {
00122         vector<string> tokens;
00123         string_split(tokens, attr.value());
00124 
00125         foreach(const string& token, tokens)
00126             value.push_back(atof(token.c_str()));
00127 
00128         return true;
00129     }
00130 
00131     return false;
00132 }
00133 
00134 static bool xml_read_float3(float3 *value, pugi::xml_node node, const char *name)
00135 {
00136     vector<float> array;
00137 
00138     if(xml_read_float_array(array, node, name) && array.size() == 3) {
00139         *value = make_float3(array[0], array[1], array[2]);
00140         return true;
00141     }
00142 
00143     return false;
00144 }
00145 
00146 static bool xml_read_float3_array(vector<float3>& value, pugi::xml_node node, const char *name)
00147 {
00148     vector<float> array;
00149 
00150     if(xml_read_float_array(array, node, name)) {
00151         for(size_t i = 0; i < array.size(); i += 3)
00152             value.push_back(make_float3(array[i+0], array[i+1], array[i+2]));
00153 
00154         return true;
00155     }
00156 
00157     return false;
00158 }
00159 
00160 static bool xml_read_float4(float4 *value, pugi::xml_node node, const char *name)
00161 {
00162     vector<float> array;
00163 
00164     if(xml_read_float_array(array, node, name) && array.size() == 4) {
00165         *value = make_float4(array[0], array[1], array[2], array[3]);
00166         return true;
00167     }
00168 
00169     return false;
00170 }
00171 
00172 static bool xml_read_string(string *str, pugi::xml_node node, const char *name)
00173 {
00174     pugi::xml_attribute attr = node.attribute(name);
00175 
00176     if(attr) {
00177         *str = attr.value();
00178         return true;
00179     }
00180 
00181     return false;
00182 }
00183 
00184 static bool xml_read_ustring(ustring *str, pugi::xml_node node, const char *name)
00185 {
00186     pugi::xml_attribute attr = node.attribute(name);
00187 
00188     if(attr) {
00189         *str = ustring(attr.value());
00190         return true;
00191     }
00192 
00193     return false;
00194 }
00195 
00196 static bool xml_equal_string(pugi::xml_node node, const char *name, const char *value)
00197 {
00198     pugi::xml_attribute attr = node.attribute(name);
00199 
00200     if(attr)
00201         return string_iequals(attr.value(), value);
00202     
00203     return false;
00204 }
00205 
00206 static bool xml_read_enum(ustring *str, ShaderEnum& enm, pugi::xml_node node, const char *name)
00207 {
00208     pugi::xml_attribute attr = node.attribute(name);
00209 
00210     if(attr) {
00211         ustring ustr(attr.value());
00212 
00213         if(enm.exists(ustr)) {
00214             *str = ustr;
00215             return true;
00216         }
00217         else
00218             fprintf(stderr, "Unknown value \"%s\" for attribute \"%s\".\n", ustr.c_str(), name);
00219     }
00220 
00221     return false;
00222 }
00223 
00224 /* Film */
00225 
00226 static void xml_read_film(const XMLReadState& state, pugi::xml_node node)
00227 {
00228     Camera *cam = state.scene->camera;
00229 
00230     xml_read_int(&cam->width, node, "width");
00231     xml_read_int(&cam->height, node, "height");
00232 
00233     float aspect = (float)cam->width/(float)cam->height;
00234 
00235     if(cam->width >= cam->height) {
00236         cam->left = -aspect;
00237         cam->right = aspect;
00238         cam->bottom = -1.0f;
00239         cam->top = 1.0f;
00240     }
00241     else {
00242         cam->left = -1.0f;
00243         cam->right = 1.0f;
00244         cam->bottom = -1.0f/aspect;
00245         cam->top = 1.0f/aspect;
00246     }
00247 
00248     cam->need_update = true;
00249     cam->update();
00250 }
00251 
00252 /* Integrator */
00253 
00254 static void xml_read_integrator(const XMLReadState& state, pugi::xml_node node)
00255 {
00256     Integrator *integrator = state.scene->integrator;
00257 
00258     xml_read_int(&integrator->min_bounce, node, "min_bounce");
00259     xml_read_int(&integrator->max_bounce, node, "max_bounce");
00260     
00261     xml_read_int(&integrator->max_diffuse_bounce, node, "max_diffuse_bounce");
00262     xml_read_int(&integrator->max_glossy_bounce, node, "max_glossy_bounce");
00263     xml_read_int(&integrator->max_transmission_bounce, node, "max_transmission_bounce");
00264     
00265     xml_read_int(&integrator->transparent_min_bounce, node, "transparent_min_bounce");
00266     xml_read_int(&integrator->transparent_max_bounce, node, "transparent_max_bounce");
00267     
00268     xml_read_bool(&integrator->transparent_shadows, node, "transparent_shadows");
00269     xml_read_bool(&integrator->no_caustics, node, "no_caustics");
00270     
00271     xml_read_int(&integrator->seed, node, "seed");
00272 }
00273 
00274 /* Camera */
00275 
00276 static void xml_read_camera(const XMLReadState& state, pugi::xml_node node)
00277 {
00278     Camera *cam = state.scene->camera;
00279 
00280     if(xml_read_float(&cam->fov, node, "fov"))
00281         cam->fov *= M_PI/180.0f;
00282 
00283     xml_read_float(&cam->nearclip, node, "nearclip");
00284     xml_read_float(&cam->farclip, node, "farclip");
00285     xml_read_float(&cam->aperturesize, node, "aperturesize"); // 0.5*focallength/fstop
00286     xml_read_float(&cam->focaldistance, node, "focaldistance");
00287     xml_read_float(&cam->shutteropen, node, "shutteropen");
00288     xml_read_float(&cam->shutterclose, node, "shutterclose");
00289 
00290     if(xml_equal_string(node, "type", "orthographic"))
00291         cam->ortho = true;
00292     else if(xml_equal_string(node, "type", "perspective"))
00293         cam->ortho = false;
00294 
00295     cam->matrix = state.tfm;
00296 
00297     cam->need_update = true;
00298     cam->update();
00299 }
00300 
00301 /* Shader */
00302 
00303 static string xml_socket_name(const char *name)
00304 {
00305     string sname = name;
00306     size_t i;
00307 
00308     while((i = sname.find(" ")) != string::npos)
00309         sname.replace(i, 1, "");
00310     
00311     return sname;
00312 }
00313 
00314 static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pugi::xml_node graph_node)
00315 {
00316     ShaderGraph *graph = new ShaderGraph();
00317 
00318     map<string, ShaderNode*> nodemap;
00319 
00320     nodemap["output"] = graph->output();
00321 
00322     for(pugi::xml_node node = graph_node.first_child(); node; node = node.next_sibling()) {
00323         ShaderNode *snode = NULL;
00324 
00325         if(string_iequals(node.name(), "image_texture")) {
00326             ImageTextureNode *img = new ImageTextureNode();
00327 
00328             xml_read_string(&img->filename, node, "src");
00329             img->filename = path_join(state.base, img->filename);
00330 
00331             snode = img;
00332         }
00333         else if(string_iequals(node.name(), "environment_texture")) {
00334             EnvironmentTextureNode *env = new EnvironmentTextureNode();
00335 
00336             xml_read_string(&env->filename, node, "src");
00337             env->filename = path_join(state.base, env->filename);
00338 
00339             snode = env;
00340         }
00341         else if(string_iequals(node.name(), "sky_texture")) {
00342             SkyTextureNode *sky = new SkyTextureNode();
00343 
00344             xml_read_float3(&sky->sun_direction, node, "sun_direction");
00345             xml_read_float(&sky->turbidity, node, "turbidity");
00346             
00347             snode = sky;
00348         }
00349         else if(string_iequals(node.name(), "noise_texture")) {
00350             snode = new NoiseTextureNode();
00351         }
00352         else if(string_iequals(node.name(), "checker_texture")) {
00353             snode = new CheckerTextureNode();
00354         }
00355         else if(string_iequals(node.name(), "gradient_texture")) {
00356             GradientTextureNode *blend = new GradientTextureNode();
00357             xml_read_enum(&blend->type, GradientTextureNode::type_enum, node, "type");
00358             snode = blend;
00359         }
00360         else if(string_iequals(node.name(), "voronoi_texture")) {
00361             VoronoiTextureNode *voronoi = new VoronoiTextureNode();
00362             xml_read_enum(&voronoi->coloring, VoronoiTextureNode::coloring_enum, node, "coloring");
00363             snode = voronoi;
00364         }
00365         else if(string_iequals(node.name(), "musgrave_texture")) {
00366             MusgraveTextureNode *musgrave = new MusgraveTextureNode();
00367             xml_read_enum(&musgrave->type, MusgraveTextureNode::type_enum, node, "type");
00368             snode = musgrave;
00369         }
00370         else if(string_iequals(node.name(), "magic_texture")) {
00371             MagicTextureNode *magic = new MagicTextureNode();
00372             xml_read_int(&magic->depth, node, "depth");
00373             snode = magic;
00374         }
00375         else if(string_iequals(node.name(), "noise_texture")) {
00376             NoiseTextureNode *dist = new NoiseTextureNode();
00377             snode = dist;
00378         }
00379         else if(string_iequals(node.name(), "wave_texture")) {
00380             WaveTextureNode *wood = new WaveTextureNode();
00381             xml_read_enum(&wood->type, WaveTextureNode::type_enum, node, "type");
00382             snode = wood;
00383         }
00384         else if(string_iequals(node.name(), "normal")) {
00385             snode = new NormalNode();
00386         }
00387         else if(string_iequals(node.name(), "mapping")) {
00388             snode = new MappingNode();
00389         }
00390         else if(string_iequals(node.name(), "ward_bsdf")) {
00391             snode = new WardBsdfNode();
00392         }
00393         else if(string_iequals(node.name(), "diffuse_bsdf")) {
00394             snode = new DiffuseBsdfNode();
00395         }
00396         else if(string_iequals(node.name(), "translucent_bsdf")) {
00397             snode = new TranslucentBsdfNode();
00398         }
00399         else if(string_iequals(node.name(), "transparent_bsdf")) {
00400             snode = new TransparentBsdfNode();
00401         }
00402         else if(string_iequals(node.name(), "velvet_bsdf")) {
00403             snode = new VelvetBsdfNode();
00404         }
00405         else if(string_iequals(node.name(), "glossy_bsdf")) {
00406             GlossyBsdfNode *glossy = new GlossyBsdfNode();
00407             xml_read_enum(&glossy->distribution, GlossyBsdfNode::distribution_enum, node, "distribution");
00408             snode = glossy;
00409         }
00410         else if(string_iequals(node.name(), "glass_bsdf")) {
00411             GlassBsdfNode *diel = new GlassBsdfNode();
00412             xml_read_enum(&diel->distribution, GlassBsdfNode::distribution_enum, node, "distribution");
00413             snode = diel;
00414         }
00415         else if(string_iequals(node.name(), "emission")) {
00416             EmissionNode *emission = new EmissionNode();
00417             xml_read_bool(&emission->total_power, node, "total_power");
00418             snode = emission;
00419         }
00420         else if(string_iequals(node.name(), "background")) {
00421             snode = new BackgroundNode();
00422         }
00423         else if(string_iequals(node.name(), "transparent_volume")) {
00424             snode = new TransparentVolumeNode();
00425         }
00426         else if(string_iequals(node.name(), "isotropic_volume")) {
00427             snode = new IsotropicVolumeNode();
00428         }
00429         else if(string_iequals(node.name(), "geometry")) {
00430             snode = new GeometryNode();
00431         }
00432         else if(string_iequals(node.name(), "texture_coordinate")) {
00433             snode = new TextureCoordinateNode();
00434         }
00435         else if(string_iequals(node.name(), "lightPath")) {
00436             snode = new LightPathNode();
00437         }
00438         else if(string_iequals(node.name(), "value")) {
00439             ValueNode *value = new ValueNode();
00440             xml_read_float(&value->value, node, "value");
00441             snode = value;
00442         }
00443         else if(string_iequals(node.name(), "color")) {
00444             ColorNode *color = new ColorNode();
00445             xml_read_float3(&color->value, node, "value");
00446             snode = color;
00447         }
00448         else if(string_iequals(node.name(), "mix_closure")) {
00449             snode = new MixClosureNode();
00450         }
00451         else if(string_iequals(node.name(), "add_closure")) {
00452             snode = new AddClosureNode();
00453         }
00454         else if(string_iequals(node.name(), "invert")) {
00455             snode = new InvertNode();
00456         }
00457         else if(string_iequals(node.name(), "mix")) {
00458             MixNode *mix = new MixNode();
00459             xml_read_enum(&mix->type, MixNode::type_enum, node, "type");
00460             snode = mix;
00461         }
00462         else if(string_iequals(node.name(), "gamma")) {
00463             snode = new GammaNode();
00464         }
00465         else if(string_iequals(node.name(), "combine_rgb")) {
00466             snode = new CombineRGBNode();
00467         }
00468         else if(string_iequals(node.name(), "separate_rgb")) {
00469             snode = new SeparateRGBNode();
00470         }
00471         else if(string_iequals(node.name(), "hsv")) {
00472             snode = new HSVNode();
00473         }
00474         else if(string_iequals(node.name(), "attribute")) {
00475             AttributeNode *attr = new AttributeNode();
00476             xml_read_ustring(&attr->attribute, node, "attribute");
00477             snode = attr;
00478         }
00479         else if(string_iequals(node.name(), "camera")) {
00480             snode = new CameraNode();
00481         }
00482         else if(string_iequals(node.name(), "fresnel")) {
00483             snode = new FresnelNode();
00484         }
00485         else if(string_iequals(node.name(), "math")) {
00486             MathNode *math = new MathNode();
00487             xml_read_enum(&math->type, MathNode::type_enum, node, "type");
00488             snode = math;
00489         }
00490         else if(string_iequals(node.name(), "vector_math")) {
00491             VectorMathNode *vmath = new VectorMathNode();
00492             xml_read_enum(&vmath->type, VectorMathNode::type_enum, node, "type");
00493             snode = vmath;
00494         }
00495         else if(string_iequals(node.name(), "connect")) {
00496             /* connect nodes */
00497             vector<string> from_tokens, to_tokens;
00498 
00499             string_split(from_tokens, node.attribute("from").value());
00500             string_split(to_tokens, node.attribute("to").value());
00501 
00502             if(from_tokens.size() == 2 && to_tokens.size() == 2) {
00503                 /* find nodes and sockets */
00504                 ShaderOutput *output = NULL;
00505                 ShaderInput *input = NULL;
00506 
00507                 if(nodemap.find(from_tokens[0]) != nodemap.end()) {
00508                     ShaderNode *fromnode = nodemap[from_tokens[0]];
00509 
00510                     foreach(ShaderOutput *out, fromnode->outputs)
00511                         if(string_iequals(xml_socket_name(out->name), from_tokens[1]))
00512                             output = out;
00513 
00514                     if(!output)
00515                         fprintf(stderr, "Unknown output socket name \"%s\" on \"%s\".\n", from_tokens[1].c_str(), from_tokens[0].c_str());
00516                 }
00517                 else
00518                     fprintf(stderr, "Unknown shader node name \"%s\".\n", from_tokens[0].c_str());
00519 
00520                 if(nodemap.find(to_tokens[0]) != nodemap.end()) {
00521                     ShaderNode *tonode = nodemap[to_tokens[0]];
00522 
00523                     foreach(ShaderInput *in, tonode->inputs)
00524                         if(string_iequals(xml_socket_name(in->name), to_tokens[1]))
00525                             input = in;
00526 
00527                     if(!input)
00528                         fprintf(stderr, "Unknown input socket name \"%s\" on \"%s\".\n", to_tokens[1].c_str(), to_tokens[0].c_str());
00529                 }
00530                 else
00531                     fprintf(stderr, "Unknown shader node name \"%s\".\n", to_tokens[0].c_str());
00532 
00533                 /* connect */
00534                 if(output && input)
00535                     graph->connect(output, input);
00536             }
00537             else
00538                 fprintf(stderr, "Invalid from or to value for connect node.\n");
00539         }
00540         else
00541             fprintf(stderr, "Unknown shader node \"%s\".\n", node.name());
00542 
00543         if(snode) {
00544             /* add to graph */
00545             graph->add(snode);
00546 
00547             /* add to map for name lookups */
00548             string name = "";
00549             xml_read_string(&name, node, "name");
00550 
00551             nodemap[name] = snode;
00552 
00553             /* read input values */
00554             for(pugi::xml_attribute attr = node.first_attribute(); attr; attr = attr.next_attribute()) {
00555                 foreach(ShaderInput *in, snode->inputs) {
00556                     if(string_iequals(in->name, attr.name())) {
00557                         switch(in->type) {
00558                             case SHADER_SOCKET_FLOAT:
00559                                 xml_read_float(&in->value.x, node, attr.name());
00560                                 break;
00561                             case SHADER_SOCKET_COLOR:
00562                             case SHADER_SOCKET_VECTOR:
00563                             case SHADER_SOCKET_POINT:
00564                             case SHADER_SOCKET_NORMAL:
00565                                 xml_read_float3(&in->value, node, attr.name());
00566                                 break;
00567                             default:
00568                                 break;
00569                         }
00570                     }
00571                 }
00572             }
00573         }
00574     }
00575 
00576     shader->set_graph(graph);
00577     shader->tag_update(state.scene);
00578 }
00579 
00580 static void xml_read_shader(const XMLReadState& state, pugi::xml_node node)
00581 {
00582     Shader *shader = new Shader();
00583     xml_read_string(&shader->name, node, "name");
00584     xml_read_shader_graph(state, shader, node);
00585     state.scene->shaders.push_back(shader);
00586 }
00587 
00588 /* Background */
00589 
00590 static void xml_read_background(const XMLReadState& state, pugi::xml_node node)
00591 {
00592     Shader *shader = state.scene->shaders[state.scene->default_background];
00593 
00594     xml_read_shader_graph(state, shader, node);
00595 }
00596 
00597 /* Mesh */
00598 
00599 static Mesh *xml_add_mesh(Scene *scene, const Transform& tfm)
00600 {
00601     /* create mesh */
00602     Mesh *mesh = new Mesh();
00603     scene->meshes.push_back(mesh);
00604 
00605     /* create object*/
00606     Object *object = new Object();
00607     object->mesh = mesh;
00608     object->tfm = tfm;
00609     scene->objects.push_back(object);
00610 
00611     return mesh;
00612 }
00613 
00614 static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
00615 {
00616     /* add mesh */
00617     Mesh *mesh = xml_add_mesh(state.scene, state.tfm);
00618     mesh->used_shaders.push_back(state.shader);
00619 
00620     /* read state */
00621     int shader = state.shader;
00622     bool smooth = state.smooth;
00623 
00624     mesh->displacement_method = state.displacement_method;
00625 
00626     /* read vertices and polygons, RIB style */
00627     vector<float3> P;
00628     vector<int> verts, nverts;
00629 
00630     xml_read_float3_array(P, node, "P");
00631     xml_read_int_array(verts, node, "verts");
00632     xml_read_int_array(nverts, node, "nverts");
00633 
00634     if(xml_equal_string(node, "subdivision", "catmull-clark")) {
00635         /* create subd mesh */
00636         SubdMesh sdmesh;
00637 
00638         /* create subd vertices */
00639         for(size_t i = 0; i < P.size(); i++)
00640             sdmesh.add_vert(P[i]);
00641 
00642         /* create subd faces */
00643         int index_offset = 0;
00644 
00645         for(size_t i = 0; i < nverts.size(); i++) {
00646             if(nverts[i] == 4) {
00647                 int v0 = verts[index_offset + 0];
00648                 int v1 = verts[index_offset + 1];
00649                 int v2 = verts[index_offset + 2];
00650                 int v3 = verts[index_offset + 3];
00651 
00652                 sdmesh.add_face(v0, v1, v2, v3);
00653             }
00654             else {
00655                 for(int j = 0; j < nverts[i]-2; j++) {
00656                     int v0 = verts[index_offset];
00657                     int v1 = verts[index_offset + j + 1];
00658                     int v2 = verts[index_offset + j + 2];;
00659 
00660                     sdmesh.add_face(v0, v1, v2);
00661                 }
00662             }
00663 
00664             index_offset += nverts[i];
00665         }
00666 
00667         /* finalize subd mesh */
00668         sdmesh.link_boundary();
00669 
00670         /* subdivide */
00671         DiagSplit dsplit;
00672         //dsplit.camera = state.scene->camera;
00673         //dsplit.dicing_rate = 5.0f;
00674         dsplit.dicing_rate = state.dicing_rate;
00675         xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
00676         sdmesh.tesselate(&dsplit, false, mesh, shader, smooth);
00677     }
00678     else {
00679         /* create vertices */
00680         mesh->verts = P;
00681 
00682         /* create triangles */
00683         int index_offset = 0;
00684 
00685         for(size_t i = 0; i < nverts.size(); i++) {
00686             for(int j = 0; j < nverts[i]-2; j++) {
00687                 int v0 = verts[index_offset];
00688                 int v1 = verts[index_offset + j + 1];
00689                 int v2 = verts[index_offset + j + 2];
00690 
00691                 assert(v0 < (int)P.size());
00692                 assert(v1 < (int)P.size());
00693                 assert(v2 < (int)P.size());
00694 
00695                 mesh->add_triangle(v0, v1, v2, shader, smooth);
00696             }
00697 
00698             index_offset += nverts[i];
00699         }
00700     }
00701 
00702     /* temporary for test compatibility */
00703     mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL);
00704 }
00705 
00706 /* Patch */
00707 
00708 static void xml_read_patch(const XMLReadState& state, pugi::xml_node node)
00709 {
00710     /* read patch */
00711     Patch *patch = NULL;
00712 
00713     vector<float3> P;
00714     xml_read_float3_array(P, node, "P");
00715 
00716     if(xml_equal_string(node, "type", "bilinear")) {
00717         /* bilinear patch */
00718         if(P.size() == 4) {
00719             LinearQuadPatch *bpatch = new LinearQuadPatch();
00720 
00721             for(int i = 0; i < 4; i++)
00722                 P[i] = transform(&state.tfm, P[i]);
00723             memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull));
00724 
00725             patch = bpatch;
00726         }
00727         else
00728             fprintf(stderr, "Invalid number of control points for bilinear patch.\n");
00729     }
00730     else if(xml_equal_string(node, "type", "bicubic")) {
00731         /* bicubic patch */
00732         if(P.size() == 16) {
00733             BicubicPatch *bpatch = new BicubicPatch();
00734 
00735             for(int i = 0; i < 16; i++)
00736                 P[i] = transform(&state.tfm, P[i]);
00737             memcpy(bpatch->hull, &P[0], sizeof(bpatch->hull));
00738 
00739             patch = bpatch;
00740         }
00741         else
00742             fprintf(stderr, "Invalid number of control points for bicubic patch.\n");
00743     }
00744     else
00745         fprintf(stderr, "Unknown patch type.\n");
00746 
00747     if(patch) {
00748         /* add mesh */
00749         Mesh *mesh = xml_add_mesh(state.scene, transform_identity());
00750 
00751         mesh->used_shaders.push_back(state.shader);
00752 
00753         /* split */
00754         DiagSplit dsplit;
00755         //dsplit.camera = state.scene->camera;
00756         //dsplit.dicing_rate = 5.0f;
00757         dsplit.dicing_rate = state.dicing_rate;
00758         xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
00759         dsplit.split_quad(mesh, patch, state.shader, state.smooth);
00760 
00761         delete patch;
00762 
00763         /* temporary for test compatibility */
00764         mesh->attributes.remove(Attribute::STD_VERTEX_NORMAL);
00765     }
00766 }
00767 
00768 /* Light */
00769 
00770 static void xml_read_light(const XMLReadState& state, pugi::xml_node node)
00771 {
00772     Light *light = new Light();
00773     light->shader = state.shader;
00774     xml_read_float3(&light->co, node, "P");
00775     light->co = transform(&state.tfm, light->co);
00776 
00777     state.scene->lights.push_back(light);
00778 }
00779 
00780 /* Transform */
00781 
00782 static void xml_read_transform(pugi::xml_node node, Transform& tfm)
00783 {
00784     if(node.attribute("matrix")) {
00785         vector<float> matrix;
00786         if(xml_read_float_array(matrix, node, "matrix") && matrix.size() == 16)
00787             tfm = tfm * transform_transpose((*(Transform*)&matrix[0]));
00788     }
00789 
00790     if(node.attribute("translate")) {
00791         float3 translate = make_float3(0.0f, 0.0f, 0.0f);
00792         xml_read_float3(&translate, node, "translate");
00793         tfm = tfm * transform_translate(translate);
00794     }
00795 
00796     if(node.attribute("rotate")) {
00797         float4 rotate = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
00798         xml_read_float4(&rotate, node, "rotate");
00799         tfm = tfm * transform_rotate(rotate.x*M_PI/180.0f, make_float3(rotate.y, rotate.z, rotate.w));
00800     }
00801 
00802     if(node.attribute("scale")) {
00803         float3 scale = make_float3(0.0f, 0.0f, 0.0f);
00804         xml_read_float3(&scale, node, "scale");
00805         tfm = tfm * transform_scale(scale);
00806     }
00807 }
00808 
00809 /* State */
00810 
00811 static void xml_read_state(XMLReadState& state, pugi::xml_node node)
00812 {
00813     /* read shader */
00814     string shadername;
00815 
00816     if(xml_read_string(&shadername, node, "shader")) {
00817         int i = 0;
00818         bool found = false;
00819 
00820         foreach(Shader *shader, state.scene->shaders) {
00821             if(shader->name == shadername) {
00822                 state.shader = i;
00823                 found = true;
00824                 break;
00825             }
00826 
00827             i++;
00828         }
00829 
00830         if(!found)
00831             fprintf(stderr, "Unknown shader \"%s\".\n", shadername.c_str());
00832     }
00833 
00834     xml_read_float(&state.dicing_rate, node, "dicing_rate");
00835 
00836     /* read smooth/flat */
00837     if(xml_equal_string(node, "interpolation", "smooth"))
00838         state.smooth = true;
00839     else if(xml_equal_string(node, "interpolation", "flat"))
00840         state.smooth = false;
00841 
00842     /* read displacement method */
00843     if(xml_equal_string(node, "displacement_method", "true"))
00844         state.displacement_method = Mesh::DISPLACE_TRUE;
00845     else if(xml_equal_string(node, "displacement_method", "bump"))
00846         state.displacement_method = Mesh::DISPLACE_BUMP;
00847     else if(xml_equal_string(node, "displacement_method", "both"))
00848         state.displacement_method = Mesh::DISPLACE_BOTH;
00849 }
00850 
00851 /* Scene */
00852 
00853 static void xml_read_include(const XMLReadState& state, const string& src);
00854 
00855 static void xml_read_scene(const XMLReadState& state, pugi::xml_node scene_node)
00856 {
00857     for(pugi::xml_node node = scene_node.first_child(); node; node = node.next_sibling()) {
00858         if(string_iequals(node.name(), "film")) {
00859             xml_read_film(state, node);
00860         }
00861         else if(string_iequals(node.name(), "integrator")) {
00862             xml_read_integrator(state, node);
00863         }
00864         else if(string_iequals(node.name(), "camera")) {
00865             xml_read_camera(state, node);
00866         }
00867         else if(string_iequals(node.name(), "shader")) {
00868             xml_read_shader(state, node);
00869         }
00870         else if(string_iequals(node.name(), "background")) {
00871             xml_read_background(state, node);
00872         }
00873         else if(string_iequals(node.name(), "mesh")) {
00874             xml_read_mesh(state, node);
00875         }
00876         else if(string_iequals(node.name(), "patch")) {
00877             xml_read_patch(state, node);
00878         }
00879         else if(string_iequals(node.name(), "light")) {
00880             xml_read_light(state, node);
00881         }
00882         else if(string_iequals(node.name(), "transform")) {
00883             XMLReadState substate = state;
00884 
00885             xml_read_transform(node, substate.tfm);
00886             xml_read_scene(substate, node);
00887         }
00888         else if(string_iequals(node.name(), "state")) {
00889             XMLReadState substate = state;
00890 
00891             xml_read_state(substate, node);
00892             xml_read_scene(substate, node);
00893         }
00894         else if(string_iequals(node.name(), "include")) {
00895             string src;
00896 
00897             if(xml_read_string(&src, node, "src"))
00898                 xml_read_include(state, src);
00899         }
00900         else
00901             fprintf(stderr, "Unknown node \"%s\".\n", node.name());
00902     }
00903 }
00904 
00905 /* Include */
00906 
00907 static void xml_read_include(const XMLReadState& state, const string& src)
00908 {
00909     /* open XML document */
00910     pugi::xml_document doc;
00911     pugi::xml_parse_result parse_result;
00912 
00913     string path = path_join(state.base, src);
00914     parse_result = doc.load_file(path.c_str());
00915 
00916     if(parse_result) {
00917         XMLReadState substate = state;
00918         substate.base = path_dirname(path);
00919 
00920         xml_read_scene(substate, doc);
00921     }
00922     else
00923         fprintf(stderr, "%s read error: %s\n", src.c_str(), parse_result.description());
00924 }
00925 
00926 /* File */
00927 
00928 void xml_read_file(Scene *scene, const char *filepath)
00929 {
00930     XMLReadState state;
00931 
00932     state.scene = scene;
00933     state.tfm = transform_identity();
00934     state.shader = scene->default_surface;
00935     state.smooth = false;
00936     state.dicing_rate = 0.1f;
00937     state.base = path_dirname(filepath);
00938 
00939     xml_read_include(state, path_filename(filepath));
00940 
00941     scene->params.bvh_type = SceneParams::BVH_STATIC;
00942 }
00943 
00944 CCL_NAMESPACE_END
00945