1 /****************************************************************************
2 * xmlparser.cc: a libXML based parser for YafRay scenes
3 * This is part of the yafray package
4 * Copyright (C) 2006 Mathias Wein
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <yafraycore/xmlparser.h>
22 #include <core_api/logging.h>
23 #include <core_api/environment.h>
24 #include <core_api/scene.h>
25 #include <utilities/math_utils.h>
26 #include <iomanip>
27
28 #if HAVE_XML
29 #include <libxml/parser.h>
30 #endif
31 #include <cstring>
32
33
34 __BEGIN_YAFRAY
35
36 #if HAVE_XML
37
setLastElementName(const char * element_name)38 void xmlParser_t::setLastElementName(const char *element_name)
39 {
40 if(element_name) current->last_element = std::string(element_name);
41 else current->last_element.clear();
42 }
43
setLastElementNameAttrs(const char ** element_attrs)44 void xmlParser_t::setLastElementNameAttrs(const char **element_attrs)
45 {
46 current->last_element_attrs.clear();
47 if(element_attrs)
48 {
49 for(int n=0; element_attrs[n]; ++n)
50 {
51 if(n > 0) current->last_element_attrs += " ";
52 current->last_element_attrs += (std::string(element_attrs[n]));
53 }
54 }
55 }
56
startDocument(void * user_data)57 void startDocument(void *user_data)
58 {
59 //Empty
60 }
61
endDocument(void * user_data)62 void endDocument(void *user_data)
63 {
64 //Empty
65 }
66
startElement(void * user_data,const xmlChar * name,const xmlChar ** attrs)67 void startElement(void * user_data, const xmlChar * name, const xmlChar **attrs)
68 {
69 xmlParser_t &parser = *((xmlParser_t *)user_data);
70 parser.startElement((const char *)name, (const char **)attrs);
71 }
72
endElement(void * user_data,const xmlChar * name)73 void endElement(void *user_data, const xmlChar *name)
74 {
75 xmlParser_t &parser = *((xmlParser_t *)user_data);
76 parser.endElement((const char *)name);
77 }
78
my_warning(void * user_data,const char * msg,...)79 static void my_warning(void *user_data, const char *msg, ...)
80 {
81 xmlParser_t &parser = *((xmlParser_t *)user_data);
82 va_list args;
83 va_start(args, msg);
84 const size_t message_size = 1000;
85 char message_buffer[message_size];
86 vsnprintf(message_buffer, message_size, msg, args);
87 Y_WARNING << "XMLParser warning: " << message_buffer;
88 Y_WARNING << " in section '" << parser.getLastSection() << ", level " << parser.currLevel() << yendl;
89 Y_WARNING << " an element previous to the error: '" << parser.getLastElementName() << "', attrs: { " << parser.getLastElementNameAttrs() << " }" << yendl;
90 va_end(args);
91 }
92
my_error(void * user_data,const char * msg,...)93 static void my_error(void *user_data, const char *msg, ...)
94 {
95 xmlParser_t &parser = *((xmlParser_t *)user_data);
96 va_list args;
97 va_start(args, msg);
98 const size_t message_size = 1000;
99 char message_buffer[message_size];
100 vsnprintf(message_buffer, message_size, msg, args);
101 Y_ERROR << "XMLParser error: " << message_buffer;
102 Y_ERROR << " in section '" << parser.getLastSection() << ", level " << parser.currLevel() << yendl;
103 Y_ERROR << " an element previous to the error: '" << parser.getLastElementName() << "', attrs: { " << parser.getLastElementNameAttrs() << " }" << yendl;
104 va_end(args);
105 }
106
my_fatalError(void * user_data,const char * msg,...)107 static void my_fatalError(void *user_data, const char *msg, ...)
108 {
109 xmlParser_t &parser = *((xmlParser_t *)user_data);
110 va_list args;
111 va_start(args, msg);
112 const size_t message_size = 1000;
113 char message_buffer[message_size];
114 vsnprintf(message_buffer, message_size, msg, args);
115 Y_ERROR << "XMLParser fatal error: " << message_buffer;
116 Y_ERROR << " in section '" << parser.getLastSection() << ", level " << parser.currLevel() << yendl;
117 Y_ERROR << " an element previous to the error: '" << parser.getLastElementName() << "', attrs: { " << parser.getLastElementNameAttrs() << " }" << yendl;
118 va_end(args);
119 }
120
121 static xmlSAXHandler my_handler =
122 {
123 nullptr,
124 nullptr,
125 nullptr,
126 nullptr,
127 nullptr,
128 nullptr,
129 nullptr,
130 nullptr,
131 nullptr,
132 nullptr,
133 nullptr,
134 nullptr,
135 startDocument, // startDocumentSAXFunc startDocument;
136 endDocument, // endDocumentSAXFunc endDocument;
137 startElement, // startElementSAXFunc startElement;
138 endElement, // endElementSAXFunc endElement;
139 nullptr,
140 nullptr, // charactersSAXFunc characters;
141 nullptr,
142 nullptr,
143 nullptr,
144 my_warning,
145 my_error,
146 my_fatalError
147 };
148 #endif // HAVE_XML
149
parse_xml_file(const char * filename,scene_t * scene,renderEnvironment_t * env,paraMap_t & render,std::string color_space_string,float input_gamma)150 bool parse_xml_file(const char *filename, scene_t *scene, renderEnvironment_t *env, paraMap_t &render, std::string color_space_string, float input_gamma)
151 {
152 #if HAVE_XML
153
154 colorSpaces_t input_color_space = RAW_MANUAL_GAMMA;
155
156 if(color_space_string == "sRGB") input_color_space = SRGB;
157 else if(color_space_string == "XYZ") input_color_space = XYZ_D65;
158 else if(color_space_string == "LinearRGB") input_color_space = LINEAR_RGB;
159 //else if(color_space_string == "Raw_Manual_Gamma") input_color_space = RAW_MANUAL_GAMMA; //not available for now
160 else input_color_space = SRGB;
161
162 xmlParser_t parser(env, scene, render, input_color_space, input_gamma);
163
164 if (xmlSAXUserParseFile(&my_handler, &parser, filename) < 0)
165 {
166 Y_ERROR << "XMLParser: Parsing the file " << filename << yendl;
167 return false;
168 }
169 return true;
170 #else
171 Y_WARNING << "XMLParser: yafray was compiled without XML support, cannot parse file." << yendl;
172 return false;
173 #endif
174 }
175
176 #if HAVE_XML
177 /*=============================================================
178 / parser functions
179 =============================================================*/
180
xmlParser_t(renderEnvironment_t * renv,scene_t * sc,paraMap_t & r,colorSpaces_t input_color_space,float input_gamma)181 xmlParser_t::xmlParser_t(renderEnvironment_t *renv, scene_t *sc, paraMap_t &r, colorSpaces_t input_color_space, float input_gamma):
182 env(renv), scene(sc), render(r), current(0), level(0), inputGamma(input_gamma), inputColorSpace(input_color_space)
183 {
184 cparams = ¶ms;
185 pushState(startEl_document, endEl_document);
186 }
187
pushState(startElement_cb start,endElement_cb end,void * userdata)188 void xmlParser_t::pushState(startElement_cb start, endElement_cb end, void *userdata)
189 {
190 parserState_t state;
191 state.start = start;
192 state.end = end;
193 state.userdata = userdata;
194 state.level = level;
195 state_stack.push_back(state);
196 current = &state_stack.back();
197 }
198
popState()199 void xmlParser_t::popState()
200 {
201 state_stack.pop_back();
202 if(!state_stack.empty()) current = &state_stack.back();
203 else current = nullptr;
204 }
205
206 /*=============================================================
207 / utility functions...
208 =============================================================*/
209
str2bool(const char * s)210 inline bool str2bool(const char *s){ return strcmp(s, "true") ? false : true; }
211
parsePoint(const char ** attrs,point3d_t & p,point3d_t & op)212 static bool parsePoint(const char **attrs, point3d_t &p, point3d_t &op)
213 {
214 for( ;attrs && attrs[0]; attrs += 2)
215 {
216 if(attrs[0][0] == 'o')
217 {
218 if(attrs[0][1] == 0 || attrs[0][2] != 0)
219 {
220 Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in orco point (1)" << yendl;
221 continue; //it is not a single character
222 }
223 switch(attrs[0][1])
224 {
225 case 'x' : op.x = atof(attrs[1]); break;
226 case 'y' : op.y = atof(attrs[1]); break;
227 case 'z' : op.z = atof(attrs[1]); break;
228 default: Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in orco point (2)" << yendl;
229 }
230 continue;
231 }
232 else if(attrs[0][1] != 0)
233 {
234 Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in point" << yendl;
235 continue; //it is not a single character
236 }
237 switch(attrs[0][0])
238 {
239 case 'x' : p.x = atof(attrs[1]); break;
240 case 'y' : p.y = atof(attrs[1]); break;
241 case 'z' : p.z = atof(attrs[1]); break;
242 default: Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in point" << yendl;
243 }
244 }
245
246 return true;
247 }
248
parseNormal(const char ** attrs,normal_t & n)249 static bool parseNormal(const char **attrs, normal_t &n)
250 {
251 int compoRead = 0;
252 for( ;attrs && attrs[0]; attrs += 2)
253 {
254 if(attrs[0][1] != 0)
255 {
256 Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in normal" << yendl;
257 continue; //it is not a single character
258 }
259 switch(attrs[0][0])
260 {
261 case 'x' : n.x = atof(attrs[1]); compoRead++; break;
262 case 'y' : n.y = atof(attrs[1]); compoRead++; break;
263 case 'z' : n.z = atof(attrs[1]); compoRead++; break;
264 default: Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in normal." << yendl;
265 }
266 }
267
268 return (compoRead == 3);
269 }
270
parseParam(const char ** attrs,parameter_t & param,xmlParser_t & parser)271 void parseParam(const char **attrs, parameter_t ¶m, xmlParser_t &parser)
272 {
273 if(!attrs[0]) return;
274 if(!attrs[2]) // only one attribute => bool, integer or float value
275 {
276 std::string name(attrs[0]);
277 if(name == "ival"){ int i = atoi(attrs[1]); param = parameter_t(i); return; }
278 else if(name == "fval"){ double f = atof(attrs[1]); param = parameter_t(f); return; }
279 else if(name == "bval"){ bool b = str2bool(attrs[1]); param = parameter_t(b); return; }
280 else if(name == "sval"){ param = parameter_t(std::string(attrs[1])); return; }
281 }
282 colorA_t c(0.f); point3d_t p(0,0,0);
283 int type=TYPE_NONE;
284 for(int n=0; attrs[n]; ++n)
285 {
286 if(attrs[n][1] != '\0') continue;
287 switch(attrs[n][0])
288 {
289 case 'x': p.x = atof(attrs[n+1]); type = TYPE_POINT; break;
290 case 'y': p.y = atof(attrs[n+1]); type = TYPE_POINT; break;
291 case 'z': p.z = atof(attrs[n+1]); type = TYPE_POINT; break;
292
293 case 'r': c.R = (float)atof(attrs[n+1]); type = TYPE_COLOR; break;
294 case 'g': c.G = (float)atof(attrs[n+1]); type = TYPE_COLOR; break;
295 case 'b': c.B = (float)atof(attrs[n+1]); type = TYPE_COLOR; break;
296 case 'a': c.A = (float)atof(attrs[n+1]); type = TYPE_COLOR; break;
297 }
298 }
299
300 switch(type)
301 {
302 case TYPE_POINT: param = parameter_t(p); break;
303 case TYPE_COLOR:
304 c.linearRGB_from_ColorSpace(parser.getInputColorSpace(), parser.getInputGamma());
305 param = parameter_t(c);
306 break;
307 }
308 }
309
310 /*=============================================================
311 / start- and endElement callbacks for the different states
312 =============================================================*/
313
endEl_dummy(xmlParser_t & parser,const char * element)314 void endEl_dummy(xmlParser_t &parser, const char *element)
315 { parser.popState(); }
316
startEl_dummy(xmlParser_t & parser,const char * element,const char ** attrs)317 void startEl_dummy(xmlParser_t &parser, const char *element, const char **attrs)
318 { parser.pushState(startEl_dummy, endEl_dummy); }
319
startEl_document(xmlParser_t & parser,const char * element,const char ** attrs)320 void startEl_document(xmlParser_t &parser, const char *element, const char **attrs)
321 {
322 parser.setLastSection("Document");
323 parser.setLastElementName(element);
324 parser.setLastElementNameAttrs(attrs);
325
326 if( strcmp(element, "scene") ) Y_WARNING << "XMLParser: skipping <" << element << ">" << yendl; /* parser.error("Expected scene definition"); */
327 else
328 {
329 for( ;attrs && attrs[0]; attrs += 2)
330 {
331 if(!strcmp(attrs[0], "type") )
332 {
333 std::string val(attrs[1]);
334 if (val == "triangle") parser.scene->setMode(0);
335 else if (val == "universal") parser.scene->setMode(1);
336 }
337 }
338 parser.pushState(startEl_scene, endEl_scene);
339 }
340 }
341
endEl_document(xmlParser_t & parser,const char * element)342 void endEl_document(xmlParser_t &parser, const char *element)
343 {
344 Y_VERBOSE << "XMLParser: Finished document" << yendl;
345 }
346
347 struct mesh_dat_t
348 {
mesh_dat_tmesh_dat_t349 mesh_dat_t(): has_orco(false), has_uv(false), smooth(false), smooth_angle(0), ID(0), mat(0) {};
350 bool has_orco, has_uv;
351 bool smooth;
352 float smooth_angle;
353 objID_t ID;
354 const material_t *mat;
355 };
356
357 struct curve_dat_t
358 {
curve_dat_tcurve_dat_t359 curve_dat_t(): ID(0), mat(nullptr), strandStart(0), strandEnd(0), strandShape(0) {};
360 objID_t ID;
361 const material_t *mat;
362 float strandStart, strandEnd, strandShape;
363 };
364
365 // scene-state, i.e. expect only primary elements
366 // such as light, material, texture, object, integrator, render...
367
startEl_scene(xmlParser_t & parser,const char * element,const char ** attrs)368 void startEl_scene(xmlParser_t &parser, const char *element, const char **attrs)
369 {
370 parser.setLastSection("Scene");
371 parser.setLastElementName(element);
372 parser.setLastElementNameAttrs(attrs);
373
374 std::string el(element), *name=0;
375 if( el == "material" || el == "integrator" || el == "light" || el == "texture" ||
376 el == "camera" || el == "background" || el == "object" || el == "volumeregion" || el == "render_passes" || el == "logging_badge")
377 {
378 if(!attrs[0])
379 {
380 Y_ERROR << "XMLParser: No attributes for scene element given!" << yendl;
381 return;
382 }
383 else if(!strcmp(attrs[0], "name")) name = new std::string(attrs[1]);
384 else
385 {
386 Y_ERROR << "XMLParser: Attribute for scene element does not match 'name'!" << yendl;
387 return;
388 }
389 parser.pushState(startEl_parammap, endEl_parammap, name);
390 }
391 else if(el == "mesh")
392 {
393 mesh_dat_t *md = new mesh_dat_t();
394 int vertices=0, triangles=0, type=0, id=-1, obj_pass_index=0;
395 for(int n=0; attrs[n]; ++n)
396 {
397 std::string name(attrs[n]);
398 if(name == "has_orco") md->has_orco = str2bool(attrs[n+1]);
399 else if(name == "has_uv") md->has_uv = str2bool(attrs[n+1]);
400 else if(name == "vertices") vertices = atoi(attrs[n+1]);
401 else if(name == "faces") triangles = atoi(attrs[n+1]);
402 else if(name == "type") type = atoi(attrs[n+1]);
403 else if(name == "id" ) id = atoi(attrs[n+1]);
404 else if(name == "obj_pass_index" ) obj_pass_index = atoi(attrs[n+1]);
405 }
406 parser.pushState(startEl_mesh, endEl_mesh, md);
407 if(!parser.scene->startGeometry()) Y_ERROR << "XMLParser: Invalid scene state on startGeometry()!" << yendl;
408
409 // Get a new object ID if we did not get one
410 if(id == -1) md->ID = parser.scene->getNextFreeID();
411 else md->ID = id;
412
413 if(!parser.scene->startTriMesh(md->ID, vertices, triangles, md->has_orco, md->has_uv, type, obj_pass_index))
414 {
415 Y_ERROR << "XMLParser: Invalid scene state on startTriMesh()!" << yendl;
416 }
417 }
418 else if(el == "smooth")
419 {
420 unsigned int ID=0;
421 float angle=181;
422 for(int n=0; attrs[n]; ++n)
423 {
424 std::string name(attrs[n]);
425 if(name == "ID") ID = atoi(attrs[n+1]);
426 else if(name == "angle") angle = atof(attrs[n+1]);
427 }
428 //not optimal to take ID blind...
429 parser.scene->startGeometry();
430 bool success = parser.scene->smoothMesh(ID, angle);
431 if(!success) Y_ERROR << "XMLParser: Couldn't smooth mesh ID = " << ID << ", angle = " << angle << yendl;
432 parser.scene->endGeometry();
433 parser.pushState(startEl_dummy, endEl_dummy);
434 }
435 else if(el == "render")
436 {
437 parser.cparams = &parser.render;
438 parser.pushState(startEl_parammap, endEl_render);
439 }
440 else if(el == "instance")
441 {
442 objID_t * base_object_id = new objID_t();
443 *base_object_id = -1;
444 for(int n=0; attrs[n]; n++)
445 {
446 std::string name(attrs[n]);
447 if(name == "base_object_id") *base_object_id = atoi(attrs[n+1]);
448 }
449 parser.pushState(startEl_instance,endEl_instance, base_object_id);
450 }
451 else if(el == "curve")
452 {
453 curve_dat_t *cvd = new curve_dat_t();
454 int vertex = 0, idc = -1;
455 // attribute's loop
456 for(int n=0; attrs[n]; ++n)
457 {
458 std::string name(attrs[n]);
459 if(name == "vertices") vertex = atoi(attrs[n+1]);
460 else if(name == "id" ) idc = atoi(attrs[n+1]);
461 }
462 parser.pushState(startEl_curve, endEl_curve, cvd);
463 if(!parser.scene->startGeometry()) Y_ERROR << "XMLParser: Invalid scene state on startGeometry()!" << yendl;
464
465 // Get a new object ID if we did not get one
466 if(idc == -1) cvd->ID = parser.scene->getNextFreeID();
467 else cvd->ID = idc;
468
469 if(!parser.scene->startCurveMesh(cvd->ID, vertex))
470 {
471 Y_ERROR << "XMLParser: Invalid scene state on startCurveMesh()!" << yendl;
472 }
473 }
474 else Y_WARNING << "XMLParser: Skipping unrecognized scene element" << yendl;
475 }
476
endEl_scene(xmlParser_t & parser,const char * element)477 void endEl_scene(xmlParser_t &parser, const char *element)
478 {
479 if(strcmp(element, "scene")) Y_WARNING << "XMLParser: : expected </scene> tag!" << yendl;
480 else
481 {
482 parser.popState();
483 }
484 }
startEl_curve(xmlParser_t & parser,const char * element,const char ** attrs)485 void startEl_curve(xmlParser_t &parser, const char *element, const char **attrs)
486 {
487 parser.setLastSection("Curve");
488 parser.setLastElementName(element);
489 parser.setLastElementNameAttrs(attrs);
490
491 std::string el(element);
492 curve_dat_t *dat = (curve_dat_t *)parser.stateData();
493
494 if(el == "p")
495 {
496 point3d_t p, op;
497 if(!parsePoint(attrs, p, op)) return;
498 parser.scene->addVertex(p);
499 }
500 else if(el == "strand_start")
501 {
502 dat->strandStart = atof(attrs[1]);
503 }
504 else if(el == "strand_end")
505 {
506 dat->strandEnd = atof(attrs[1]);
507 }
508 else if(el == "strand_shape")
509 {
510 dat->strandShape = atof(attrs[1]);
511
512 }
513 else if(el == "set_material")
514 {
515 std::string mat_name(attrs[1]);
516 dat->mat = parser.env->getMaterial(mat_name);
517 if(!dat->mat) Y_WARNING << "XMLParser: Unknown material!" << yendl;
518 }
519 }
endEl_curve(xmlParser_t & parser,const char * element)520 void endEl_curve(xmlParser_t &parser, const char *element)
521 {
522 if(std::string(element) == "curve")
523 {
524 curve_dat_t *cd = (curve_dat_t *)parser.stateData();
525 if(!parser.scene->endCurveMesh(cd->mat, cd->strandStart, cd->strandEnd, cd->strandShape))
526 {
527 Y_WARNING << "XMLParser: Invalid scene state on endCurveMesh()!" << yendl;
528 }
529 if(!parser.scene->endGeometry())
530 {
531 Y_WARNING << "XMLParser: Invalid scene state on endGeometry()!" << yendl;
532 }
533 delete cd;
534 parser.popState();
535 }
536 }
537
538 // mesh-state, i.e. expect only points (vertices), faces and material settings
539 // since we're supposed to be inside a mesh block, exit state on "mesh" element
startEl_mesh(xmlParser_t & parser,const char * element,const char ** attrs)540 void startEl_mesh(xmlParser_t &parser, const char *element, const char **attrs)
541 {
542 parser.setLastSection("Mesh");
543 parser.setLastElementName(element);
544 parser.setLastElementNameAttrs(attrs);
545
546 std::string el(element);
547 mesh_dat_t *dat = (mesh_dat_t *)parser.stateData();
548 if(el == "p")
549 {
550 point3d_t p, op;
551 if(!parsePoint(attrs, p, op)) return;
552 if(dat->has_orco) parser.scene->addVertex(p, op);
553 else parser.scene->addVertex(p);
554 }
555 else if(el == "n")
556 {
557 normal_t n(0.0, 0.0, 0.0);
558 if(!parseNormal(attrs, n)) return;
559 parser.scene->addNormal(n);
560 }
561 else if(el == "f")
562 {
563 int a=0, b=0, c=0, uv_a=0, uv_b=0, uv_c=0;
564 for( ;attrs && attrs[0]; attrs += 2)
565 {
566 if(attrs[0][1]==0) switch(attrs[0][0])
567 {
568 case 'a' : a = atoi(attrs[1]); break;
569 case 'b' : b = atoi(attrs[1]); break;
570 case 'c' : c = atoi(attrs[1]); break;
571 default: Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in face" << yendl;
572 }
573 else
574 {
575 if(!strcmp(attrs[0], "uv_a")) uv_a = atoi(attrs[1]);
576 else if(!strcmp(attrs[0], "uv_b")) uv_b = atoi(attrs[1]);
577 else if(!strcmp(attrs[0], "uv_c")) uv_c = atoi(attrs[1]);
578 }
579 }
580 if(dat->has_uv) parser.scene->addTriangle(a, b, c, uv_a, uv_b, uv_c, dat->mat);
581 else parser.scene->addTriangle(a, b, c, dat->mat);
582 }
583 else if(el == "uv")
584 {
585 float u=0, v=0;
586 for( ;attrs && attrs[0]; attrs += 2)
587 {
588 switch(attrs[0][0])
589 {
590 case 'u': u = atof(attrs[1]);
591 if(!(isValidFloat(u)))
592 {
593 Y_WARNING << std::scientific << std::setprecision(6) << "XMLParser: invalid value in \"" << el << "\" xml entry: " << attrs[0]<<"="<<attrs[1]<<". Replacing with 0.0." << yendl;
594 u = 0.f;
595 }
596 break;
597 case 'v': v = atof(attrs[1]);
598 if(!(isValidFloat(v)))
599 {
600 Y_WARNING << std::scientific << std::setprecision(6) << "XMLParser: invalid value in \"" << el << "\" xml entry: " << attrs[0]<<"="<<attrs[1]<<". Replacing with 0.0." << yendl;
601 v = 0.f;
602 }
603 break;
604
605 default: Y_WARNING << "XMLParser: Ignored wrong attribute " << attrs[0] << " in uv" << yendl;
606 }
607 }
608 parser.scene->addUV(u, v);
609 }
610 else if(el == "set_material")
611 {
612 std::string mat_name(attrs[1]);
613 dat->mat = parser.env->getMaterial(mat_name);
614 if(!dat->mat) Y_WARNING << "XMLParser: Unknown material!" << yendl;
615 }
616 }
617
endEl_mesh(xmlParser_t & parser,const char * element)618 void endEl_mesh(xmlParser_t &parser, const char *element)
619 {
620 if(std::string(element) == "mesh")
621 {
622 mesh_dat_t *md = (mesh_dat_t *)parser.stateData();
623 if(!parser.scene->endTriMesh()) Y_ERROR << "XMLParser: Invalid scene state on endTriMesh()!" << yendl;
624 if(!parser.scene->endGeometry()) Y_ERROR << "XMLParser: Invalid scene state on endGeometry()!" << yendl;
625 delete md;
626 parser.popState();
627 }
628 }
629
startEl_instance(xmlParser_t & parser,const char * element,const char ** attrs)630 void startEl_instance(xmlParser_t &parser, const char *element, const char **attrs)
631 {
632 parser.setLastSection("Instance");
633 parser.setLastElementName(element);
634 parser.setLastElementNameAttrs(attrs);
635
636 std::string el(element);
637 objID_t boi = *(objID_t *)parser.stateData();
638 if(el == "transform")
639 {
640 float m[4][4];
641 for(int n=0; attrs[n]; ++n)
642 {
643 std::string name(attrs[n]);
644 if(name == "m00") m[0][0] = atof(attrs[n+1]);
645 else if(name == "m01") m[0][1] = atof(attrs[n+1]);
646 else if(name == "m02") m[0][2] = atof(attrs[n+1]);
647 else if(name == "m03") m[0][3] = atof(attrs[n+1]);
648 else if(name == "m10") m[1][0] = atof(attrs[n+1]);
649 else if(name == "m11") m[1][1] = atof(attrs[n+1]);
650 else if(name == "m12") m[1][2] = atof(attrs[n+1]);
651 else if(name == "m13") m[1][3] = atof(attrs[n+1]);
652 else if(name == "m20") m[2][0] = atof(attrs[n+1]);
653 else if(name == "m21") m[2][1] = atof(attrs[n+1]);
654 else if(name == "m22") m[2][2] = atof(attrs[n+1]);
655 else if(name == "m23") m[2][3] = atof(attrs[n+1]);
656 else if(name == "m30") m[3][0] = atof(attrs[n+1]);
657 else if(name == "m31") m[3][1] = atof(attrs[n+1]);
658 else if(name == "m32") m[3][2] = atof(attrs[n+1]);
659 else if(name == "m33") m[3][3] = atof(attrs[n+1]);
660 }
661 matrix4x4_t *m4 = new matrix4x4_t(m);
662 parser.scene->addInstance(boi,*m4);
663 }
664 }
665
endEl_instance(xmlParser_t & parser,const char * element)666 void endEl_instance(xmlParser_t &parser, const char *element)
667 {
668 if(std::string(element) == "instance" )
669 {
670 parser.popState();
671 }
672 }
673 // read a parameter map; take any tag as parameter name
674 // again, exit when end-element is on of the elements that caused to enter state
675 // depending on exit element, create appropriate scene element
676
startEl_parammap(xmlParser_t & parser,const char * element,const char ** attrs)677 void startEl_parammap(xmlParser_t &parser, const char *element, const char **attrs)
678 {
679 parser.setLastSection("Params map");
680 parser.setLastElementName(element);
681 parser.setLastElementNameAttrs(attrs);
682 // support for lists of paramMaps
683 if(std::string(element) == "list_element")
684 {
685 parser.eparams.push_back(paraMap_t());
686 parser.cparams = &parser.eparams.back();
687 parser.pushState(startEl_paramlist, endEl_paramlist);
688 return;
689 }
690 parameter_t p;
691 parseParam(attrs, p, parser);
692 parser.setParam(std::string(element), p);
693 }
694
endEl_parammap(xmlParser_t & p,const char * element)695 void endEl_parammap(xmlParser_t &p, const char *element)
696 {
697 bool exit_state= (p.currLevel() == p.stateLevel());
698 if(exit_state)
699 {
700 std::string el(element);
701 std::string *name = (std::string *)p.stateData();
702 if(!name) Y_ERROR << "XMLParser: No name for scene element available!" << yendl;
703 else
704 {
705 if(el == "material")
706 { p.env->createMaterial(*name, p.params, p.eparams); }
707 else if(el == "integrator")
708 { p.env->createIntegrator(*name, p.params); }
709 else if(el == "light")
710 {
711 light_t *light = p.env->createLight(*name, p.params);
712 if(light) p.scene->addLight(light);
713 }
714 else if(el == "texture")
715 { p.env->createTexture(*name, p.params); }
716 else if(el == "camera")
717 { p.env->createCamera(*name, p.params); }
718 else if(el == "background")
719 { p.env->createBackground(*name, p.params); }
720 else if(el == "object")
721 {
722 objID_t id;
723 object3d_t *obj = p.env->createObject(*name, p.params);
724 if(obj) p.scene->addObject(obj, id);
725 }
726 else if(el == "volumeregion")
727 {
728 VolumeRegion* vr = p.env->createVolumeRegion(*name, p.params);
729 if (vr) p.scene->addVolumeRegion(vr);
730 }
731 else if(el == "render_passes")
732 {
733 p.env->setupRenderPasses(p.params);
734 }
735 else if(el == "logging_badge")
736 {
737 p.env->setupLoggingAndBadge(p.params);
738 }
739 else Y_WARNING << "XMLParser: Unexpected end-tag of scene element!" << yendl;
740 }
741
742 if(name) delete name;
743 p.popState(); p.params.clear(); p.eparams.clear();
744 }
745 }
746
startEl_paramlist(xmlParser_t & parser,const char * element,const char ** attrs)747 void startEl_paramlist(xmlParser_t &parser, const char *element, const char **attrs)
748 {
749 parser.setLastSection("Params list");
750 parser.setLastElementName(element);
751 parser.setLastElementNameAttrs(attrs);
752 parameter_t p;
753 parseParam(attrs, p, parser);
754 parser.setParam(std::string(element), p);
755 }
756
endEl_paramlist(xmlParser_t & parser,const char * element)757 void endEl_paramlist(xmlParser_t &parser, const char *element)
758 {
759 if(std::string(element) == "list_element")
760 {
761 parser.popState();
762 parser.cparams = &parser.params;
763 }
764 }
765
endEl_render(xmlParser_t & parser,const char * element)766 void endEl_render(xmlParser_t &parser, const char *element)
767 {
768 parser.setLastSection("render");
769 parser.setLastElementName(element);
770 parser.setLastElementNameAttrs(nullptr);
771
772 if(!strcmp(element, "render"))
773 {
774 parser.cparams = &parser.params;
775 parser.popState();
776 }
777 }
778
779 #endif // HAVE_XML
780
781 __END_YAFRAY
782