fixed collada import for objects which have NO children
[blender.git] / source / blender / collada / DocumentImporter.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/collada/DocumentImporter.cpp
24  *  \ingroup collada
25  */
26
27 // TODO:
28 // * name imported objects
29 // * import object rotation as euler
30
31 #include <string>
32 #include <map>
33 #include <algorithm> // sort()
34
35 #include "COLLADAFWRoot.h"
36 #include "COLLADAFWStableHeaders.h"
37 #include "COLLADAFWColorOrTexture.h"
38 #include "COLLADAFWIndexList.h"
39 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
40 #include "COLLADAFWPolygons.h"
41 #include "COLLADAFWSampler.h"
42 #include "COLLADAFWTypes.h"
43 #include "COLLADAFWVisualScene.h"
44 #include "COLLADAFWArrayPrimitiveType.h"
45 #include "COLLADAFWLibraryNodes.h"
46 #include "COLLADAFWCamera.h"
47 #include "COLLADAFWLight.h"
48
49 #include "COLLADASaxFWLLoader.h"
50 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
51
52 extern "C" {
53 #include "BLI_listbase.h"
54 #include "BLI_math.h"
55 #include "BLI_string.h"
56 #include "BLI_utildefines.h"
57
58 #include "BKE_camera.h"
59 #include "BKE_main.h"
60 #include "BKE_lamp.h"
61 #include "BKE_library.h"
62 #include "BKE_texture.h"
63 #include "BKE_fcurve.h"
64 #include "BKE_depsgraph.h"
65 #include "BKE_scene.h"
66 #include "BKE_global.h"
67 #include "BKE_material.h"
68 #include "BKE_image.h"
69
70 #include "BLI_path_util.h"
71
72 #include "DNA_camera_types.h"
73 #include "DNA_lamp_types.h"
74
75 #include "RNA_access.h"
76
77 #include "MEM_guardedalloc.h"
78
79 }
80
81 #include "ExtraHandler.h"
82 #include "ErrorHandler.h"
83 #include "DocumentImporter.h"
84 #include "TransformReader.h"
85
86 #include "collada_internal.h"
87 #include "collada_utils.h"
88
89
90 /*
91  * COLLADA Importer limitations:
92  * - no multiple scene import, all objects are added to active scene
93  */
94
95 // #define COLLADA_DEBUG
96 // creates empties for each imported bone on layer 2, for debugging
97 // #define ARMATURE_TEST
98
99 DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
100         mImportStage(General),
101         mFilename(filename),
102         mContext(C),
103         armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
104         mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
105         anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
106 {
107 }
108
109 DocumentImporter::~DocumentImporter()
110 {
111         TagsMap::iterator etit;
112         etit = uid_tags_map.begin();
113         while (etit != uid_tags_map.end()) {
114                 delete etit->second;
115                 etit++;
116         }
117 }
118
119 bool DocumentImporter::import()
120 {
121         ErrorHandler errorHandler;
122         COLLADASaxFWL::Loader loader(&errorHandler);
123         COLLADAFW::Root root(&loader, this);
124         ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
125         
126         loader.registerExtraDataCallbackHandler(ehandler);
127
128         // deselect all to select new objects
129         BKE_scene_base_deselect_all(CTX_data_scene(mContext));
130
131         if (!root.loadDocument(mFilename)) {
132                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
133                 return false;
134         }
135         
136         if (errorHandler.hasError())
137                 return false;
138         
139         /** TODO set up scene graph and such here */
140         
141         mImportStage = Controller;
142         
143         COLLADASaxFWL::Loader loader2;
144         COLLADAFW::Root root2(&loader2, this);
145         
146         if (!root2.loadDocument(mFilename)) {
147                 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
148                 return false;
149         }
150         
151         
152         delete ehandler;
153
154         mesh_importer.bmeshConversion();
155
156         return true;
157 }
158
159 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
160 {
161         // TODO: if possible show error info
162         //
163         // Should we get rid of invisible Meshes that were created so far
164         // or maybe create objects at coordinate space origin?
165         //
166         // The latter sounds better.
167 }
168
169 void DocumentImporter::start()
170 {
171 }
172
173 void DocumentImporter::finish()
174 {
175         if (mImportStage != General)
176                 return;
177                 
178         /** TODO Break up and put into 2-pass parsing of DAE */
179         std::vector<const COLLADAFW::VisualScene *>::iterator it;
180         for (it = vscenes.begin(); it != vscenes.end(); it++) {
181                 PointerRNA sceneptr, unit_settings;
182                 PropertyRNA *system, *scale;
183                 // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
184                 Scene *sce = CTX_data_scene(mContext);
185                 
186                 // for scene unit settings: system, scale_length
187                 RNA_id_pointer_create(&sce->id, &sceneptr);
188                 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
189                 system = RNA_struct_find_property(&unit_settings, "system");
190                 scale = RNA_struct_find_property(&unit_settings, "scale_length");
191                 
192                 switch (unit_converter.isMetricSystem()) {
193                         case UnitConverter::Metric:
194                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
195                                 break;
196                         case UnitConverter::Imperial:
197                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
198                                 break;
199                         default:
200                                 RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
201                                 break;
202                 }
203                 RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
204                 
205                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
206
207                 for (unsigned int i = 0; i < roots.getCount(); i++) {
208                         write_node(roots[i], NULL, sce, NULL, false);
209                 }
210         }
211
212
213         mesh_importer.optimize_material_assignements();
214
215         armature_importer.set_tags_map(this->uid_tags_map);
216         armature_importer.make_armatures(mContext);
217         armature_importer.make_shape_keys();
218
219 #if 0
220         armature_importer.fix_animation();
221 #endif
222
223         for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
224                 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
225
226                 for (unsigned int i = 0; i < roots.getCount(); i++)
227                         translate_anim_recursive(roots[i], NULL, NULL);
228         }
229
230         if (libnode_ob.size()) {
231                 Scene *sce = CTX_data_scene(mContext);
232
233                 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
234                 // free all library_nodes
235                 std::vector<Object *>::iterator it;
236                 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
237                         Object *ob = *it;
238
239                         Base *base = BKE_scene_base_find(sce, ob);
240                         if (base) {
241                                 BLI_remlink(&sce->base, base);
242                                 BKE_libblock_free_us(&G.main->object, base->object);
243                                 if (sce->basact == base)
244                                         sce->basact = NULL;
245                                 MEM_freeN(base);
246                         }
247                 }
248                 libnode_ob.clear();
249
250                 DAG_scene_sort(CTX_data_main(mContext), sce);
251                 DAG_ids_flush_update(CTX_data_main(mContext), 0);
252         }
253 }
254
255
256 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
257 {
258
259         // The split in #29246, rootmap must point at actual root when
260         // calculating bones in apply_curves_as_matrix. - actual root is the root node.
261         // This has to do with inverse bind poses being world space
262         // (the sources for skinned bones' restposes) and the way
263         // non-skinning nodes have their "restpose" recursively calculated.
264         // XXX TODO: design issue, how to support unrelated joints taking
265         // part in skinning.
266         if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
267                 // par is root if there's no corresp. key in root_map
268                 if (root_map.find(par->getUniqueId()) == root_map.end())
269                         root_map[node->getUniqueId()] = node;
270                 else
271                         root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
272         }
273
274 #if 0
275         COLLADAFW::Transformation::TransformationType types[] = {
276                 COLLADAFW::Transformation::ROTATE,
277                 COLLADAFW::Transformation::SCALE,
278                 COLLADAFW::Transformation::TRANSLATE,
279                 COLLADAFW::Transformation::MATRIX
280         };
281
282         Object *ob;
283 #endif
284         unsigned int i;
285
286         //for (i = 0; i < 4; i++)
287         //    ob =
288         anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
289
290         COLLADAFW::NodePointerArray &children = node->getChildNodes();
291         for (i = 0; i < children.getCount(); i++) {
292                 translate_anim_recursive(children[i], node, NULL);
293         }
294 }
295
296 /** When this method is called, the writer must write the global document asset.
297  * \return The writer should return true, if writing succeeded, false otherwise.*/
298 bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset)
299 {
300         unit_converter.read_asset(asset);
301
302         return true;
303 }
304
305 /** When this method is called, the writer must write the scene.
306  * \return The writer should return true, if writing succeeded, false otherwise.*/
307 bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene)
308 {
309         // XXX could store the scene id, but do nothing for now
310         return true;
311 }
312 Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
313 {
314         const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
315         if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {
316                 // fprintf(stderr, "Couldn't find camera by UID.\n");
317                 return NULL;
318         }
319
320         Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
321         Camera *cam = uid_camera_map[cam_uid];
322         Camera *old_cam = (Camera *)ob->data;
323         ob->data = cam;
324         old_cam->id.us--;
325         if (old_cam->id.us == 0)
326                 BKE_libblock_free(&G.main->camera, old_cam);
327         return ob;
328 }
329
330 Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
331 {
332         const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
333         if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
334                 fprintf(stderr, "Couldn't find lamp by UID.\n");
335                 return NULL;
336         }
337
338         Object *ob = bc_add_object(sce, OB_LAMP, NULL);
339         Lamp *la = uid_lamp_map[lamp_uid];
340         Lamp *old_lamp = (Lamp *)ob->data;
341         ob->data = la;
342         old_lamp->id.us--;
343         if (old_lamp->id.us == 0)
344                 BKE_libblock_free(&G.main->lamp, old_lamp);
345         return ob;
346 }
347
348 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
349 {
350         fprintf(stderr, "create <instance_node> under node id=%s from node id=%s\n", instance_node ? instance_node->getOriginalId().c_str() : NULL, source_node ? source_node->getOriginalId().c_str() : NULL);
351
352         Object *obn = BKE_object_copy(source_ob);
353         obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
354         BKE_scene_base_add(sce, obn);
355
356         if (instance_node) {
357                 anim_importer.read_node_transform(instance_node, obn);
358                 // if we also have a source_node (always ;), take its
359                 // transformation matrix and apply it to the newly instantiated
360                 // object to account for node hierarchy transforms in
361                 // .dae
362                 if (source_node) {
363                         COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
364                         COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
365                         float mat[4][4];
366                         for (int i = 0; i < 4; i++) {
367                                 for (int j = 0; j < 4; j++) {
368                                         mat[i][j] = bmat4[i][j];
369                                 }
370                         }
371                         // calc new matrix and apply
372                         mult_m4_m4m4(obn->obmat, obn->obmat, mat);
373                         BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
374                 }
375         }
376         else {
377                 anim_importer.read_node_transform(source_node, obn);
378         }
379
380         /*DAG_scene_sort(CTX_data_main(mContext), sce);
381         DAG_ids_flush_update(CTX_data_main(mContext), 0);*/
382
383         COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
384         if (children.getCount()) {
385                 for (unsigned int i = 0; i < children.getCount(); i++) {
386                         COLLADAFW::Node *child_node = children[i];
387                         const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
388                         if (object_map.find(child_id) == object_map.end())
389                                 continue;
390                         COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
391                         Object *new_child = NULL;
392                         if (inodes.getCount()) { // \todo loop through instance nodes
393                                 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
394                                 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
395                                 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
396                         }
397                         else {
398                                 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
399                         }
400                         bc_set_parent(new_child, obn, mContext, true);
401
402                         if (is_library_node)
403                                 libnode_ob.push_back(new_child);
404                 }
405         }
406
407         return obn;
408 }
409
410 // to create constraints off node <extra> tags. Assumes only constraint data in
411 // current <extra> with blender profile.
412 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob){
413         if ( et && et->isProfile("blender")){
414                 std::string name;
415                 short* type = 0;
416                 et->setData("type", type);
417                 BKE_add_ob_constraint(ob, "Test_con", *type);
418                 
419         }
420 }
421
422 void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
423 {
424         Object *ob = NULL;
425         bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
426         bool read_transform = true;
427
428         std::vector<Object *> *objects_done = new std::vector<Object *>();
429
430         if (is_joint) {
431                 armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
432         }
433         else {
434                 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
435                 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
436                 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
437                 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
438                 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
439                 size_t geom_done = 0;
440                 size_t camera_done = 0;
441                 size_t lamp_done = 0;
442                 size_t controller_done = 0;
443                 size_t inst_done = 0;
444
445                 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
446                 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
447                 // <instance_geometry>
448                 while (geom_done < geom.getCount()) {
449                         ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
450                                                               material_texture_mapping_map);
451                         if (ob == NULL) {
452                                 std::string id   = node->getOriginalId();
453                                 std::string name = node->getName();
454                                 fprintf(stderr,
455                                                 "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
456                                                 id.c_str(),
457                                                 name.c_str());
458                         }
459                         else {
460                                 objects_done->push_back(ob);
461                         }
462                         ++geom_done;
463                 }
464                 while (camera_done < camera.getCount()) {
465                         ob = create_camera_object(camera[camera_done], sce);
466                         if (ob == NULL) {
467                                 std::string id   = node->getOriginalId();
468                                 std::string name = node->getName();
469                                 fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
470                         }
471                         else
472                                 objects_done->push_back(ob);
473                         ++camera_done;
474                 }
475                 while (lamp_done < lamp.getCount()) {
476                         ob = create_lamp_object(lamp[lamp_done], sce);
477                         objects_done->push_back(ob);
478                         ++lamp_done;
479                 }
480                 while (controller_done < controller.getCount()) {
481                         COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
482                         ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
483                         objects_done->push_back(ob);
484                         ++controller_done;
485                 }
486                 // XXX instance_node is not supported yet
487                 while (inst_done < inst_node.getCount()) {
488                         const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
489                         if (object_map.find(node_id) == object_map.end()) {
490                                 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
491                                 ob = NULL;
492                         }
493                         else {
494                                 std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id);
495                                 for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) {
496                                         Object *source_ob = (Object *)it2->second;
497                                         COLLADAFW::Node *source_node = node_map[node_id];
498                                         ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
499                                 }
500                         }
501                         if (ob != NULL) objects_done->push_back(ob);
502                         ++inst_done;
503
504                         read_transform = false;
505                 }
506
507                 // if node is empty - create empty object
508                 // XXX empty node may not mean it is empty object, not sure about this
509                 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
510                         //Check if Object is armature, by checking if immediate child is a JOINT node.
511                         if(is_armature(node))
512                                 ob = bc_add_object(sce, OB_ARMATURE, NULL);
513                         else ob = bc_add_object(sce, OB_EMPTY, NULL);
514
515                         objects_done->push_back(ob);
516                 }
517                 
518                 // XXX: if there're multiple instances, only one is stored
519
520                 if (!ob) return;
521                 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
522                         ob = *it;
523                         std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
524                         rename_id(&ob->id, (char *)nodename.c_str());
525                         object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob));
526                         node_map[node->getUniqueId()] = node;
527
528                         if (is_library_node)
529                                 libnode_ob.push_back(ob);
530                 }
531
532                 //create_constraints(et,ob);
533
534         }
535
536         for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
537                 ob = *it;
538
539                 if (read_transform)
540                         anim_importer.read_node_transform(node, ob);  // overwrites location set earlier
541
542                 if (!is_joint) {
543                         // if par was given make this object child of the previous
544                         if (par && ob)
545                                 bc_set_parent(ob, par, mContext);
546                 }
547         }
548         // if node has child nodes write them
549         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
550         if (objects_done->size() > 0) {
551                 ob = *objects_done->begin();
552                 for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
553                         write_node(child_nodes[i], node, sce, ob, is_library_node);
554                 }
555         }
556 }
557
558 /** When this method is called, the writer must write the entire visual scene.
559  * \return The writer should return true, if writing succeeded, false otherwise.*/
560 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
561 {
562         if (mImportStage != General)
563                 return true;
564                 
565         // this method called on post process after writeGeometry, writeMaterial, etc.
566
567         // for each <node> in <visual_scene>:
568         // create an Object
569         // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
570
571         // update: since we cannot link a Mesh with Object in
572         // writeGeometry because <geometry> does not reference <node>,
573         // we link Objects with Meshes here
574
575         vscenes.push_back(visualScene);
576         
577         return true;
578 }
579
580 /** When this method is called, the writer must handle all nodes contained in the 
581  * library nodes.
582  * \return The writer should return true, if writing succeeded, false otherwise.*/
583 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
584 {
585         if (mImportStage != General)
586                 return true;
587                 
588         Scene *sce = CTX_data_scene(mContext);
589
590         const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
591
592         for (unsigned int i = 0; i < nodes.getCount(); i++) {
593                 write_node(nodes[i], NULL, sce, NULL, true);
594         }
595
596         return true;
597 }
598
599 /** When this method is called, the writer must write the geometry.
600  * \return The writer should return true, if writing succeeded, false otherwise.*/
601 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
602 {
603         if (mImportStage != General)
604                 return true;
605                 
606         return mesh_importer.write_geometry(geom);
607 }
608
609 /** When this method is called, the writer must write the material.
610  * \return The writer should return true, if writing succeeded, false otherwise.*/
611 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
612 {
613         if (mImportStage != General)
614                 return true;
615                 
616         const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
617         Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
618         
619         this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
620         this->uid_material_map[cmat->getUniqueId()] = ma;
621         
622         return true;
623 }
624
625 // create mtex, create texture, set texture image
626 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
627                                        int i, TexIndexTextureArrayMap &texindex_texarray_map)
628 {
629         COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
630         COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
631                 
632         const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
633         
634         if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
635                 fprintf(stderr, "Couldn't find an image by UID.\n");
636                 return NULL;
637         }
638         
639         ma->mtex[i] = add_mtex();
640         ma->mtex[i]->texco = TEXCO_UV;
641         ma->mtex[i]->tex = add_texture(G.main, "Texture");
642         ma->mtex[i]->tex->type = TEX_IMAGE;
643         ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
644         
645         texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
646         
647         return ma->mtex[i];
648 }
649
650 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
651 {
652         COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
653         
654         // blinn
655         if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
656                 ma->spec_shader = MA_SPEC_BLINN;
657                 ma->spec = ef->getShininess().getFloatValue();
658         }
659         // phong
660         else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
661                 ma->spec_shader = MA_SPEC_PHONG;
662                 ma->har = ef->getShininess().getFloatValue();
663         }
664         // lambert
665         else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
666                 ma->diff_shader = MA_DIFF_LAMBERT;
667         }
668         // default - lambert
669         else {
670                 ma->diff_shader = MA_DIFF_LAMBERT;
671                 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
672         }
673         // reflectivity
674         ma->ray_mirror = ef->getReflectivity().getFloatValue();
675         // index of refraction
676         ma->ang = ef->getIndexOfRefraction().getFloatValue();
677         
678         int i = 0;
679         COLLADAFW::Color col;
680         MTex *mtex = NULL;
681         TexIndexTextureArrayMap texindex_texarray_map;
682         
683         // DIFFUSE
684         // color
685         if (ef->getDiffuse().isColor()) {
686                 col = ef->getDiffuse().getColor();
687                 ma->r = col.getRed();
688                 ma->g = col.getGreen();
689                 ma->b = col.getBlue();
690         }
691         // texture
692         else if (ef->getDiffuse().isTexture()) {
693                 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); 
694                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
695                 if (mtex != NULL) {
696                         mtex->mapto = MAP_COL;
697                         ma->texact = (int)i;
698                         i++;
699                 }
700         }
701         // AMBIENT
702         // color
703         if (ef->getAmbient().isColor()) {
704                 col = ef->getAmbient().getColor();
705                 ma->ambr = col.getRed();
706                 ma->ambg = col.getGreen();
707                 ma->ambb = col.getBlue();
708         }
709         // texture
710         else if (ef->getAmbient().isTexture()) {
711                 COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); 
712                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
713                 if (mtex != NULL) {
714                         mtex->mapto = MAP_AMB; 
715                         i++;
716                 }
717         }
718         // SPECULAR
719         // color
720         if (ef->getSpecular().isColor()) {
721                 col = ef->getSpecular().getColor();
722                 ma->specr = col.getRed();
723                 ma->specg = col.getGreen();
724                 ma->specb = col.getBlue();
725         }
726         // texture
727         else if (ef->getSpecular().isTexture()) {
728                 COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); 
729                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
730                 if (mtex != NULL) {
731                         mtex->mapto = MAP_SPEC; 
732                         i++;
733                 }
734         }
735         // REFLECTIVE
736         // color
737         if (ef->getReflective().isColor()) {
738                 col = ef->getReflective().getColor();
739                 ma->mirr = col.getRed();
740                 ma->mirg = col.getGreen();
741                 ma->mirb = col.getBlue();
742         }
743         // texture
744         else if (ef->getReflective().isTexture()) {
745                 COLLADAFW::Texture ctex = ef->getReflective().getTexture(); 
746                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
747                 if (mtex != NULL) {
748                         mtex->mapto = MAP_REF; 
749                         i++;
750                 }
751         }
752         // EMISSION
753         // color
754         if (ef->getEmission().isColor()) {
755                 // XXX there is no emission color in blender
756                 // but I am not sure
757         }
758         // texture
759         else if (ef->getEmission().isTexture()) {
760                 COLLADAFW::Texture ctex = ef->getEmission().getTexture(); 
761                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
762                 if (mtex != NULL) {
763                         mtex->mapto = MAP_EMIT; 
764                         i++;
765                 }
766         }
767         
768         if (ef->getOpacity().isTexture()) {
769                 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
770                 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
771                 if (mtex != NULL) {
772                         mtex->mapto = MAP_ALPHA;
773                         i++;
774                         ma->spectra = ma->alpha = 0;
775                         ma->mode |= MA_ZTRANSP | MA_TRANSP;
776                 }
777         }
778         // TRANSPARENT
779         // color
780 #if 0
781         if (ef->getOpacity().isColor()) {
782                 // XXX don't know what to do here
783         }
784         // texture
785         else if (ef->getOpacity().isTexture()) {
786                 ctex = ef->getOpacity().getTexture();
787                 if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
788                 else {
789                         mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
790                         if (mtex != NULL) mtex->mapto = MAP_ALPHA;
791                 }
792         }
793 #endif
794         material_texture_mapping_map[ma] = texindex_texarray_map;
795 }
796
797 /** When this method is called, the writer must write the effect.
798  * \return The writer should return true, if writing succeeded, false otherwise.*/
799
800 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
801 {
802         if (mImportStage != General)
803                 return true;
804         
805         const COLLADAFW::UniqueId& uid = effect->getUniqueId();
806         
807         if (uid_effect_map.find(uid) == uid_effect_map.end()) {
808                 fprintf(stderr, "Couldn't find a material by UID.\n");
809                 return true;
810         }
811         
812         Material *ma = uid_effect_map[uid];
813         std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
814         for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
815                 if (iter->second == ma) {
816                         this->FW_object_map[iter->first] = effect;
817                         break;
818                 }
819         }
820         COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
821         if (common_efs.getCount() < 1) {
822                 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
823                 return true;
824         }
825         // XXX TODO: Take all <profile_common>s
826         // Currently only first <profile_common> is supported
827         COLLADAFW::EffectCommon *ef = common_efs[0];
828         write_profile_COMMON(ef, ma);
829         this->FW_object_map[effect->getUniqueId()] = effect;
830                 
831         return true;
832 }
833
834
835 /** When this method is called, the writer must write the camera.
836  * \return The writer should return true, if writing succeeded, false otherwise.*/
837 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
838 {
839         if (mImportStage != General)
840                 return true;
841                 
842         Camera *cam = NULL;
843         std::string cam_id, cam_name;
844         
845         cam_id = camera->getOriginalId();
846         cam_name = camera->getName();
847         if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
848         else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
849         
850         if (!cam) {
851                 fprintf(stderr, "Cannot create camera.\n");
852                 return true;
853         }
854         cam->clipsta = camera->getNearClippingPlane().getValue();
855         cam->clipend = camera->getFarClippingPlane().getValue();
856         
857         COLLADAFW::Camera::CameraType type = camera->getCameraType();
858         switch (type) {
859                 case COLLADAFW::Camera::ORTHOGRAPHIC:
860                 {
861                         cam->type = CAM_ORTHO;
862                 }
863                 break;
864                 case COLLADAFW::Camera::PERSPECTIVE:
865                 {
866                         cam->type = CAM_PERSP;
867                 }
868                 break;
869                 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
870                 {
871                         fprintf(stderr, "Current camera type is not supported.\n");
872                         cam->type = CAM_PERSP;
873                 }
874                 break;
875         }
876         
877         switch (camera->getDescriptionType()) {
878                 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
879                 {
880                         switch (cam->type) {
881                                 case CAM_ORTHO:
882                                 {
883                                         double ymag = 2 * camera->getYMag().getValue();
884                                         double aspect = camera->getAspectRatio().getValue();
885                                         double xmag = aspect * ymag;
886                                         cam->ortho_scale = (float)xmag;
887                                 }
888                                 break;
889                                 case CAM_PERSP:
890                                 default:
891                                 {
892                                         double yfov = camera->getYFov().getValue();
893                                         double aspect = camera->getAspectRatio().getValue();
894
895                                         // NOTE: Needs more testing (As we curretnly have no official test data for this)
896
897                                         double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
898                                         cam->lens = fov_to_focallength(xfov, cam->sensor_x);
899                                 }
900                                 break;
901                         }
902                 }
903                 break;
904                 /* XXX correct way to do following four is probably to get also render
905                  * size and determine proper settings from that somehow */
906                 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
907                 case COLLADAFW::Camera::SINGLE_X:
908                 case COLLADAFW::Camera::X_AND_Y:
909                 {
910                         switch (cam->type) {
911                                 case CAM_ORTHO:
912                                         cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
913                                         break;
914                                 case CAM_PERSP:
915                                 default:
916                                 {
917                                         double x = camera->getXFov().getValue();
918                                         // x is in degrees, cam->lens is in millimiters
919                                         cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
920                                 }
921                                 break;
922                         }
923                 }
924                 break;
925                 case COLLADAFW::Camera::SINGLE_Y:
926                 {
927                         switch (cam->type) {
928                                 case CAM_ORTHO:
929                                         cam->ortho_scale = (float)camera->getYMag().getValue();
930                                         break;
931                                 case CAM_PERSP:
932                                 default:
933                                 {
934                                         double yfov = camera->getYFov().getValue();
935                                         // yfov is in degrees, cam->lens is in millimiters
936                                         cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
937                                 }
938                                 break;
939                         }
940                 }
941                 break;
942                 case COLLADAFW::Camera::UNDEFINED:
943                         // read nothing, use blender defaults.
944                         break;
945         }
946         
947         this->uid_camera_map[camera->getUniqueId()] = cam;
948         this->FW_object_map[camera->getUniqueId()] = camera;
949         // XXX import camera options
950         return true;
951 }
952
953 /** When this method is called, the writer must write the image.
954  * \return The writer should return true, if writing succeeded, false otherwise.*/
955 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
956 {
957         if (mImportStage != General)
958                 return true;
959                 
960         // XXX maybe it is necessary to check if the path is absolute or relative
961         const std::string& filepath = image->getImageURI().toNativePath();
962         const char *filename = (const char *)mFilename.c_str();
963         char dir[FILE_MAX];
964         char full_path[FILE_MAX];
965         
966         BLI_split_dir_part(filename, dir, sizeof(dir));
967         BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
968         Image *ima = BKE_image_load_exists(full_path);
969         if (!ima) {
970                 fprintf(stderr, "Cannot create image.\n");
971                 return true;
972         }
973         this->uid_image_map[image->getUniqueId()] = ima;
974         
975         return true;
976 }
977
978 /** When this method is called, the writer must write the light.
979  * \return The writer should return true, if writing succeeded, false otherwise.*/
980 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
981 {
982         if (mImportStage != General)
983                 return true;
984
985         Lamp *lamp = NULL;
986         std::string la_id, la_name;
987
988         ExtraTags *et = getExtraTags(light->getUniqueId());
989         /*TagsMap::iterator etit;
990         ExtraTags *et = 0;
991         etit = uid_tags_map.find(light->getUniqueId().toAscii());
992         if (etit != uid_tags_map.end())
993                 et = etit->second;*/
994
995         la_id = light->getOriginalId();
996         la_name = light->getName();
997         if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
998         else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
999
1000         if (!lamp) {
1001                 fprintf(stderr, "Cannot create lamp.\n");
1002                 return true;
1003         }
1004
1005         // if we find an ExtraTags for this, use that instead.
1006         if (et && et->isProfile("blender")) {
1007                 et->setData("type", &(lamp->type));
1008                 et->setData("flag", &(lamp->flag));
1009                 et->setData("mode", &(lamp->mode));
1010                 et->setData("gamma", &(lamp->k));
1011                 et->setData("red", &(lamp->r));
1012                 et->setData("green", &(lamp->g));
1013                 et->setData("blue", &(lamp->b));
1014                 et->setData("shadow_r", &(lamp->shdwr));
1015                 et->setData("shadow_g", &(lamp->shdwg));
1016                 et->setData("shadow_b", &(lamp->shdwb));
1017                 et->setData("energy", &(lamp->energy));
1018                 et->setData("dist", &(lamp->dist));
1019                 et->setData("spotsize", &(lamp->spotsize));
1020                 et->setData("spotblend", &(lamp->spotblend));
1021                 et->setData("halo_intensity", &(lamp->haint));
1022                 et->setData("att1", &(lamp->att1));
1023                 et->setData("att2", &(lamp->att2));
1024                 et->setData("falloff_type", &(lamp->falloff_type));
1025                 et->setData("clipsta", &(lamp->clipsta));
1026                 et->setData("clipend", &(lamp->clipend));
1027                 et->setData("shadspotsize", &(lamp->shadspotsize));
1028                 et->setData("bias", &(lamp->bias));
1029                 et->setData("soft", &(lamp->soft));
1030                 et->setData("compressthresh", &(lamp->compressthresh));
1031                 et->setData("bufsize", &(lamp->bufsize));
1032                 et->setData("samp", &(lamp->samp));
1033                 et->setData("buffers", &(lamp->buffers));
1034                 et->setData("filtertype", &(lamp->filtertype));
1035                 et->setData("bufflag", &(lamp->bufflag));
1036                 et->setData("buftype", &(lamp->buftype));
1037                 et->setData("ray_samp", &(lamp->ray_samp));
1038                 et->setData("ray_sampy", &(lamp->ray_sampy));
1039                 et->setData("ray_sampz", &(lamp->ray_sampz));
1040                 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1041                 et->setData("area_shape", &(lamp->area_shape));
1042                 et->setData("area_size", &(lamp->area_size));
1043                 et->setData("area_sizey", &(lamp->area_sizey));
1044                 et->setData("area_sizez", &(lamp->area_sizez));
1045                 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1046                 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1047                 et->setData("shadhalostep", &(lamp->shadhalostep));
1048                 et->setData("sun_effect_type", &(lamp->shadhalostep));
1049                 et->setData("skyblendtype", &(lamp->skyblendtype));
1050                 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1051                 et->setData("spread", &(lamp->spread));
1052                 et->setData("sun_brightness", &(lamp->sun_brightness));
1053                 et->setData("sun_size", &(lamp->sun_size));
1054                 et->setData("backscattered_light", &(lamp->backscattered_light));
1055                 et->setData("sun_intensity", &(lamp->sun_intensity));
1056                 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1057                 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1058                 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1059                 et->setData("skyblendfac", &(lamp->skyblendfac));
1060                 et->setData("sky_exposure", &(lamp->sky_exposure));
1061                 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1062         }
1063         else {
1064                 float constatt = light->getConstantAttenuation().getValue();
1065                 float linatt = light->getLinearAttenuation().getValue();
1066                 float quadatt = light->getQuadraticAttenuation().getValue();
1067                 float d = 25.0f;
1068                 float att1 = 0.0f;
1069                 float att2 = 0.0f;
1070                 float e = 1.0f;
1071
1072                 if (light->getColor().isValid()) {
1073                         COLLADAFW::Color col = light->getColor();
1074                         lamp->r = col.getRed();
1075                         lamp->g = col.getGreen();
1076                         lamp->b = col.getBlue();
1077                 }
1078
1079                 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1080                         att2 = quadatt;
1081                         d = sqrt(1.0f / quadatt);
1082                 }
1083                 // linear light
1084                 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1085                         att1 = linatt;
1086                         d = (1.0f / linatt);
1087                 }
1088                 else if (IS_EQ(constatt, 1.0f)) {
1089                         att1 = 1.0f;
1090                 }
1091                 else {
1092                         // assuming point light (const att = 1.0);
1093                         att1 = 1.0f;
1094                 }
1095                 
1096                 d *= (1.0f / unit_converter.getLinearMeter());
1097
1098                 lamp->energy = e;
1099                 lamp->dist = d;
1100
1101                 COLLADAFW::Light::LightType type = light->getLightType();
1102                 switch (type) {
1103                         case COLLADAFW::Light::AMBIENT_LIGHT:
1104                         {
1105                                 lamp->type = LA_HEMI;
1106                         }
1107                         break;
1108                         case COLLADAFW::Light::SPOT_LIGHT:
1109                         {
1110                                 lamp->type = LA_SPOT;
1111                                 lamp->att1 = att1;
1112                                 lamp->att2 = att2;
1113                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1114                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1115                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1116                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1117                                 lamp->spotsize = light->getFallOffAngle().getValue();
1118                                 lamp->spotblend = light->getFallOffExponent().getValue();
1119                         }
1120                         break;
1121                         case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1122                         {
1123                                 /* our sun is very strong, so pick a smaller energy level */
1124                                 lamp->type = LA_SUN;
1125                                 lamp->mode |= LA_NO_SPEC;
1126                         }
1127                         break;
1128                         case COLLADAFW::Light::POINT_LIGHT:
1129                         {
1130                                 lamp->type = LA_LOCAL;
1131                                 lamp->att1 = att1;
1132                                 lamp->att2 = att2;
1133                                 if (IS_EQ(att1, 0.0f) && att2 > 0)
1134                                         lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1135                                 if (IS_EQ(att2, 0.0f) && att1 > 0)
1136                                         lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1137                         }
1138                         break;
1139                         case COLLADAFW::Light::UNDEFINED:
1140                         {
1141                                 fprintf(stderr, "Current lamp type is not supported.\n");
1142                                 lamp->type = LA_LOCAL;
1143                         }
1144                         break;
1145                 }
1146         }
1147
1148         this->uid_lamp_map[light->getUniqueId()] = lamp;
1149         this->FW_object_map[light->getUniqueId()] = light;
1150         return true;
1151 }
1152
1153 // this function is called only for animations that pass COLLADAFW::validate
1154 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1155 {
1156         if (mImportStage != General)
1157                 return true;
1158                 
1159         // return true;
1160         return anim_importer.write_animation(anim);
1161 }
1162
1163 // called on post-process stage after writeVisualScenes
1164 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1165 {
1166         if (mImportStage != General)
1167                 return true;
1168                 
1169         // return true;
1170         return anim_importer.write_animation_list(animationList);
1171 }
1172
1173 /** When this method is called, the writer must write the skin controller data.
1174  * \return The writer should return true, if writing succeeded, false otherwise.*/
1175 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1176 {
1177         return armature_importer.write_skin_controller_data(skin);
1178 }
1179
1180 // this is called on postprocess, before writeVisualScenes
1181 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1182 {
1183         if (mImportStage != General)
1184                 return true;
1185                 
1186         return armature_importer.write_controller(controller);
1187 }
1188
1189 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1190 {
1191         return true;
1192 }
1193
1194 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1195 {
1196         return true;
1197 }
1198
1199 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1200 {
1201         if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1202                 return NULL;
1203         }
1204         return uid_tags_map[uid.toAscii()];
1205 }
1206
1207 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1208 {
1209         uid_tags_map[uid.toAscii()] = extra_tags;
1210         return true;
1211 }
1212
1213 bool DocumentImporter::is_armature(COLLADAFW::Node *node){
1214         COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1215         for (unsigned int i = 0; i < child_nodes.getCount(); i++) {     
1216                 if(child_nodes[i]->getType() == COLLADAFW::Node::JOINT) return true;
1217                 else continue;
1218         }
1219
1220         //no child is JOINT
1221         return false;
1222
1223 }