1 /*************************************************************************/
2 /*  collada.cpp                                                          */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
10 /*                                                                       */
11 /* Permission is hereby granted, free of charge, to any person obtaining */
12 /* a copy of this software and associated documentation files (the       */
13 /* "Software"), to deal in the Software without restriction, including   */
14 /* without limitation the rights to use, copy, modify, merge, publish,   */
15 /* distribute, sublicense, and/or sell copies of the Software, and to    */
16 /* permit persons to whom the Software is furnished to do so, subject to */
17 /* the following conditions:                                             */
18 /*                                                                       */
19 /* The above copyright notice and this permission notice shall be        */
20 /* included in all copies or substantial portions of the Software.       */
21 /*                                                                       */
22 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
23 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
24 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
25 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
26 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
27 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
28 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
29 /*************************************************************************/
30 
31 #include "collada.h"
32 
33 #include <stdio.h>
34 
35 //#define DEBUG_DEFAULT_ANIMATION
36 //#define DEBUG_COLLADA
37 #ifdef DEBUG_COLLADA
38 #define COLLADA_PRINT(m_what) print_line(m_what)
39 #else
40 #define COLLADA_PRINT(m_what)
41 #endif
42 
43 #define COLLADA_IMPORT_SCALE_SCENE
44 
45 /* HELPERS */
46 
get_texture_path(const String & p_source,Collada & state) const47 String Collada::Effect::get_texture_path(const String &p_source, Collada &state) const {
48 
49 	const String &image = p_source;
50 	ERR_FAIL_COND_V(!state.state.image_map.has(image), "");
51 	return state.state.image_map[image].path;
52 }
53 
get_root_transform() const54 Transform Collada::get_root_transform() const {
55 
56 	Transform unit_scale_transform;
57 #ifndef COLLADA_IMPORT_SCALE_SCENE
58 	unit_scale_transform.scale(Vector3(state.unit_scale, state.unit_scale, state.unit_scale));
59 #endif
60 	return unit_scale_transform;
61 }
62 
fix_unit_scale(Collada & state)63 void Collada::Vertex::fix_unit_scale(Collada &state) {
64 #ifdef COLLADA_IMPORT_SCALE_SCENE
65 	vertex *= state.state.unit_scale;
66 #endif
67 }
68 
_uri_to_id(const String & p_uri)69 static String _uri_to_id(const String &p_uri) {
70 
71 	if (p_uri.begins_with("#"))
72 		return p_uri.substr(1, p_uri.size() - 1);
73 	else
74 		return p_uri;
75 }
76 
77 /** HELPER FUNCTIONS **/
78 
fix_transform(const Transform & p_transform)79 Transform Collada::fix_transform(const Transform &p_transform) {
80 
81 	Transform tr = p_transform;
82 
83 #ifndef NO_UP_AXIS_SWAP
84 
85 	if (state.up_axis != Vector3::AXIS_Y) {
86 
87 		for (int i = 0; i < 3; i++)
88 			SWAP(tr.basis[1][i], tr.basis[state.up_axis][i]);
89 		for (int i = 0; i < 3; i++)
90 			SWAP(tr.basis[i][1], tr.basis[i][state.up_axis]);
91 
92 		SWAP(tr.origin[1], tr.origin[state.up_axis]);
93 
94 		tr.basis[state.up_axis][0] = -tr.basis[state.up_axis][0];
95 		tr.basis[state.up_axis][1] = -tr.basis[state.up_axis][1];
96 		tr.basis[0][state.up_axis] = -tr.basis[0][state.up_axis];
97 		tr.basis[1][state.up_axis] = -tr.basis[1][state.up_axis];
98 		tr.origin[state.up_axis] = -tr.origin[state.up_axis];
99 	}
100 #endif
101 
102 	//tr.scale(Vector3(state.unit_scale.unit_scale.unit_scale));
103 	return tr;
104 	//return state.matrix_fix * p_transform;
105 }
106 
_read_transform_from_array(const Vector<float> & array,int ofs=0)107 static Transform _read_transform_from_array(const Vector<float> &array, int ofs = 0) {
108 
109 	Transform tr;
110 	// i wonder why collada matrices are transposed, given that's opposed to opengl..
111 	tr.basis.elements[0][0] = array[0 + ofs];
112 	tr.basis.elements[0][1] = array[1 + ofs];
113 	tr.basis.elements[0][2] = array[2 + ofs];
114 	tr.basis.elements[1][0] = array[4 + ofs];
115 	tr.basis.elements[1][1] = array[5 + ofs];
116 	tr.basis.elements[1][2] = array[6 + ofs];
117 	tr.basis.elements[2][0] = array[8 + ofs];
118 	tr.basis.elements[2][1] = array[9 + ofs];
119 	tr.basis.elements[2][2] = array[10 + ofs];
120 	tr.origin.x = array[3 + ofs];
121 	tr.origin.y = array[7 + ofs];
122 	tr.origin.z = array[11 + ofs];
123 	return tr;
124 }
125 
126 /* STRUCTURES */
127 
compute_transform(Collada & state) const128 Transform Collada::Node::compute_transform(Collada &state) const {
129 
130 	Transform xform;
131 
132 	for (int i = 0; i < xform_list.size(); i++) {
133 
134 		Transform xform_step;
135 		const XForm &xf = xform_list[i];
136 		switch (xf.op) {
137 
138 			case XForm::OP_ROTATE: {
139 				if (xf.data.size() >= 4) {
140 
141 					xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg2rad(xf.data[3]));
142 				}
143 			} break;
144 			case XForm::OP_SCALE: {
145 
146 				if (xf.data.size() >= 3) {
147 
148 					xform_step.scale(Vector3(xf.data[0], xf.data[1], xf.data[2]));
149 				}
150 
151 			} break;
152 			case XForm::OP_TRANSLATE: {
153 
154 				if (xf.data.size() >= 3) {
155 
156 					xform_step.origin = Vector3(xf.data[0], xf.data[1], xf.data[2]);
157 				}
158 
159 			} break;
160 			case XForm::OP_MATRIX: {
161 
162 				if (xf.data.size() >= 16) {
163 					xform_step = _read_transform_from_array(xf.data, 0);
164 				}
165 
166 			} break;
167 			default: {
168 			}
169 		}
170 
171 		xform = xform * xform_step;
172 	}
173 
174 #ifdef COLLADA_IMPORT_SCALE_SCENE
175 	xform.origin *= state.state.unit_scale;
176 #endif
177 	return xform;
178 }
179 
get_transform() const180 Transform Collada::Node::get_transform() const {
181 
182 	return default_transform;
183 }
184 
get_global_transform() const185 Transform Collada::Node::get_global_transform() const {
186 
187 	if (parent)
188 		return parent->get_global_transform() * default_transform;
189 	else
190 		return default_transform;
191 }
192 
get_value_at_time(float p_time) const193 Vector<float> Collada::AnimationTrack::get_value_at_time(float p_time) const {
194 
195 	ERR_FAIL_COND_V(keys.size() == 0, Vector<float>());
196 	int i = 0;
197 
198 	for (i = 0; i < keys.size(); i++) {
199 
200 		if (keys[i].time > p_time)
201 			break;
202 	}
203 
204 	if (i == 0)
205 		return keys[0].data;
206 	if (i == keys.size())
207 		return keys[keys.size() - 1].data;
208 
209 	switch (keys[i].interp_type) {
210 
211 		case INTERP_BEZIER: //wait for bezier
212 		case INTERP_LINEAR: {
213 
214 			float c = (p_time - keys[i - 1].time) / (keys[i].time - keys[i - 1].time);
215 
216 			if (keys[i].data.size() == 16) {
217 				//interpolate a matrix
218 				Transform src = _read_transform_from_array(keys[i - 1].data);
219 				Transform dst = _read_transform_from_array(keys[i].data);
220 
221 				Transform interp = c < 0.001 ? src : src.interpolate_with(dst, c);
222 
223 				Vector<float> ret;
224 				ret.resize(16);
225 				Transform tr;
226 				// i wonder why collada matrices are transposed, given that's opposed to opengl..
227 				ret.write[0] = interp.basis.elements[0][0];
228 				ret.write[1] = interp.basis.elements[0][1];
229 				ret.write[2] = interp.basis.elements[0][2];
230 				ret.write[4] = interp.basis.elements[1][0];
231 				ret.write[5] = interp.basis.elements[1][1];
232 				ret.write[6] = interp.basis.elements[1][2];
233 				ret.write[8] = interp.basis.elements[2][0];
234 				ret.write[9] = interp.basis.elements[2][1];
235 				ret.write[10] = interp.basis.elements[2][2];
236 				ret.write[3] = interp.origin.x;
237 				ret.write[7] = interp.origin.y;
238 				ret.write[11] = interp.origin.z;
239 				ret.write[12] = 0;
240 				ret.write[13] = 0;
241 				ret.write[14] = 0;
242 				ret.write[15] = 1;
243 
244 				return ret;
245 			} else {
246 
247 				Vector<float> dest;
248 				dest.resize(keys[i].data.size());
249 				for (int j = 0; j < dest.size(); j++) {
250 
251 					dest.write[j] = keys[i].data[j] * c + keys[i - 1].data[j] * (1.0 - c);
252 				}
253 				return dest;
254 				//interpolate one by one
255 			}
256 		} break;
257 	}
258 
259 	ERR_FAIL_V(Vector<float>());
260 }
261 
_parse_asset(XMLParser & parser)262 void Collada::_parse_asset(XMLParser &parser) {
263 
264 	while (parser.read() == OK) {
265 
266 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
267 
268 			String name = parser.get_node_name();
269 
270 			if (name == "up_axis") {
271 
272 				parser.read();
273 				if (parser.get_node_data() == "X_UP")
274 					state.up_axis = Vector3::AXIS_X;
275 				if (parser.get_node_data() == "Y_UP")
276 					state.up_axis = Vector3::AXIS_Y;
277 				if (parser.get_node_data() == "Z_UP")
278 					state.up_axis = Vector3::AXIS_Z;
279 
280 				COLLADA_PRINT("up axis: " + parser.get_node_data());
281 			} else if (name == "unit") {
282 
283 				state.unit_scale = parser.get_attribute_value("meter").to_double();
284 				COLLADA_PRINT("unit scale: " + rtos(state.unit_scale));
285 			}
286 
287 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "asset")
288 			break; //end of <asset>
289 	}
290 }
291 
_parse_image(XMLParser & parser)292 void Collada::_parse_image(XMLParser &parser) {
293 
294 	String id = parser.get_attribute_value("id");
295 
296 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
297 		if (!parser.is_empty())
298 			parser.skip_section();
299 		return;
300 	}
301 
302 	Image image;
303 
304 	if (state.version < State::Version(1, 4, 0)) {
305 		/* <1.4 */
306 		String path = parser.get_attribute_value("source").strip_edges();
307 		if (path.find("://") == -1 && path.is_rel_path()) {
308 			// path is relative to file being loaded, so convert to a resource path
309 			image.path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path.percent_decode()));
310 		}
311 	} else {
312 
313 		while (parser.read() == OK) {
314 
315 			if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
316 
317 				String name = parser.get_node_name();
318 
319 				if (name == "init_from") {
320 
321 					parser.read();
322 					String path = parser.get_node_data().strip_edges().percent_decode();
323 
324 					if (path.find("://") == -1 && path.is_rel_path()) {
325 						// path is relative to file being loaded, so convert to a resource path
326 						path = ProjectSettings::get_singleton()->localize_path(state.local_path.get_base_dir().plus_file(path));
327 
328 					} else if (path.find("file:///") == 0) {
329 						path = path.replace_first("file:///", "");
330 						path = ProjectSettings::get_singleton()->localize_path(path);
331 					}
332 
333 					image.path = path;
334 
335 				} else if (name == "data") {
336 
337 					ERR_PRINT("COLLADA Embedded image data not supported!");
338 
339 				} else if (name == "extra" && !parser.is_empty())
340 					parser.skip_section();
341 
342 			} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "image")
343 				break; //end of <asset>
344 		}
345 	}
346 
347 	state.image_map[id] = image;
348 }
349 
_parse_material(XMLParser & parser)350 void Collada::_parse_material(XMLParser &parser) {
351 
352 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
353 		if (!parser.is_empty())
354 			parser.skip_section();
355 		return;
356 	}
357 
358 	Material material;
359 
360 	String id = parser.get_attribute_value("id");
361 	if (parser.has_attribute("name"))
362 		material.name = parser.get_attribute_value("name");
363 
364 	if (state.version < State::Version(1, 4, 0)) {
365 		/* <1.4 */
366 		ERR_PRINT("Collada Materials < 1.4 are not supported (yet)");
367 	} else {
368 
369 		while (parser.read() == OK) {
370 
371 			if (parser.get_node_type() == XMLParser::NODE_ELEMENT && parser.get_node_name() == "instance_effect") {
372 
373 				material.instance_effect = _uri_to_id(parser.get_attribute_value("url"));
374 			} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "material")
375 				break; //end of <asset>
376 		}
377 	}
378 
379 	state.material_map[id] = material;
380 }
381 
382 //! reads floats from inside of xml element until end of xml element
_read_float_array(XMLParser & parser)383 Vector<float> Collada::_read_float_array(XMLParser &parser) {
384 
385 	if (parser.is_empty())
386 		return Vector<float>();
387 
388 	Vector<String> splitters;
389 	splitters.push_back(" ");
390 	splitters.push_back("\n");
391 	splitters.push_back("\r");
392 	splitters.push_back("\t");
393 
394 	Vector<float> array;
395 	while (parser.read() == OK) {
396 		// TODO: check for comments inside the element
397 		// and ignore them.
398 
399 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
400 			// parse float data
401 			String str = parser.get_node_data();
402 			array = str.split_floats_mk(splitters, false);
403 			//array=str.split_floats(" ",false);
404 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
405 			break; // end parsing text
406 	}
407 
408 	return array;
409 }
410 
_read_string_array(XMLParser & parser)411 Vector<String> Collada::_read_string_array(XMLParser &parser) {
412 
413 	if (parser.is_empty())
414 		return Vector<String>();
415 
416 	Vector<String> array;
417 	while (parser.read() == OK) {
418 		// TODO: check for comments inside the element
419 		// and ignore them.
420 
421 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
422 			// parse String data
423 			String str = parser.get_node_data();
424 			array = str.split_spaces();
425 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
426 			break; // end parsing text
427 	}
428 
429 	return array;
430 }
431 
_read_transform(XMLParser & parser)432 Transform Collada::_read_transform(XMLParser &parser) {
433 
434 	if (parser.is_empty())
435 		return Transform();
436 
437 	Vector<String> array;
438 	while (parser.read() == OK) {
439 		// TODO: check for comments inside the element
440 		// and ignore them.
441 
442 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
443 			// parse float data
444 			String str = parser.get_node_data();
445 			array = str.split_spaces();
446 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
447 			break; // end parsing text
448 	}
449 
450 	ERR_FAIL_COND_V(array.size() != 16, Transform());
451 	Vector<float> farr;
452 	farr.resize(16);
453 	for (int i = 0; i < 16; i++) {
454 		farr.write[i] = array[i].to_double();
455 	}
456 
457 	return _read_transform_from_array(farr);
458 }
459 
_read_empty_draw_type(XMLParser & parser)460 String Collada::_read_empty_draw_type(XMLParser &parser) {
461 
462 	String empty_draw_type = "";
463 
464 	if (parser.is_empty())
465 		return empty_draw_type;
466 
467 	while (parser.read() == OK) {
468 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
469 			empty_draw_type = parser.get_node_data();
470 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
471 			break; // end parsing text
472 	}
473 	return empty_draw_type;
474 }
475 
_parse_param(XMLParser & parser)476 Variant Collada::_parse_param(XMLParser &parser) {
477 
478 	if (parser.is_empty())
479 		return Variant();
480 
481 	String from = parser.get_node_name();
482 	Variant data;
483 
484 	while (parser.read() == OK) {
485 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
486 
487 			if (parser.get_node_name() == "float") {
488 
489 				parser.read();
490 				if (parser.get_node_type() == XMLParser::NODE_TEXT) {
491 
492 					data = parser.get_node_data().to_double();
493 				}
494 			} else if (parser.get_node_name() == "float2") {
495 
496 				Vector<float> v2 = _read_float_array(parser);
497 
498 				if (v2.size() >= 2) {
499 
500 					data = Vector2(v2[0], v2[1]);
501 				}
502 			} else if (parser.get_node_name() == "float3") {
503 
504 				Vector<float> v3 = _read_float_array(parser);
505 
506 				if (v3.size() >= 3) {
507 
508 					data = Vector3(v3[0], v3[1], v3[2]);
509 				}
510 			} else if (parser.get_node_name() == "float4") {
511 
512 				Vector<float> v4 = _read_float_array(parser);
513 
514 				if (v4.size() >= 4) {
515 
516 					data = Color(v4[0], v4[1], v4[2], v4[3]);
517 				}
518 			} else if (parser.get_node_name() == "sampler2D") {
519 
520 				while (parser.read() == OK) {
521 
522 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
523 
524 						if (parser.get_node_name() == "source") {
525 
526 							parser.read();
527 
528 							if (parser.get_node_type() == XMLParser::NODE_TEXT) {
529 
530 								data = parser.get_node_data();
531 							}
532 						}
533 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "sampler2D")
534 						break;
535 				}
536 			} else if (parser.get_node_name() == "surface") {
537 
538 				while (parser.read() == OK) {
539 
540 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
541 
542 						if (parser.get_node_name() == "init_from") {
543 
544 							parser.read();
545 
546 							if (parser.get_node_type() == XMLParser::NODE_TEXT) {
547 
548 								data = parser.get_node_data();
549 							}
550 						}
551 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "surface")
552 						break;
553 				}
554 			}
555 
556 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == from)
557 			break;
558 	}
559 
560 	COLLADA_PRINT("newparam ending " + parser.get_node_name());
561 	return data;
562 }
563 
_parse_effect_material(XMLParser & parser,Effect & effect,String & id)564 void Collada::_parse_effect_material(XMLParser &parser, Effect &effect, String &id) {
565 
566 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
567 		if (!parser.is_empty())
568 			parser.skip_section();
569 		return;
570 	}
571 
572 	while (parser.read() == OK) {
573 
574 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
575 
576 			// first come the tags we descend, but ignore the top-levels
577 
578 			COLLADA_PRINT("node name: " + parser.get_node_name());
579 
580 			if (!parser.is_empty() && (parser.get_node_name() == "profile_COMMON" || parser.get_node_name() == "technique" || parser.get_node_name() == "extra")) {
581 
582 				_parse_effect_material(parser, effect, id); // try again
583 
584 			} else if (parser.get_node_name() == "newparam") {
585 				String name = parser.get_attribute_value("sid");
586 				Variant value = _parse_param(parser);
587 				effect.params[name] = value;
588 				COLLADA_PRINT("param: " + name + " value:" + String(value));
589 
590 			} else if (parser.get_node_name() == "constant" ||
591 					   parser.get_node_name() == "lambert" ||
592 					   parser.get_node_name() == "phong" ||
593 					   parser.get_node_name() == "blinn") {
594 
595 				COLLADA_PRINT("shade model: " + parser.get_node_name());
596 				while (parser.read() == OK) {
597 
598 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
599 
600 						String what = parser.get_node_name();
601 
602 						if (what == "emission" ||
603 								what == "diffuse" ||
604 								what == "specular" ||
605 								what == "reflective") {
606 
607 							// color or texture types
608 							while (parser.read() == OK) {
609 
610 								if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
611 
612 									if (parser.get_node_name() == "color") {
613 
614 										Vector<float> colorarr = _read_float_array(parser);
615 										COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
616 
617 										if (colorarr.size() >= 3) {
618 
619 											// alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity
620 											Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
621 											if (what == "diffuse")
622 												effect.diffuse.color = color;
623 											if (what == "specular")
624 												effect.specular.color = color;
625 											if (what == "emission")
626 												effect.emission.color = color;
627 
628 											COLLADA_PRINT(what + " color: " + color);
629 										}
630 
631 									} else if (parser.get_node_name() == "texture") {
632 
633 										String sampler = parser.get_attribute_value("texture");
634 										if (!effect.params.has(sampler)) {
635 											ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
636 										} else {
637 											String surface = effect.params[sampler];
638 
639 											if (!effect.params.has(surface)) {
640 												ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
641 											} else {
642 												String uri = effect.params[surface];
643 
644 												if (what == "diffuse") {
645 													effect.diffuse.texture = uri;
646 												} else if (what == "specular") {
647 													effect.specular.texture = uri;
648 												} else if (what == "emission") {
649 													effect.emission.texture = uri;
650 												} else if (what == "bump") {
651 													if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
652 														WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
653 													}
654 
655 													effect.bump.texture = uri;
656 												}
657 
658 												COLLADA_PRINT(what + " texture: " + uri);
659 											}
660 										}
661 									} else if (!parser.is_empty())
662 										parser.skip_section();
663 
664 								} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == what)
665 									break;
666 							}
667 
668 						} else if (what == "shininess") {
669 							effect.shininess = _parse_param(parser);
670 						}
671 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && (parser.get_node_name() == "constant" ||
672 																								parser.get_node_name() == "lambert" ||
673 																								parser.get_node_name() == "phong" ||
674 																								parser.get_node_name() == "blinn"))
675 						break;
676 				}
677 			} else if (parser.get_node_name() == "double_sided" || parser.get_node_name() == "show_double_sided") { // colladamax / google earth
678 
679 				// 3DS Max / Google Earth double sided extension
680 				parser.read();
681 				effect.found_double_sided = true;
682 				effect.double_sided = parser.get_node_data().to_int();
683 				COLLADA_PRINT("double sided: " + itos(parser.get_node_data().to_int()));
684 			} else if (parser.get_node_name() == "unshaded") {
685 				parser.read();
686 				effect.unshaded = parser.get_node_data().to_int();
687 			} else if (parser.get_node_name() == "bump") {
688 
689 				// color or texture types
690 				while (parser.read() == OK) {
691 
692 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
693 
694 						if (parser.get_node_name() == "texture") {
695 
696 							String sampler = parser.get_attribute_value("texture");
697 							if (!effect.params.has(sampler)) {
698 								ERR_PRINT(String("Couldn't find sampler: " + sampler + " in material:" + id).utf8().get_data());
699 							} else {
700 								String surface = effect.params[sampler];
701 
702 								if (!effect.params.has(surface)) {
703 									ERR_PRINT(String("Couldn't find surface: " + surface + " in material:" + id).utf8().get_data());
704 								} else {
705 									String uri = effect.params[surface];
706 
707 									if (parser.has_attribute("bumptype") && parser.get_attribute_value("bumptype") != "NORMALMAP") {
708 										WARN_PRINT("'bump' texture type is not NORMALMAP, only NORMALMAP is supported.");
709 									}
710 
711 									effect.bump.texture = uri;
712 									COLLADA_PRINT(" bump: " + uri);
713 								}
714 							}
715 						} else if (!parser.is_empty())
716 							parser.skip_section();
717 
718 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "bump")
719 						break;
720 				}
721 
722 			} else if (!parser.is_empty())
723 				parser.skip_section();
724 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END &&
725 				   (parser.get_node_name() == "effect" ||
726 						   parser.get_node_name() == "profile_COMMON" ||
727 						   parser.get_node_name() == "technique" ||
728 						   parser.get_node_name() == "extra"))
729 			break;
730 	}
731 }
732 
_parse_effect(XMLParser & parser)733 void Collada::_parse_effect(XMLParser &parser) {
734 
735 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
736 		if (!parser.is_empty())
737 			parser.skip_section();
738 		return;
739 	}
740 
741 	String id = parser.get_attribute_value("id");
742 
743 	Effect effect;
744 	if (parser.has_attribute("name"))
745 		effect.name = parser.get_attribute_value("name");
746 	_parse_effect_material(parser, effect, id);
747 
748 	state.effect_map[id] = effect;
749 
750 	COLLADA_PRINT("Effect ID:" + id);
751 }
752 
_parse_camera(XMLParser & parser)753 void Collada::_parse_camera(XMLParser &parser) {
754 
755 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
756 		if (!parser.is_empty())
757 			parser.skip_section();
758 		return;
759 	}
760 
761 	String id = parser.get_attribute_value("id");
762 
763 	state.camera_data_map[id] = CameraData();
764 	CameraData &camera = state.camera_data_map[id];
765 
766 	while (parser.read() == OK) {
767 
768 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
769 
770 			String name = parser.get_node_name();
771 
772 			if (name == "perspective") {
773 
774 				camera.mode = CameraData::MODE_PERSPECTIVE;
775 			} else if (name == "orthographic") {
776 
777 				camera.mode = CameraData::MODE_ORTHOGONAL;
778 			} else if (name == "xfov") {
779 
780 				parser.read();
781 				camera.perspective.x_fov = parser.get_node_data().to_double();
782 
783 			} else if (name == "yfov") {
784 
785 				parser.read();
786 				camera.perspective.y_fov = parser.get_node_data().to_double();
787 			} else if (name == "xmag") {
788 
789 				parser.read();
790 				camera.orthogonal.x_mag = parser.get_node_data().to_double();
791 
792 			} else if (name == "ymag") {
793 
794 				parser.read();
795 				camera.orthogonal.y_mag = parser.get_node_data().to_double();
796 			} else if (name == "aspect_ratio") {
797 
798 				parser.read();
799 				camera.aspect = parser.get_node_data().to_double();
800 
801 			} else if (name == "znear") {
802 
803 				parser.read();
804 				camera.z_near = parser.get_node_data().to_double();
805 
806 			} else if (name == "zfar") {
807 
808 				parser.read();
809 				camera.z_far = parser.get_node_data().to_double();
810 			}
811 
812 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "camera")
813 			break; //end of <asset>
814 	}
815 
816 	COLLADA_PRINT("Camera ID:" + id);
817 }
818 
_parse_light(XMLParser & parser)819 void Collada::_parse_light(XMLParser &parser) {
820 
821 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
822 		if (!parser.is_empty())
823 			parser.skip_section();
824 		return;
825 	}
826 
827 	String id = parser.get_attribute_value("id");
828 
829 	state.light_data_map[id] = LightData();
830 	LightData &light = state.light_data_map[id];
831 
832 	while (parser.read() == OK) {
833 
834 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
835 
836 			String name = parser.get_node_name();
837 
838 			if (name == "ambient") {
839 
840 				light.mode = LightData::MODE_AMBIENT;
841 			} else if (name == "directional") {
842 
843 				light.mode = LightData::MODE_DIRECTIONAL;
844 			} else if (name == "point") {
845 
846 				light.mode = LightData::MODE_OMNI;
847 			} else if (name == "spot") {
848 
849 				light.mode = LightData::MODE_SPOT;
850 			} else if (name == "color") {
851 
852 				parser.read();
853 				Vector<float> colorarr = _read_float_array(parser);
854 				COLLADA_PRINT("colorarr size: " + rtos(colorarr.size()));
855 
856 				if (colorarr.size() >= 4) {
857 					// alpha strangely not alright? maybe it needs to be multiplied by value as a channel intensity
858 					Color color(colorarr[0], colorarr[1], colorarr[2], 1.0);
859 					light.color = color;
860 				}
861 
862 			} else if (name == "constant_attenuation") {
863 
864 				parser.read();
865 				light.constant_att = parser.get_node_data().to_double();
866 			} else if (name == "linear_attenuation") {
867 
868 				parser.read();
869 				light.linear_att = parser.get_node_data().to_double();
870 			} else if (name == "quadratic_attenuation") {
871 
872 				parser.read();
873 				light.quad_att = parser.get_node_data().to_double();
874 			} else if (name == "falloff_angle") {
875 
876 				parser.read();
877 				light.spot_angle = parser.get_node_data().to_double();
878 
879 			} else if (name == "falloff_exponent") {
880 
881 				parser.read();
882 				light.spot_exp = parser.get_node_data().to_double();
883 			}
884 
885 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "light")
886 			break; //end of <asset>
887 	}
888 
889 	COLLADA_PRINT("Light ID:" + id);
890 }
891 
_parse_curve_geometry(XMLParser & parser,String p_id,String p_name)892 void Collada::_parse_curve_geometry(XMLParser &parser, String p_id, String p_name) {
893 
894 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
895 		if (!parser.is_empty())
896 			parser.skip_section();
897 		return;
898 	}
899 
900 	//load everything into a pre dictionary
901 
902 	state.curve_data_map[p_id] = CurveData();
903 
904 	CurveData &curvedata = state.curve_data_map[p_id];
905 	curvedata.name = p_name;
906 
907 	COLLADA_PRINT("curve name: " + p_name);
908 
909 	String current_source;
910 	// handles geometry node and the curve children in this loop
911 	// read sources with arrays and accessor for each curve
912 	if (parser.is_empty()) {
913 		return;
914 	}
915 
916 	while (parser.read() == OK) {
917 
918 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
919 
920 			String section = parser.get_node_name();
921 
922 			if (section == "source") {
923 
924 				String id = parser.get_attribute_value("id");
925 				curvedata.sources[id] = CurveData::Source();
926 				current_source = id;
927 				COLLADA_PRINT("source data: " + id);
928 
929 			} else if (section == "float_array" || section == "array") {
930 				// create a new array and read it.
931 				if (curvedata.sources.has(current_source)) {
932 
933 					curvedata.sources[current_source].array = _read_float_array(parser);
934 					COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
935 				}
936 			} else if (section == "Name_array") {
937 				// create a new array and read it.
938 				if (curvedata.sources.has(current_source)) {
939 
940 					curvedata.sources[current_source].sarray = _read_string_array(parser);
941 					COLLADA_PRINT("section: " + current_source + " read " + itos(curvedata.sources[current_source].array.size()) + " values.");
942 				}
943 
944 			} else if (section == "technique_common") {
945 				//skip it
946 			} else if (section == "accessor") { // child of source (below a technique tag)
947 
948 				if (curvedata.sources.has(current_source)) {
949 					curvedata.sources[current_source].stride = parser.get_attribute_value("stride").to_int();
950 					COLLADA_PRINT("section: " + current_source + " stride " + itos(curvedata.sources[current_source].stride));
951 				}
952 			} else if (section == "control_vertices") {
953 
954 				while (parser.read() == OK) {
955 
956 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
957 
958 						if (parser.get_node_name() == "input") {
959 
960 							String semantic = parser.get_attribute_value("semantic");
961 							String source = _uri_to_id(parser.get_attribute_value("source"));
962 
963 							curvedata.control_vertices[semantic] = source;
964 
965 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
966 						}
967 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
968 						break;
969 				}
970 
971 			} else if (!parser.is_empty()) {
972 
973 				parser.skip_section();
974 			}
975 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "spline")
976 			break;
977 	}
978 }
979 
_parse_mesh_geometry(XMLParser & parser,String p_id,String p_name)980 void Collada::_parse_mesh_geometry(XMLParser &parser, String p_id, String p_name) {
981 
982 	if (!(state.import_flags & IMPORT_FLAG_SCENE)) {
983 		if (!parser.is_empty())
984 			parser.skip_section();
985 		return;
986 	}
987 
988 	//load everything into a pre dictionary
989 
990 	state.mesh_data_map[p_id] = MeshData();
991 
992 	MeshData &meshdata = state.mesh_data_map[p_id];
993 	meshdata.name = p_name;
994 
995 	COLLADA_PRINT("mesh name: " + p_name);
996 
997 	String current_source;
998 	// handles geometry node and the mesh children in this loop
999 	// read sources with arrays and accessor for each mesh
1000 	if (parser.is_empty()) {
1001 		return;
1002 	}
1003 
1004 	while (parser.read() == OK) {
1005 
1006 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1007 
1008 			String section = parser.get_node_name();
1009 
1010 			if (section == "source") {
1011 
1012 				String id = parser.get_attribute_value("id");
1013 				meshdata.sources[id] = MeshData::Source();
1014 				current_source = id;
1015 				COLLADA_PRINT("source data: " + id);
1016 
1017 			} else if (section == "float_array" || section == "array") {
1018 				// create a new array and read it.
1019 				if (meshdata.sources.has(current_source)) {
1020 
1021 					meshdata.sources[current_source].array = _read_float_array(parser);
1022 					COLLADA_PRINT("section: " + current_source + " read " + itos(meshdata.sources[current_source].array.size()) + " values.");
1023 				}
1024 			} else if (section == "technique_common") {
1025 				//skip it
1026 			} else if (section == "accessor") { // child of source (below a technique tag)
1027 
1028 				if (meshdata.sources.has(current_source)) {
1029 					meshdata.sources[current_source].stride = parser.get_attribute_value("stride").to_int();
1030 					COLLADA_PRINT("section: " + current_source + " stride " + itos(meshdata.sources[current_source].stride));
1031 				}
1032 			} else if (section == "vertices") {
1033 
1034 				MeshData::Vertices vert;
1035 				String id = parser.get_attribute_value("id");
1036 
1037 				while (parser.read() == OK) {
1038 
1039 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1040 
1041 						if (parser.get_node_name() == "input") {
1042 
1043 							String semantic = parser.get_attribute_value("semantic");
1044 							String source = _uri_to_id(parser.get_attribute_value("source"));
1045 
1046 							vert.sources[semantic] = source;
1047 
1048 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
1049 						}
1050 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
1051 						break;
1052 				}
1053 
1054 				meshdata.vertices[id] = vert;
1055 
1056 			} else if (section == "triangles" || section == "polylist" || section == "polygons") {
1057 
1058 				bool polygons = (section == "polygons");
1059 				if (polygons) {
1060 					WARN_PRINT("Primitive type \"polygons\" is not well supported (concave shapes may fail). To ensure that the geometry is properly imported, please re-export using \"triangles\" or \"polylist\".");
1061 				}
1062 				MeshData::Primitives prim;
1063 
1064 				if (parser.has_attribute("material"))
1065 					prim.material = parser.get_attribute_value("material");
1066 				prim.count = parser.get_attribute_value("count").to_int();
1067 				prim.vertex_size = 0;
1068 				int last_ref = 0;
1069 
1070 				while (parser.read() == OK) {
1071 
1072 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1073 
1074 						if (parser.get_node_name() == "input") {
1075 
1076 							String semantic = parser.get_attribute_value("semantic");
1077 							String source = _uri_to_id(parser.get_attribute_value("source"));
1078 
1079 							if (semantic == "TEXCOORD") {
1080 								/*
1081 								if (parser.has_attribute("set"))// a texcoord
1082 									semantic+=parser.get_attribute_value("set");
1083 								else
1084 									semantic="TEXCOORD0";*/
1085 								semantic = "TEXCOORD" + itos(last_ref++);
1086 							}
1087 							int offset = parser.get_attribute_value("offset").to_int();
1088 
1089 							MeshData::Primitives::SourceRef sref;
1090 							sref.source = source;
1091 							sref.offset = offset;
1092 							prim.sources[semantic] = sref;
1093 							prim.vertex_size = MAX(prim.vertex_size, offset + 1);
1094 
1095 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
1096 
1097 						} else if (parser.get_node_name() == "p") { //indices
1098 
1099 							Vector<float> values = _read_float_array(parser);
1100 							if (polygons) {
1101 
1102 								ERR_CONTINUE(prim.vertex_size == 0);
1103 								prim.polygons.push_back(values.size() / prim.vertex_size);
1104 								int from = prim.indices.size();
1105 								prim.indices.resize(from + values.size());
1106 								for (int i = 0; i < values.size(); i++)
1107 									prim.indices.write[from + i] = values[i];
1108 
1109 							} else if (prim.vertex_size > 0) {
1110 								prim.indices = values;
1111 							}
1112 
1113 							COLLADA_PRINT("read " + itos(values.size()) + " index values");
1114 
1115 						} else if (parser.get_node_name() == "vcount") { // primitive
1116 
1117 							Vector<float> values = _read_float_array(parser);
1118 							prim.polygons = values;
1119 							COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
1120 						}
1121 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
1122 						break;
1123 				}
1124 
1125 				meshdata.primitives.push_back(prim);
1126 
1127 			} else if (parser.get_node_name() == "double_sided") {
1128 
1129 				parser.read();
1130 				meshdata.found_double_sided = true;
1131 				meshdata.double_sided = parser.get_node_data().to_int();
1132 
1133 			} else if (parser.get_node_name() == "polygons") {
1134 				ERR_PRINT("Primitive type \"polygons\" not supported, re-export using \"polylist\" or \"triangles\".");
1135 			} else if (!parser.is_empty()) {
1136 
1137 				parser.skip_section();
1138 			}
1139 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "mesh")
1140 			break;
1141 	}
1142 }
1143 
_parse_skin_controller(XMLParser & parser,String p_id)1144 void Collada::_parse_skin_controller(XMLParser &parser, String p_id) {
1145 
1146 	state.skin_controller_data_map[p_id] = SkinControllerData();
1147 	SkinControllerData &skindata = state.skin_controller_data_map[p_id];
1148 
1149 	skindata.base = _uri_to_id(parser.get_attribute_value("source"));
1150 
1151 	String current_source;
1152 
1153 	while (parser.read() == OK) {
1154 
1155 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1156 
1157 			String section = parser.get_node_name();
1158 
1159 			if (section == "bind_shape_matrix") {
1160 
1161 				skindata.bind_shape = _read_transform(parser);
1162 #ifdef COLLADA_IMPORT_SCALE_SCENE
1163 				skindata.bind_shape.origin *= state.unit_scale;
1164 
1165 #endif
1166 				COLLADA_PRINT("skeleton bind shape transform: " + skindata.bind_shape);
1167 
1168 			} else if (section == "source") {
1169 
1170 				String id = parser.get_attribute_value("id");
1171 				skindata.sources[id] = SkinControllerData::Source();
1172 				current_source = id;
1173 				COLLADA_PRINT("source data: " + id);
1174 
1175 			} else if (section == "float_array" || section == "array") {
1176 				// create a new array and read it.
1177 				if (skindata.sources.has(current_source)) {
1178 
1179 					skindata.sources[current_source].array = _read_float_array(parser);
1180 					COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values.");
1181 				}
1182 			} else if (section == "Name_array" || section == "IDREF_array") {
1183 				// create a new array and read it.
1184 
1185 				if (section == "IDREF_array")
1186 					skindata.use_idrefs = true;
1187 				if (skindata.sources.has(current_source)) {
1188 
1189 					skindata.sources[current_source].sarray = _read_string_array(parser);
1190 					if (section == "IDREF_array") {
1191 						Vector<String> sa = skindata.sources[current_source].sarray;
1192 						for (int i = 0; i < sa.size(); i++)
1193 							state.idref_joints.insert(sa[i]);
1194 					}
1195 					COLLADA_PRINT("section: " + current_source + " read " + itos(skindata.sources[current_source].array.size()) + " values.");
1196 				}
1197 			} else if (section == "technique_common") {
1198 				//skip it
1199 			} else if (section == "accessor") { // child of source (below a technique tag)
1200 
1201 				if (skindata.sources.has(current_source)) {
1202 
1203 					int stride = 1;
1204 					if (parser.has_attribute("stride"))
1205 						stride = parser.get_attribute_value("stride").to_int();
1206 
1207 					skindata.sources[current_source].stride = stride;
1208 					COLLADA_PRINT("section: " + current_source + " stride " + itos(skindata.sources[current_source].stride));
1209 				}
1210 
1211 			} else if (section == "joints") {
1212 
1213 				SkinControllerData::Joints joint;
1214 
1215 				while (parser.read() == OK) {
1216 
1217 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1218 
1219 						if (parser.get_node_name() == "input") {
1220 
1221 							String semantic = parser.get_attribute_value("semantic");
1222 							String source = _uri_to_id(parser.get_attribute_value("source"));
1223 
1224 							joint.sources[semantic] = source;
1225 
1226 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
1227 						}
1228 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
1229 						break;
1230 				}
1231 
1232 				skindata.joints = joint;
1233 
1234 			} else if (section == "vertex_weights") {
1235 
1236 				SkinControllerData::Weights weights;
1237 
1238 				weights.count = parser.get_attribute_value("count").to_int();
1239 
1240 				while (parser.read() == OK) {
1241 
1242 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1243 
1244 						if (parser.get_node_name() == "input") {
1245 
1246 							String semantic = parser.get_attribute_value("semantic");
1247 							String source = _uri_to_id(parser.get_attribute_value("source"));
1248 
1249 							int offset = parser.get_attribute_value("offset").to_int();
1250 
1251 							SkinControllerData::Weights::SourceRef sref;
1252 							sref.source = source;
1253 							sref.offset = offset;
1254 							weights.sources[semantic] = sref;
1255 
1256 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source + " offset: " + itos(offset));
1257 
1258 						} else if (parser.get_node_name() == "v") { //indices
1259 
1260 							Vector<float> values = _read_float_array(parser);
1261 							weights.indices = values;
1262 							COLLADA_PRINT("read " + itos(values.size()) + " index values");
1263 
1264 						} else if (parser.get_node_name() == "vcount") { // weightsitive
1265 
1266 							Vector<float> values = _read_float_array(parser);
1267 							weights.sets = values;
1268 							COLLADA_PRINT("read " + itos(values.size()) + " polygon values");
1269 						}
1270 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
1271 						break;
1272 				}
1273 
1274 				skindata.weights = weights;
1275 			}
1276 			/*
1277 			else if (!parser.is_empty())
1278 				parser.skip_section();
1279 			*/
1280 
1281 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "skin")
1282 			break;
1283 	}
1284 
1285 	/* STORE REST MATRICES */
1286 
1287 	Vector<Transform> rests;
1288 	ERR_FAIL_COND(!skindata.joints.sources.has("JOINT"));
1289 	ERR_FAIL_COND(!skindata.joints.sources.has("INV_BIND_MATRIX"));
1290 
1291 	String joint_arr = skindata.joints.sources["JOINT"];
1292 	String ibm = skindata.joints.sources["INV_BIND_MATRIX"];
1293 
1294 	ERR_FAIL_COND(!skindata.sources.has(joint_arr));
1295 	ERR_FAIL_COND(!skindata.sources.has(ibm));
1296 
1297 	SkinControllerData::Source &joint_source = skindata.sources[joint_arr];
1298 	SkinControllerData::Source &ibm_source = skindata.sources[ibm];
1299 
1300 	ERR_FAIL_COND(joint_source.sarray.size() != ibm_source.array.size() / 16);
1301 
1302 	for (int i = 0; i < joint_source.sarray.size(); i++) {
1303 
1304 		String name = joint_source.sarray[i];
1305 		Transform xform = _read_transform_from_array(ibm_source.array, i * 16); //<- this is a mistake, it must be applied to vertices
1306 		xform.affine_invert(); // inverse for rest, because it's an inverse
1307 #ifdef COLLADA_IMPORT_SCALE_SCENE
1308 		xform.origin *= state.unit_scale;
1309 #endif
1310 		skindata.bone_rest_map[name] = xform;
1311 	}
1312 }
1313 
_parse_morph_controller(XMLParser & parser,String p_id)1314 void Collada::_parse_morph_controller(XMLParser &parser, String p_id) {
1315 
1316 	state.morph_controller_data_map[p_id] = MorphControllerData();
1317 	MorphControllerData &morphdata = state.morph_controller_data_map[p_id];
1318 
1319 	morphdata.mesh = _uri_to_id(parser.get_attribute_value("source"));
1320 	morphdata.mode = parser.get_attribute_value("method");
1321 	String current_source;
1322 
1323 	while (parser.read() == OK) {
1324 
1325 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1326 
1327 			String section = parser.get_node_name();
1328 
1329 			if (section == "source") {
1330 
1331 				String id = parser.get_attribute_value("id");
1332 				morphdata.sources[id] = MorphControllerData::Source();
1333 				current_source = id;
1334 				COLLADA_PRINT("source data: " + id);
1335 
1336 			} else if (section == "float_array" || section == "array") {
1337 				// create a new array and read it.
1338 				if (morphdata.sources.has(current_source)) {
1339 
1340 					morphdata.sources[current_source].array = _read_float_array(parser);
1341 					COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
1342 				}
1343 			} else if (section == "Name_array" || section == "IDREF_array") {
1344 				// create a new array and read it.
1345 
1346 				/*
1347 				if (section=="IDREF_array")
1348 					morphdata.use_idrefs=true;
1349 				*/
1350 				if (morphdata.sources.has(current_source)) {
1351 
1352 					morphdata.sources[current_source].sarray = _read_string_array(parser);
1353 					/*
1354 					if (section=="IDREF_array") {
1355 						Vector<String> sa = morphdata.sources[current_source].sarray;
1356 						for(int i=0;i<sa.size();i++)
1357 							state.idref_joints.insert(sa[i]);
1358 					}*/
1359 					COLLADA_PRINT("section: " + current_source + " read " + itos(morphdata.sources[current_source].array.size()) + " values.");
1360 				}
1361 			} else if (section == "technique_common") {
1362 				//skip it
1363 			} else if (section == "accessor") { // child of source (below a technique tag)
1364 
1365 				if (morphdata.sources.has(current_source)) {
1366 
1367 					int stride = 1;
1368 					if (parser.has_attribute("stride"))
1369 						stride = parser.get_attribute_value("stride").to_int();
1370 
1371 					morphdata.sources[current_source].stride = stride;
1372 					COLLADA_PRINT("section: " + current_source + " stride " + itos(morphdata.sources[current_source].stride));
1373 				}
1374 
1375 			} else if (section == "targets") {
1376 
1377 				while (parser.read() == OK) {
1378 
1379 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1380 
1381 						if (parser.get_node_name() == "input") {
1382 
1383 							String semantic = parser.get_attribute_value("semantic");
1384 							String source = _uri_to_id(parser.get_attribute_value("source"));
1385 
1386 							morphdata.targets[semantic] = source;
1387 
1388 							COLLADA_PRINT(section + " input semantic: " + semantic + " source: " + source);
1389 						}
1390 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == section)
1391 						break;
1392 				}
1393 			}
1394 			/*
1395 			else if (!parser.is_empty())
1396 				parser.skip_section();
1397 			*/
1398 
1399 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "morph")
1400 			break;
1401 	}
1402 
1403 	if (morphdata.targets.has("MORPH_WEIGHT")) {
1404 
1405 		state.morph_name_map[morphdata.targets["MORPH_WEIGHT"]] = p_id;
1406 	}
1407 }
1408 
_parse_controller(XMLParser & parser)1409 void Collada::_parse_controller(XMLParser &parser) {
1410 
1411 	String id = parser.get_attribute_value("id");
1412 
1413 	if (parser.is_empty()) {
1414 		return;
1415 	}
1416 
1417 	while (parser.read() == OK) {
1418 
1419 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1420 
1421 			String section = parser.get_node_name();
1422 
1423 			if (section == "skin") {
1424 				_parse_skin_controller(parser, id);
1425 			} else if (section == "morph") {
1426 				_parse_morph_controller(parser, id);
1427 			}
1428 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "controller")
1429 			break;
1430 	}
1431 }
1432 
_parse_visual_instance_geometry(XMLParser & parser)1433 Collada::Node *Collada::_parse_visual_instance_geometry(XMLParser &parser) {
1434 
1435 	String type = parser.get_node_name();
1436 	NodeGeometry *geom = memnew(NodeGeometry);
1437 	geom->controller = type == "instance_controller";
1438 	geom->source = _uri_to_id(parser.get_attribute_value_safe("url"));
1439 
1440 	if (parser.is_empty()) //nothing else to parse...
1441 		return geom;
1442 	// try to find also many materials and skeletons!
1443 	while (parser.read() == OK) {
1444 
1445 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1446 
1447 			if (parser.get_node_name() == "instance_material") {
1448 
1449 				String symbol = parser.get_attribute_value("symbol");
1450 				String target = _uri_to_id(parser.get_attribute_value("target"));
1451 
1452 				NodeGeometry::Material mat;
1453 				mat.target = target;
1454 				geom->material_map[symbol] = mat;
1455 				COLLADA_PRINT("uses material: '" + target + "' on primitive'" + symbol + "'");
1456 			} else if (parser.get_node_name() == "skeleton") {
1457 
1458 				parser.read();
1459 				String uri = _uri_to_id(parser.get_node_data());
1460 				if (uri != "") {
1461 					geom->skeletons.push_back(uri);
1462 				}
1463 			}
1464 
1465 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == type)
1466 			break;
1467 	}
1468 
1469 	if (geom->controller) {
1470 
1471 		if (geom->skeletons.empty()) {
1472 			//XSI style
1473 
1474 			if (state.skin_controller_data_map.has(geom->source)) {
1475 				SkinControllerData *skin = &state.skin_controller_data_map[geom->source];
1476 				//case where skeletons reference bones with IDREF (XSI)
1477 				ERR_FAIL_COND_V(!skin->joints.sources.has("JOINT"), geom);
1478 				String joint_arr = skin->joints.sources["JOINT"];
1479 				ERR_FAIL_COND_V(!skin->sources.has(joint_arr), geom);
1480 				Collada::SkinControllerData::Source &joint_source = skin->sources[joint_arr];
1481 				geom->skeletons = joint_source.sarray; //quite crazy, but should work.
1482 			}
1483 		}
1484 	}
1485 
1486 	return geom;
1487 }
1488 
_parse_visual_instance_camera(XMLParser & parser)1489 Collada::Node *Collada::_parse_visual_instance_camera(XMLParser &parser) {
1490 
1491 	NodeCamera *cam = memnew(NodeCamera);
1492 	cam->camera = _uri_to_id(parser.get_attribute_value_safe("url"));
1493 
1494 	if (state.up_axis == Vector3::AXIS_Z) //collada weirdness
1495 		cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5);
1496 
1497 	if (parser.is_empty()) //nothing else to parse...
1498 		return cam;
1499 
1500 	while (parser.read() == OK) {
1501 
1502 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_camera")
1503 			break;
1504 	}
1505 
1506 	return cam;
1507 }
1508 
_parse_visual_instance_light(XMLParser & parser)1509 Collada::Node *Collada::_parse_visual_instance_light(XMLParser &parser) {
1510 
1511 	NodeLight *cam = memnew(NodeLight);
1512 	cam->light = _uri_to_id(parser.get_attribute_value_safe("url"));
1513 
1514 	if (state.up_axis == Vector3::AXIS_Z) //collada weirdness
1515 		cam->post_transform.basis.rotate(Vector3(1, 0, 0), -Math_PI * 0.5);
1516 
1517 	if (parser.is_empty()) //nothing else to parse...
1518 		return cam;
1519 
1520 	while (parser.read() == OK) {
1521 
1522 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "instance_light")
1523 			break;
1524 	}
1525 
1526 	return cam;
1527 }
1528 
_parse_visual_node_instance_data(XMLParser & parser)1529 Collada::Node *Collada::_parse_visual_node_instance_data(XMLParser &parser) {
1530 
1531 	String instance_type = parser.get_node_name();
1532 
1533 	if (instance_type == "instance_geometry" || instance_type == "instance_controller") {
1534 		return _parse_visual_instance_geometry(parser);
1535 	} else if (instance_type == "instance_camera") {
1536 
1537 		return _parse_visual_instance_camera(parser);
1538 	} else if (instance_type == "instance_light") {
1539 		return _parse_visual_instance_light(parser);
1540 	}
1541 
1542 	if (parser.is_empty()) //nothing else to parse...
1543 		return NULL;
1544 
1545 	while (parser.read() == OK) {
1546 
1547 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == instance_type)
1548 			break;
1549 	}
1550 
1551 	return NULL;
1552 }
1553 
_parse_visual_scene_node(XMLParser & parser)1554 Collada::Node *Collada::_parse_visual_scene_node(XMLParser &parser) {
1555 
1556 	String name;
1557 
1558 	String id = parser.get_attribute_value_safe("id");
1559 
1560 	bool found_name = false;
1561 
1562 	if (id == "") {
1563 
1564 		id = "%NODEID%" + itos(Math::rand());
1565 
1566 	} else {
1567 		found_name = true;
1568 	}
1569 
1570 	Vector<Node::XForm> xform_list;
1571 	Vector<Node *> children;
1572 
1573 	String empty_draw_type = "";
1574 
1575 	Node *node = NULL;
1576 
1577 	name = parser.has_attribute("name") ? parser.get_attribute_value_safe("name") : parser.get_attribute_value_safe("id");
1578 	if (name == "") {
1579 
1580 		name = id;
1581 	} else {
1582 		found_name = true;
1583 	}
1584 
1585 	if ((parser.has_attribute("type") && parser.get_attribute_value("type") == "JOINT") || state.idref_joints.has(name)) {
1586 		// handle a bone
1587 
1588 		NodeJoint *joint = memnew(NodeJoint);
1589 
1590 		if (parser.has_attribute("sid")) { //bones may not have sid
1591 			joint->sid = parser.get_attribute_value("sid");
1592 			//state.bone_map[joint->sid]=joint;
1593 		} else if (state.idref_joints.has(name)) {
1594 			joint->sid = name; //kind of a cheat but..
1595 		} else if (parser.has_attribute("name")) {
1596 			joint->sid = parser.get_attribute_value_safe("name");
1597 		}
1598 
1599 		if (joint->sid != "") {
1600 			state.sid_to_node_map[joint->sid] = id;
1601 		}
1602 
1603 		node = joint;
1604 	}
1605 
1606 	while (parser.read() == OK) {
1607 
1608 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1609 
1610 			String section = parser.get_node_name();
1611 
1612 			if (section == "translate") {
1613 				Node::XForm xf;
1614 				if (parser.has_attribute("sid")) {
1615 					xf.id = parser.get_attribute_value("sid");
1616 				}
1617 				xf.op = Node::XForm::OP_TRANSLATE;
1618 
1619 				Vector<float> xlt = _read_float_array(parser);
1620 				xf.data = xlt;
1621 				xform_list.push_back(xf);
1622 
1623 			} else if (section == "rotate") {
1624 				Node::XForm xf;
1625 				if (parser.has_attribute("sid")) {
1626 					xf.id = parser.get_attribute_value("sid");
1627 				}
1628 				xf.op = Node::XForm::OP_ROTATE;
1629 
1630 				Vector<float> rot = _read_float_array(parser);
1631 				xf.data = rot;
1632 
1633 				xform_list.push_back(xf);
1634 
1635 			} else if (section == "scale") {
1636 				Node::XForm xf;
1637 				if (parser.has_attribute("sid")) {
1638 					xf.id = parser.get_attribute_value("sid");
1639 				}
1640 
1641 				xf.op = Node::XForm::OP_SCALE;
1642 
1643 				Vector<float> scale = _read_float_array(parser);
1644 
1645 				xf.data = scale;
1646 
1647 				xform_list.push_back(xf);
1648 
1649 			} else if (section == "matrix") {
1650 				Node::XForm xf;
1651 				if (parser.has_attribute("sid")) {
1652 					xf.id = parser.get_attribute_value("sid");
1653 				}
1654 				xf.op = Node::XForm::OP_MATRIX;
1655 
1656 				Vector<float> matrix = _read_float_array(parser);
1657 
1658 				xf.data = matrix;
1659 				String mtx;
1660 				for (int i = 0; i < matrix.size(); i++)
1661 					mtx += " " + rtos(matrix[i]);
1662 
1663 				xform_list.push_back(xf);
1664 
1665 			} else if (section == "visibility") {
1666 				Node::XForm xf;
1667 				if (parser.has_attribute("sid")) {
1668 					xf.id = parser.get_attribute_value("sid");
1669 				}
1670 				xf.op = Node::XForm::OP_VISIBILITY;
1671 
1672 				Vector<float> visible = _read_float_array(parser);
1673 
1674 				xf.data = visible;
1675 
1676 				xform_list.push_back(xf);
1677 
1678 			} else if (section == "empty_draw_type") {
1679 				empty_draw_type = _read_empty_draw_type(parser);
1680 			} else if (section == "technique" || section == "extra") {
1681 
1682 			} else if (section != "node") {
1683 				//usually what defines the type of node
1684 				if (section.begins_with("instance_")) {
1685 
1686 					if (!node) {
1687 
1688 						node = _parse_visual_node_instance_data(parser);
1689 
1690 					} else {
1691 						ERR_PRINT("Multiple instance_* not supported.");
1692 					}
1693 				}
1694 
1695 			} else {
1696 
1697 				/* Found a child node!! what to do..*/
1698 
1699 				Node *child = _parse_visual_scene_node(parser);
1700 				children.push_back(child);
1701 			}
1702 
1703 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "node")
1704 			break;
1705 	}
1706 
1707 	if (!node) {
1708 
1709 		node = memnew(Node); //generic node, nothing of relevance found
1710 	}
1711 
1712 	node->noname = !found_name;
1713 	node->xform_list = xform_list;
1714 	node->children = children;
1715 	for (int i = 0; i < children.size(); i++) {
1716 		node->children[i]->parent = node;
1717 	}
1718 
1719 	node->name = name;
1720 	node->id = id;
1721 	node->empty_draw_type = empty_draw_type;
1722 
1723 	if (node->children.size() == 1) {
1724 		if (node->children[0]->noname && !node->noname) {
1725 			node->children[0]->name = node->name;
1726 			node->name = node->name + "-base";
1727 		}
1728 	}
1729 
1730 	node->default_transform = node->compute_transform(*this);
1731 	state.scene_map[id] = node;
1732 
1733 	return node;
1734 }
1735 
_parse_visual_scene(XMLParser & parser)1736 void Collada::_parse_visual_scene(XMLParser &parser) {
1737 
1738 	String id = parser.get_attribute_value("id");
1739 
1740 	if (parser.is_empty()) {
1741 		return;
1742 	}
1743 
1744 	state.visual_scene_map[id] = VisualScene();
1745 	VisualScene &vscene = state.visual_scene_map[id];
1746 
1747 	if (parser.has_attribute("name"))
1748 		vscene.name = parser.get_attribute_value("name");
1749 
1750 	while (parser.read() == OK) {
1751 
1752 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1753 
1754 			String section = parser.get_node_name();
1755 
1756 			if (section == "node") {
1757 				vscene.root_nodes.push_back(_parse_visual_scene_node(parser));
1758 			}
1759 
1760 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "visual_scene")
1761 			break;
1762 	}
1763 
1764 	COLLADA_PRINT("Scene ID:" + id);
1765 }
1766 
_parse_animation(XMLParser & parser)1767 void Collada::_parse_animation(XMLParser &parser) {
1768 
1769 	if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
1770 		if (!parser.is_empty())
1771 			parser.skip_section();
1772 
1773 		return;
1774 	}
1775 
1776 	Map<String, Vector<float> > float_sources;
1777 	Map<String, Vector<String> > string_sources;
1778 	Map<String, int> source_strides;
1779 	Map<String, Map<String, String> > samplers;
1780 	Map<String, Vector<String> > source_param_names;
1781 	Map<String, Vector<String> > source_param_types;
1782 
1783 	String id = "";
1784 	if (parser.has_attribute("id"))
1785 		id = parser.get_attribute_value("id");
1786 
1787 	String current_source;
1788 	String current_sampler;
1789 	Vector<String> channel_sources;
1790 	Vector<String> channel_targets;
1791 
1792 	while (parser.read() == OK) {
1793 
1794 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
1795 
1796 			String name = parser.get_node_name();
1797 			if (name == "source") {
1798 
1799 				current_source = parser.get_attribute_value("id");
1800 				source_param_names[current_source] = Vector<String>();
1801 				source_param_types[current_source] = Vector<String>();
1802 
1803 			} else if (name == "float_array") {
1804 
1805 				if (current_source != "") {
1806 					float_sources[current_source] = _read_float_array(parser);
1807 				}
1808 
1809 			} else if (name == "Name_array") {
1810 
1811 				if (current_source != "") {
1812 					string_sources[current_source] = _read_string_array(parser);
1813 				}
1814 			} else if (name == "accessor") {
1815 
1816 				if (current_source != "" && parser.has_attribute("stride")) {
1817 					source_strides[current_source] = parser.get_attribute_value("stride").to_int();
1818 				}
1819 			} else if (name == "sampler") {
1820 
1821 				current_sampler = parser.get_attribute_value("id");
1822 				samplers[current_sampler] = Map<String, String>();
1823 			} else if (name == "param") {
1824 
1825 				if (parser.has_attribute("name"))
1826 					source_param_names[current_source].push_back(parser.get_attribute_value("name"));
1827 				else
1828 					source_param_names[current_source].push_back("");
1829 
1830 				if (parser.has_attribute("type"))
1831 					source_param_types[current_source].push_back(parser.get_attribute_value("type"));
1832 				else
1833 					source_param_types[current_source].push_back("");
1834 
1835 			} else if (name == "input") {
1836 
1837 				if (current_sampler != "") {
1838 
1839 					samplers[current_sampler][parser.get_attribute_value("semantic")] = parser.get_attribute_value("source");
1840 				}
1841 
1842 			} else if (name == "channel") {
1843 
1844 				channel_sources.push_back(parser.get_attribute_value("source"));
1845 				channel_targets.push_back(parser.get_attribute_value("target"));
1846 			}
1847 
1848 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation")
1849 			break; //end of <asset>
1850 	}
1851 
1852 	for (int i = 0; i < channel_sources.size(); i++) {
1853 
1854 		String source = _uri_to_id(channel_sources[i]);
1855 		String target = channel_targets[i];
1856 		ERR_CONTINUE(!samplers.has(source));
1857 		Map<String, String> &sampler = samplers[source];
1858 
1859 		ERR_CONTINUE(!sampler.has("INPUT")); //no input semantic? wtf?
1860 		String input_id = _uri_to_id(sampler["INPUT"]);
1861 		COLLADA_PRINT("input id is " + input_id);
1862 		ERR_CONTINUE(!float_sources.has(input_id));
1863 
1864 		ERR_CONTINUE(!sampler.has("OUTPUT"));
1865 		String output_id = _uri_to_id(sampler["OUTPUT"]);
1866 		ERR_CONTINUE(!float_sources.has(output_id));
1867 
1868 		ERR_CONTINUE(!source_param_names.has(output_id));
1869 
1870 		Vector<String> &names = source_param_names[output_id];
1871 
1872 		for (int l = 0; l < names.size(); l++) {
1873 
1874 			String name = names[l];
1875 
1876 			Vector<float> &time_keys = float_sources[input_id];
1877 			int key_count = time_keys.size();
1878 
1879 			AnimationTrack track; //begin crating track
1880 			track.id = id;
1881 
1882 			track.keys.resize(key_count);
1883 
1884 			for (int j = 0; j < key_count; j++) {
1885 				track.keys.write[j].time = time_keys[j];
1886 				state.animation_length = MAX(state.animation_length, time_keys[j]);
1887 			}
1888 
1889 			//now read actual values
1890 
1891 			int stride = 1;
1892 
1893 			if (source_strides.has(output_id))
1894 				stride = source_strides[output_id];
1895 			int output_len = stride / names.size();
1896 
1897 			ERR_CONTINUE(output_len == 0);
1898 			ERR_CONTINUE(!float_sources.has(output_id));
1899 
1900 			Vector<float> &output = float_sources[output_id];
1901 
1902 			ERR_CONTINUE_MSG((output.size() / stride) != key_count, "Wrong number of keys in output.");
1903 
1904 			for (int j = 0; j < key_count; j++) {
1905 				track.keys.write[j].data.resize(output_len);
1906 				for (int k = 0; k < output_len; k++)
1907 					track.keys.write[j].data.write[k] = output[l + j * stride + k]; //super weird but should work:
1908 			}
1909 
1910 			if (sampler.has("INTERPOLATION")) {
1911 
1912 				String interp_id = _uri_to_id(sampler["INTERPOLATION"]);
1913 				ERR_CONTINUE(!string_sources.has(interp_id));
1914 				Vector<String> &interps = string_sources[interp_id];
1915 				ERR_CONTINUE(interps.size() != key_count);
1916 
1917 				for (int j = 0; j < key_count; j++) {
1918 					if (interps[j] == "BEZIER")
1919 						track.keys.write[j].interp_type = AnimationTrack::INTERP_BEZIER;
1920 					else
1921 						track.keys.write[j].interp_type = AnimationTrack::INTERP_LINEAR;
1922 				}
1923 			}
1924 
1925 			if (sampler.has("IN_TANGENT") && sampler.has("OUT_TANGENT")) {
1926 				//bezier control points..
1927 				String intangent_id = _uri_to_id(sampler["IN_TANGENT"]);
1928 				ERR_CONTINUE(!float_sources.has(intangent_id));
1929 				Vector<float> &intangents = float_sources[intangent_id];
1930 
1931 				ERR_CONTINUE(intangents.size() != key_count * 2 * names.size());
1932 
1933 				String outangent_id = _uri_to_id(sampler["OUT_TANGENT"]);
1934 				ERR_CONTINUE(!float_sources.has(outangent_id));
1935 				Vector<float> &outangents = float_sources[outangent_id];
1936 				ERR_CONTINUE(outangents.size() != key_count * 2 * names.size());
1937 
1938 				for (int j = 0; j < key_count; j++) {
1939 					track.keys.write[j].in_tangent = Vector2(intangents[j * 2 * names.size() + 0 + l * 2], intangents[j * 2 * names.size() + 1 + l * 2]);
1940 					track.keys.write[j].out_tangent = Vector2(outangents[j * 2 * names.size() + 0 + l * 2], outangents[j * 2 * names.size() + 1 + l * 2]);
1941 				}
1942 			}
1943 
1944 			if (target.find("/") != -1) { //transform component
1945 				track.target = target.get_slicec('/', 0);
1946 				track.param = target.get_slicec('/', 1);
1947 				if (track.param.find(".") != -1)
1948 					track.component = track.param.get_slice(".", 1).to_upper();
1949 				track.param = track.param.get_slice(".", 0);
1950 				if (names.size() > 1 && track.component == "") {
1951 					//this is a guess because the collada spec is ambiguous here...
1952 					//i suppose if you have many names (outputs) you can't use a component and i should abide to that.
1953 					track.component = name;
1954 				}
1955 			} else {
1956 				track.target = target;
1957 			}
1958 
1959 			state.animation_tracks.push_back(track);
1960 
1961 			if (!state.referenced_tracks.has(target))
1962 				state.referenced_tracks[target] = Vector<int>();
1963 
1964 			state.referenced_tracks[target].push_back(state.animation_tracks.size() - 1);
1965 
1966 			if (id != "") {
1967 				if (!state.by_id_tracks.has(id))
1968 					state.by_id_tracks[id] = Vector<int>();
1969 
1970 				state.by_id_tracks[id].push_back(state.animation_tracks.size() - 1);
1971 			}
1972 
1973 			COLLADA_PRINT("loaded animation with " + itos(key_count) + " keys");
1974 		}
1975 	}
1976 }
1977 
_parse_animation_clip(XMLParser & parser)1978 void Collada::_parse_animation_clip(XMLParser &parser) {
1979 
1980 	if (!(state.import_flags & IMPORT_FLAG_ANIMATION)) {
1981 		if (!parser.is_empty())
1982 			parser.skip_section();
1983 
1984 		return;
1985 	}
1986 
1987 	AnimationClip clip;
1988 
1989 	if (parser.has_attribute("name"))
1990 		clip.name = parser.get_attribute_value("name");
1991 	else if (parser.has_attribute("id"))
1992 		clip.name = parser.get_attribute_value("id");
1993 	if (parser.has_attribute("start"))
1994 		clip.begin = parser.get_attribute_value("start").to_double();
1995 	if (parser.has_attribute("end"))
1996 		clip.end = parser.get_attribute_value("end").to_double();
1997 
1998 	while (parser.read() == OK) {
1999 
2000 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
2001 
2002 			String name = parser.get_node_name();
2003 			if (name == "instance_animation") {
2004 
2005 				String url = _uri_to_id(parser.get_attribute_value("url"));
2006 				clip.tracks.push_back(url);
2007 			}
2008 
2009 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "animation_clip")
2010 			break; //end of <asset>
2011 	}
2012 
2013 	state.animation_clips.push_back(clip);
2014 }
2015 
_parse_scene(XMLParser & parser)2016 void Collada::_parse_scene(XMLParser &parser) {
2017 
2018 	if (parser.is_empty()) {
2019 		return;
2020 	}
2021 
2022 	while (parser.read() == OK) {
2023 
2024 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
2025 
2026 			String name = parser.get_node_name();
2027 
2028 			if (name == "instance_visual_scene") {
2029 
2030 				state.root_visual_scene = _uri_to_id(parser.get_attribute_value("url"));
2031 			} else if (name == "instance_physics_scene") {
2032 
2033 				state.root_physics_scene = _uri_to_id(parser.get_attribute_value("url"));
2034 			}
2035 
2036 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "scene")
2037 			break; //end of <asset>
2038 	}
2039 }
2040 
_parse_library(XMLParser & parser)2041 void Collada::_parse_library(XMLParser &parser) {
2042 
2043 	if (parser.is_empty()) {
2044 		return;
2045 	}
2046 
2047 	while (parser.read() == OK) {
2048 
2049 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
2050 
2051 			String name = parser.get_node_name();
2052 			COLLADA_PRINT("library name is: " + name);
2053 			if (name == "image") {
2054 
2055 				_parse_image(parser);
2056 			} else if (name == "material") {
2057 
2058 				_parse_material(parser);
2059 			} else if (name == "effect") {
2060 
2061 				_parse_effect(parser);
2062 			} else if (name == "camera") {
2063 
2064 				_parse_camera(parser);
2065 			} else if (name == "light") {
2066 
2067 				_parse_light(parser);
2068 			} else if (name == "geometry") {
2069 
2070 				String id = parser.get_attribute_value("id");
2071 				String name2 = parser.get_attribute_value_safe("name");
2072 				while (parser.read() == OK) {
2073 
2074 					if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
2075 
2076 						if (parser.get_node_name() == "mesh") {
2077 							state.mesh_name_map[id] = (name2 != "") ? name2 : id;
2078 							_parse_mesh_geometry(parser, id, name2);
2079 						} else if (parser.get_node_name() == "spline") {
2080 							state.mesh_name_map[id] = (name2 != "") ? name2 : id;
2081 							_parse_curve_geometry(parser, id, name2);
2082 						} else if (!parser.is_empty())
2083 							parser.skip_section();
2084 					} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name() == "geometry")
2085 						break;
2086 				}
2087 
2088 			} else if (name == "controller") {
2089 
2090 				_parse_controller(parser);
2091 			} else if (name == "animation") {
2092 
2093 				_parse_animation(parser);
2094 			} else if (name == "animation_clip") {
2095 
2096 				_parse_animation_clip(parser);
2097 			} else if (name == "visual_scene") {
2098 
2099 				COLLADA_PRINT("visual scene");
2100 				_parse_visual_scene(parser);
2101 			} else if (!parser.is_empty())
2102 				parser.skip_section();
2103 
2104 		} else if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END && parser.get_node_name().begins_with("library_"))
2105 			break; //end of <asset>
2106 	}
2107 }
2108 
_joint_set_owner(Collada::Node * p_node,NodeSkeleton * p_owner)2109 void Collada::_joint_set_owner(Collada::Node *p_node, NodeSkeleton *p_owner) {
2110 
2111 	if (p_node->type == Node::TYPE_JOINT) {
2112 
2113 		NodeJoint *nj = static_cast<NodeJoint *>(p_node);
2114 		nj->owner = p_owner;
2115 
2116 		for (int i = 0; i < nj->children.size(); i++) {
2117 
2118 			_joint_set_owner(nj->children.write[i], p_owner);
2119 		}
2120 	}
2121 }
2122 
_create_skeletons(Collada::Node ** p_node,NodeSkeleton * p_skeleton)2123 void Collada::_create_skeletons(Collada::Node **p_node, NodeSkeleton *p_skeleton) {
2124 
2125 	Node *node = *p_node;
2126 
2127 	if (node->type == Node::TYPE_JOINT) {
2128 
2129 		if (!p_skeleton) {
2130 
2131 			// ohohohoohoo it's a joint node, time to work!
2132 			NodeSkeleton *sk = memnew(NodeSkeleton);
2133 			*p_node = sk;
2134 			sk->children.push_back(node);
2135 			sk->parent = node->parent;
2136 			node->parent = sk;
2137 			p_skeleton = sk;
2138 		}
2139 
2140 		NodeJoint *nj = static_cast<NodeJoint *>(node);
2141 		nj->owner = p_skeleton;
2142 	} else {
2143 		p_skeleton = NULL;
2144 	}
2145 
2146 	for (int i = 0; i < node->children.size(); i++) {
2147 		_create_skeletons(&node->children.write[i], p_skeleton);
2148 	}
2149 }
2150 
_remove_node(Node * p_parent,Node * p_node)2151 bool Collada::_remove_node(Node *p_parent, Node *p_node) {
2152 
2153 	for (int i = 0; i < p_parent->children.size(); i++) {
2154 
2155 		if (p_parent->children[i] == p_node) {
2156 			p_parent->children.remove(i);
2157 			return true;
2158 		}
2159 		if (_remove_node(p_parent->children[i], p_node))
2160 			return true;
2161 	}
2162 
2163 	return false;
2164 }
2165 
_remove_node(VisualScene * p_vscene,Node * p_node)2166 void Collada::_remove_node(VisualScene *p_vscene, Node *p_node) {
2167 
2168 	for (int i = 0; i < p_vscene->root_nodes.size(); i++) {
2169 		if (p_vscene->root_nodes[i] == p_node) {
2170 
2171 			p_vscene->root_nodes.remove(i);
2172 			return;
2173 		}
2174 		if (_remove_node(p_vscene->root_nodes[i], p_node))
2175 			return;
2176 	}
2177 
2178 	ERR_PRINT("ERROR: Not found node to remove?");
2179 }
2180 
_merge_skeletons(VisualScene * p_vscene,Node * p_node)2181 void Collada::_merge_skeletons(VisualScene *p_vscene, Node *p_node) {
2182 
2183 	if (p_node->type == Node::TYPE_GEOMETRY) {
2184 
2185 		NodeGeometry *gnode = static_cast<NodeGeometry *>(p_node);
2186 		if (gnode->controller) {
2187 
2188 			// recount skeletons used
2189 			Set<NodeSkeleton *> skeletons;
2190 
2191 			for (int i = 0; i < gnode->skeletons.size(); i++) {
2192 
2193 				String nodeid = gnode->skeletons[i];
2194 
2195 				ERR_CONTINUE(!state.scene_map.has(nodeid)); //weird, it should have it...
2196 
2197 				NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
2198 				ERR_CONTINUE(!nj); //broken collada
2199 				ERR_CONTINUE(!nj->owner); //weird, node should have a skeleton owner
2200 
2201 				skeletons.insert(nj->owner);
2202 			}
2203 
2204 			if (skeletons.size() > 1) {
2205 
2206 				//do the merger!!
2207 				Set<NodeSkeleton *>::Element *E = skeletons.front();
2208 				NodeSkeleton *base = E->get();
2209 
2210 				for (E = E->next(); E; E = E->next()) {
2211 
2212 					NodeSkeleton *merged = E->get();
2213 					_remove_node(p_vscene, merged);
2214 					for (int i = 0; i < merged->children.size(); i++) {
2215 
2216 						_joint_set_owner(merged->children[i], base);
2217 						base->children.push_back(merged->children[i]);
2218 						merged->children[i]->parent = base;
2219 					}
2220 
2221 					merged->children.clear(); //take children from it
2222 					memdelete(merged);
2223 				}
2224 			}
2225 		}
2226 	}
2227 
2228 	for (int i = 0; i < p_node->children.size(); i++) {
2229 		_merge_skeletons(p_vscene, p_node->children[i]);
2230 	}
2231 }
2232 
_merge_skeletons2(VisualScene * p_vscene)2233 void Collada::_merge_skeletons2(VisualScene *p_vscene) {
2234 
2235 	for (Map<String, SkinControllerData>::Element *E = state.skin_controller_data_map.front(); E; E = E->next()) {
2236 
2237 		SkinControllerData &cd = E->get();
2238 
2239 		NodeSkeleton *skeleton = NULL;
2240 
2241 		for (Map<String, Transform>::Element *F = cd.bone_rest_map.front(); F; F = F->next()) {
2242 
2243 			String name;
2244 
2245 			if (!state.sid_to_node_map.has(F->key())) {
2246 				continue;
2247 			}
2248 
2249 			name = state.sid_to_node_map[F->key()];
2250 
2251 			ERR_CONTINUE(!state.scene_map.has(name));
2252 
2253 			Node *node = state.scene_map[name];
2254 			ERR_CONTINUE(node->type != Node::TYPE_JOINT);
2255 
2256 			NodeSkeleton *sk = NULL;
2257 
2258 			while (node && !sk) {
2259 
2260 				if (node->type == Node::TYPE_SKELETON) {
2261 					sk = static_cast<NodeSkeleton *>(node);
2262 				}
2263 				node = node->parent;
2264 			}
2265 
2266 			ERR_CONTINUE(!sk);
2267 
2268 			if (!skeleton) {
2269 				skeleton = sk;
2270 				continue;
2271 			}
2272 
2273 			if (skeleton != sk) {
2274 				//whoa.. wtf, merge.
2275 				_remove_node(p_vscene, sk);
2276 				for (int i = 0; i < sk->children.size(); i++) {
2277 
2278 					_joint_set_owner(sk->children[i], skeleton);
2279 					skeleton->children.push_back(sk->children[i]);
2280 					sk->children[i]->parent = skeleton;
2281 				}
2282 
2283 				sk->children.clear(); //take children from it
2284 				memdelete(sk);
2285 			}
2286 		}
2287 	}
2288 }
2289 
_optimize_skeletons(VisualScene * p_vscene,Node * p_node)2290 bool Collada::_optimize_skeletons(VisualScene *p_vscene, Node *p_node) {
2291 
2292 	Node *node = p_node;
2293 
2294 	if (node->type == Node::TYPE_SKELETON && node->parent && node->parent->type == Node::TYPE_NODE && node->parent->children.size() == 1) {
2295 		//replace parent by this...
2296 		Node *parent = node->parent;
2297 
2298 		//i wonder if this is alright.. i think it is since created skeleton (first joint) is already animated by bone..
2299 		node->id = parent->id;
2300 		node->name = parent->name;
2301 		node->xform_list = parent->xform_list;
2302 		node->default_transform = parent->default_transform;
2303 
2304 		state.scene_map[node->id] = node;
2305 		node->parent = parent->parent;
2306 
2307 		if (parent->parent) {
2308 			Node *gp = parent->parent;
2309 			bool found = false;
2310 			for (int i = 0; i < gp->children.size(); i++) {
2311 
2312 				if (gp->children[i] == parent) {
2313 					gp->children.write[i] = node;
2314 					found = true;
2315 					break;
2316 				}
2317 			}
2318 			if (!found) {
2319 				ERR_PRINT("BUG");
2320 			}
2321 		} else {
2322 
2323 			bool found = false;
2324 
2325 			for (int i = 0; i < p_vscene->root_nodes.size(); i++) {
2326 
2327 				if (p_vscene->root_nodes[i] == parent) {
2328 
2329 					p_vscene->root_nodes.write[i] = node;
2330 					found = true;
2331 					break;
2332 				}
2333 			}
2334 			if (!found) {
2335 				ERR_PRINT("BUG");
2336 			}
2337 		}
2338 
2339 		parent->children.clear();
2340 		memdelete(parent);
2341 		return true;
2342 	}
2343 
2344 	for (int i = 0; i < node->children.size(); i++) {
2345 
2346 		if (_optimize_skeletons(p_vscene, node->children[i]))
2347 			return false; //stop processing, go up
2348 	}
2349 
2350 	return false;
2351 }
2352 
_move_geometry_to_skeletons(VisualScene * p_vscene,Node * p_node,List<Node * > * p_mgeom)2353 bool Collada::_move_geometry_to_skeletons(VisualScene *p_vscene, Node *p_node, List<Node *> *p_mgeom) {
2354 
2355 	// Bind Shape Matrix scales the bones and makes them gigantic, so the matrix then shrinks the model?
2356 	// Solution: apply the Bind Shape Matrix to the VERTICES, and if the object comes scaled, it seems to be left alone!
2357 
2358 	if (p_node->type == Node::TYPE_GEOMETRY) {
2359 
2360 		NodeGeometry *ng = static_cast<NodeGeometry *>(p_node);
2361 		if (ng->ignore_anim)
2362 			return false; //already made child of skeleton and processeg
2363 
2364 		if (ng->controller && ng->skeletons.size()) {
2365 
2366 			String nodeid = ng->skeletons[0];
2367 
2368 			ERR_FAIL_COND_V(!state.scene_map.has(nodeid), false); //weird, it should have it...
2369 			NodeJoint *nj = SAFE_CAST<NodeJoint *>(state.scene_map[nodeid]);
2370 			ERR_FAIL_COND_V(!nj, false);
2371 			ERR_FAIL_COND_V(!nj->owner, false); //weird, node should have a skeleton owner
2372 
2373 			NodeSkeleton *sk = nj->owner;
2374 
2375 			Node *p = sk->parent;
2376 			bool node_is_parent_of_skeleton = false;
2377 
2378 			while (p) {
2379 				if (p == p_node) {
2380 					node_is_parent_of_skeleton = true;
2381 					break;
2382 				}
2383 				p = p->parent; // try again
2384 			}
2385 
2386 			ERR_FAIL_COND_V(node_is_parent_of_skeleton, false);
2387 
2388 			//this should be correct
2389 			ERR_FAIL_COND_V(!state.skin_controller_data_map.has(ng->source), false);
2390 			SkinControllerData &skin = state.skin_controller_data_map[ng->source];
2391 			Transform skel_inv = sk->get_global_transform().affine_inverse();
2392 			p_node->default_transform = skel_inv * (skin.bind_shape /* p_node->get_global_transform()*/); // i honestly have no idea what to do with a previous model xform.. most exporters ignore it
2393 
2394 			//make rests relative to the skeleton (they seem to be always relative to world)
2395 			for (Map<String, Transform>::Element *E = skin.bone_rest_map.front(); E; E = E->next()) {
2396 
2397 				E->get() = skel_inv * E->get(); //make the bone rest local to the skeleton
2398 				state.bone_rest_map[E->key()] = E->get(); // make it remember where the bone is globally, now that it's relative
2399 			}
2400 
2401 			//but most exporters seem to work only if i do this..
2402 			//p_node->default_transform = p_node->get_global_transform();
2403 
2404 			//p_node->default_transform=Transform(); //this seems to be correct, because bind shape makes the object local to the skeleton
2405 			p_node->ignore_anim = true; // collada may animate this later, if it does, then this is not supported (redo your original asset and don't animate the base mesh)
2406 			p_node->parent = sk;
2407 			//sk->children.push_back(0,p_node); //avoid INFINITE loop
2408 			p_mgeom->push_back(p_node);
2409 			return true;
2410 		}
2411 	}
2412 
2413 	for (int i = 0; i < p_node->children.size(); i++) {
2414 
2415 		if (_move_geometry_to_skeletons(p_vscene, p_node->children[i], p_mgeom)) {
2416 			p_node->children.remove(i);
2417 			i--;
2418 		}
2419 	}
2420 
2421 	return false;
2422 }
2423 
_find_morph_nodes(VisualScene * p_vscene,Node * p_node)2424 void Collada::_find_morph_nodes(VisualScene *p_vscene, Node *p_node) {
2425 
2426 	if (p_node->type == Node::TYPE_GEOMETRY) {
2427 
2428 		NodeGeometry *nj = static_cast<NodeGeometry *>(p_node);
2429 
2430 		if (nj->controller) {
2431 
2432 			String base = nj->source;
2433 
2434 			while (base != "" && !state.mesh_data_map.has(base)) {
2435 
2436 				if (state.skin_controller_data_map.has(base)) {
2437 
2438 					SkinControllerData &sk = state.skin_controller_data_map[base];
2439 					base = sk.base;
2440 				} else if (state.morph_controller_data_map.has(base)) {
2441 
2442 					state.morph_ownership_map[base] = nj->id;
2443 					break;
2444 				} else {
2445 					ERR_FAIL_MSG("Invalid scene.");
2446 				}
2447 			}
2448 		}
2449 	}
2450 
2451 	for (int i = 0; i < p_node->children.size(); i++) {
2452 
2453 		_find_morph_nodes(p_vscene, p_node->children[i]);
2454 	}
2455 }
2456 
_optimize()2457 void Collada::_optimize() {
2458 
2459 	for (Map<String, VisualScene>::Element *E = state.visual_scene_map.front(); E; E = E->next()) {
2460 
2461 		VisualScene &vs = E->get();
2462 		for (int i = 0; i < vs.root_nodes.size(); i++) {
2463 			_create_skeletons(&vs.root_nodes.write[i]);
2464 		}
2465 
2466 		for (int i = 0; i < vs.root_nodes.size(); i++) {
2467 			_merge_skeletons(&vs, vs.root_nodes[i]);
2468 		}
2469 
2470 		_merge_skeletons2(&vs);
2471 
2472 		for (int i = 0; i < vs.root_nodes.size(); i++) {
2473 			_optimize_skeletons(&vs, vs.root_nodes[i]);
2474 		}
2475 
2476 		for (int i = 0; i < vs.root_nodes.size(); i++) {
2477 
2478 			List<Node *> mgeom;
2479 			if (_move_geometry_to_skeletons(&vs, vs.root_nodes[i], &mgeom)) {
2480 				vs.root_nodes.remove(i);
2481 				i--;
2482 			}
2483 
2484 			while (!mgeom.empty()) {
2485 
2486 				Node *n = mgeom.front()->get();
2487 				n->parent->children.push_back(n);
2488 				mgeom.pop_front();
2489 			}
2490 		}
2491 
2492 		for (int i = 0; i < vs.root_nodes.size(); i++) {
2493 			_find_morph_nodes(&vs, vs.root_nodes[i]);
2494 		}
2495 	}
2496 }
2497 
get_uv_channel(String p_name)2498 int Collada::get_uv_channel(String p_name) {
2499 
2500 	if (!channel_map.has(p_name)) {
2501 
2502 		ERR_FAIL_COND_V(channel_map.size() == 2, 0);
2503 
2504 		channel_map[p_name] = channel_map.size();
2505 	}
2506 
2507 	return channel_map[p_name];
2508 }
2509 
load(const String & p_path,int p_flags)2510 Error Collada::load(const String &p_path, int p_flags) {
2511 
2512 	Ref<XMLParser> parserr = memnew(XMLParser);
2513 	XMLParser &parser = *parserr.ptr();
2514 	Error err = parser.open(p_path);
2515 	ERR_FAIL_COND_V_MSG(err, err, "Cannot open Collada file '" + p_path + "'.");
2516 
2517 	state.local_path = ProjectSettings::get_singleton()->localize_path(p_path);
2518 	state.import_flags = p_flags;
2519 	/* Skip headers */
2520 	while ((err = parser.read()) == OK) {
2521 
2522 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT) {
2523 
2524 			if (parser.get_node_name() == "COLLADA") {
2525 				break;
2526 			} else if (!parser.is_empty())
2527 				parser.skip_section(); // unknown section, likely headers
2528 		}
2529 	}
2530 
2531 	ERR_FAIL_COND_V_MSG(err != OK, ERR_FILE_CORRUPT, "Corrupted Collada file '" + p_path + "'.");
2532 
2533 	/* Start loading Collada */
2534 
2535 	{
2536 		//version
2537 		String version = parser.get_attribute_value("version");
2538 		state.version.major = version.get_slice(".", 0).to_int();
2539 		state.version.minor = version.get_slice(".", 1).to_int();
2540 		state.version.rev = version.get_slice(".", 2).to_int();
2541 		COLLADA_PRINT("Collada VERSION: " + version);
2542 	}
2543 
2544 	while ((err = parser.read()) == OK) {
2545 
2546 		/* Read all the main sections.. */
2547 
2548 		if (parser.get_node_type() != XMLParser::NODE_ELEMENT)
2549 			continue; //no idea what this may be, but skipping anyway
2550 
2551 		String section = parser.get_node_name();
2552 
2553 		COLLADA_PRINT("section: " + section);
2554 
2555 		if (section == "asset") {
2556 			_parse_asset(parser);
2557 
2558 		} else if (section.begins_with("library_")) {
2559 
2560 			_parse_library(parser);
2561 		} else if (section == "scene") {
2562 
2563 			_parse_scene(parser);
2564 		} else if (!parser.is_empty()) {
2565 			parser.skip_section(); // unknown section, likely headers
2566 		}
2567 	}
2568 
2569 	_optimize();
2570 	return OK;
2571 }
2572 
Collada()2573 Collada::Collada() {
2574 }
2575