2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/collada/DocumentImporter.cpp
28 // * name imported objects
29 // * import object rotation as euler
33 #include <algorithm> // sort()
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"
49 #include "COLLADASaxFWLLoader.h"
50 #include "COLLADASaxFWLIExtraDataCallbackHandler.h"
53 #include "BLI_listbase.h"
55 #include "BLI_string.h"
56 #include "BLI_utildefines.h"
58 #include "BKE_camera.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"
70 #include "BLI_path_util.h"
72 #include "DNA_camera_types.h"
73 #include "DNA_lamp_types.h"
75 #include "RNA_access.h"
77 #include "MEM_guardedalloc.h"
84 #include "ExtraHandler.h"
85 #include "ErrorHandler.h"
86 #include "DocumentImporter.h"
87 #include "TransformReader.h"
89 #include "collada_internal.h"
90 #include "collada_utils.h"
94 * COLLADA Importer limitations:
95 * - no multiple scene import, all objects are added to active scene
98 // #define COLLADA_DEBUG
99 // creates empties for each imported bone on layer 2, for debugging
100 // #define ARMATURE_TEST
102 DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
103 import_settings(import_settings),
104 mImportStage(General),
106 armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
107 mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)),
108 anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C))
112 DocumentImporter::~DocumentImporter()
114 TagsMap::iterator etit;
115 etit = uid_tags_map.begin();
116 while (etit != uid_tags_map.end()) {
122 bool DocumentImporter::import()
124 ErrorHandler errorHandler;
125 COLLADASaxFWL::Loader loader(&errorHandler);
126 COLLADAFW::Root root(&loader, this);
127 ExtraHandler *ehandler = new ExtraHandler(this, &(this->anim_importer));
129 loader.registerExtraDataCallbackHandler(ehandler);
131 // deselect all to select new objects
132 BKE_scene_base_deselect_all(CTX_data_scene(mContext));
134 std::string mFilename = std::string(this->import_settings->filepath);
135 const std::string encodedFilename = bc_url_encode(mFilename);
136 if (!root.loadDocument(encodedFilename)) {
137 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
141 if (errorHandler.hasError())
144 /** TODO set up scene graph and such here */
146 mImportStage = Controller;
148 COLLADASaxFWL::Loader loader2;
149 COLLADAFW::Root root2(&loader2, this);
151 if (!root2.loadDocument(encodedFilename)) {
152 fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
159 mesh_importer.bmeshConversion();
164 void DocumentImporter::cancel(const COLLADAFW::String& errorMessage)
166 // TODO: if possible show error info
168 // Should we get rid of invisible Meshes that were created so far
169 // or maybe create objects at coordinate space origin?
171 // The latter sounds better.
174 void DocumentImporter::start()
178 void DocumentImporter::finish()
180 if (mImportStage != General)
183 /** TODO Break up and put into 2-pass parsing of DAE */
184 std::vector<const COLLADAFW::VisualScene *>::iterator it;
185 for (it = vscenes.begin(); it != vscenes.end(); it++) {
186 PointerRNA sceneptr, unit_settings;
187 PropertyRNA *system, *scale;
188 // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
189 Scene *sce = CTX_data_scene(mContext);
191 // for scene unit settings: system, scale_length
193 RNA_id_pointer_create(&sce->id, &sceneptr);
194 unit_settings = RNA_pointer_get(&sceneptr, "unit_settings");
195 system = RNA_struct_find_property(&unit_settings, "system");
196 scale = RNA_struct_find_property(&unit_settings, "scale_length");
198 if (this->import_settings->import_units) {
200 switch (unit_converter.isMetricSystem()) {
201 case UnitConverter::Metric:
202 RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC);
204 case UnitConverter::Imperial:
205 RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL);
208 RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE);
211 float unit_factor = unit_converter.getLinearMeter();
212 RNA_property_float_set(&unit_settings, scale, unit_factor);
213 fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor);
217 // TODO: add automatic scaling for the case when Blender units
218 // and import units are set to different values.
221 // Write nodes to scene
222 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
223 for (unsigned int i = 0; i < roots.getCount(); i++) {
224 write_node(roots[i], NULL, sce, NULL, false);
228 Main *bmain = CTX_data_main(mContext);
229 DAG_scene_sort(bmain, sce);
230 DAG_ids_flush_update(bmain, 0);
231 WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
236 mesh_importer.optimize_material_assignements();
238 armature_importer.set_tags_map(this->uid_tags_map);
239 armature_importer.make_armatures(mContext);
240 armature_importer.make_shape_keys();
243 armature_importer.fix_animation();
246 for (std::vector<const COLLADAFW::VisualScene *>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
247 const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
249 for (unsigned int i = 0; i < roots.getCount(); i++)
250 translate_anim_recursive(roots[i], NULL, NULL);
253 if (libnode_ob.size()) {
254 Scene *sce = CTX_data_scene(mContext);
256 fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size());
257 // free all library_nodes
258 std::vector<Object *>::iterator it;
259 for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) {
262 Base *base = BKE_scene_base_find(sce, ob);
264 BLI_remlink(&sce->base, base);
265 BKE_libblock_free_us(&G.main->object, base->object);
266 if (sce->basact == base)
273 DAG_scene_sort(CTX_data_main(mContext), sce);
274 DAG_ids_flush_update(CTX_data_main(mContext), 0);
279 void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
282 // The split in #29246, rootmap must point at actual root when
283 // calculating bones in apply_curves_as_matrix. - actual root is the root node.
284 // This has to do with inverse bind poses being world space
285 // (the sources for skinned bones' restposes) and the way
286 // non-skinning nodes have their "restpose" recursively calculated.
287 // XXX TODO: design issue, how to support unrelated joints taking
289 if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
290 // par is root if there's no corresp. key in root_map
291 if (root_map.find(par->getUniqueId()) == root_map.end())
292 root_map[node->getUniqueId()] = node;
294 root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
298 COLLADAFW::Transformation::TransformationType types[] = {
299 COLLADAFW::Transformation::ROTATE,
300 COLLADAFW::Transformation::SCALE,
301 COLLADAFW::Transformation::TRANSLATE,
302 COLLADAFW::Transformation::MATRIX
309 //for (i = 0; i < 4; i++)
311 anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
313 COLLADAFW::NodePointerArray &children = node->getChildNodes();
314 for (i = 0; i < children.getCount(); i++) {
315 translate_anim_recursive(children[i], node, NULL);
319 /** When this method is called, the writer must write the global document asset.
320 * \return The writer should return true, if writing succeeded, false otherwise.*/
321 bool DocumentImporter::writeGlobalAsset(const COLLADAFW::FileInfo *asset)
323 unit_converter.read_asset(asset);
328 /** When this method is called, the writer must write the scene.
329 * \return The writer should return true, if writing succeeded, false otherwise.*/
330 bool DocumentImporter::writeScene(const COLLADAFW::Scene *scene)
332 // XXX could store the scene id, but do nothing for now
335 Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce)
337 const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId();
338 if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) {
339 // fprintf(stderr, "Couldn't find camera by UID.\n");
343 Object *ob = bc_add_object(sce, OB_CAMERA, NULL);
344 Camera *cam = uid_camera_map[cam_uid];
345 Camera *old_cam = (Camera *)ob->data;
348 if (old_cam->id.us == 0)
349 BKE_libblock_free(&G.main->camera, old_cam);
353 Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce)
355 const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId();
356 if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) {
357 fprintf(stderr, "Couldn't find lamp by UID.\n");
361 Object *ob = bc_add_object(sce, OB_LAMP, NULL);
362 Lamp *la = uid_lamp_map[lamp_uid];
363 Lamp *old_lamp = (Lamp *)ob->data;
366 if (old_lamp->id.us == 0)
367 BKE_libblock_free(&G.main->lamp, old_lamp);
371 Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node)
373 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);
375 Object *obn = BKE_object_copy(source_ob);
376 obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
377 BKE_scene_base_add(sce, obn);
380 anim_importer.read_node_transform(instance_node, obn);
381 // if we also have a source_node (always ;), take its
382 // transformation matrix and apply it to the newly instantiated
383 // object to account for node hierarchy transforms in
386 COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix();
387 COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order
389 for (int i = 0; i < 4; i++) {
390 for (int j = 0; j < 4; j++) {
391 mat[i][j] = bmat4[i][j];
394 // calc new matrix and apply
395 mult_m4_m4m4(obn->obmat, obn->obmat, mat);
396 BKE_object_apply_mat4(obn, obn->obmat, 0, 0);
400 anim_importer.read_node_transform(source_node, obn);
403 /*DAG_scene_sort(CTX_data_main(mContext), sce);
404 DAG_ids_flush_update(CTX_data_main(mContext), 0);*/
406 COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
407 if (children.getCount()) {
408 for (unsigned int i = 0; i < children.getCount(); i++) {
409 COLLADAFW::Node *child_node = children[i];
410 const COLLADAFW::UniqueId& child_id = child_node->getUniqueId();
411 if (object_map.find(child_id) == object_map.end())
413 COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes();
414 Object *new_child = NULL;
415 if (inodes.getCount()) { // \todo loop through instance nodes
416 const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId();
417 fprintf(stderr, "Doing %d child nodes\n", (int)node_map.count(id));
418 new_child = create_instance_node(object_map.find(id)->second, node_map[id], child_node, sce, is_library_node);
421 new_child = create_instance_node(object_map.find(child_id)->second, child_node, NULL, sce, is_library_node);
423 bc_set_parent(new_child, obn, mContext, true);
426 libnode_ob.push_back(new_child);
433 // to create constraints off node <extra> tags. Assumes only constraint data in
434 // current <extra> with blender profile.
435 void DocumentImporter::create_constraints(ExtraTags *et, Object *ob){
436 if ( et && et->isProfile("blender")){
439 et->setData("type", type);
440 BKE_add_ob_constraint(ob, "Test_con", *type);
445 void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
448 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
449 bool read_transform = true;
450 std::string id = node->getOriginalId();
451 std::string name = node->getName();
453 std::vector<Object *> *objects_done = new std::vector<Object *>();
456 "Writing node id='%s', name='%s'\n",
461 armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
464 COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
465 COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras();
466 COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights();
467 COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers();
468 COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes();
469 size_t geom_done = 0;
470 size_t camera_done = 0;
471 size_t lamp_done = 0;
472 size_t controller_done = 0;
473 size_t inst_done = 0;
475 // XXX linking object with the first <instance_geometry>, though a node may have more of them...
476 // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure...
477 // <instance_geometry>
478 while (geom_done < geom.getCount()) {
479 ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
480 material_texture_mapping_map);
483 "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
488 objects_done->push_back(ob);
492 while (camera_done < camera.getCount()) {
493 ob = create_camera_object(camera[camera_done], sce);
495 std::string id = node->getOriginalId();
496 std::string name = node->getName();
497 fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
500 objects_done->push_back(ob);
503 while (lamp_done < lamp.getCount()) {
504 ob = create_lamp_object(lamp[lamp_done], sce);
505 objects_done->push_back(ob);
508 while (controller_done < controller.getCount()) {
509 COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry *)controller[controller_done];
510 ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map);
511 objects_done->push_back(ob);
514 // XXX instance_node is not supported yet
515 while (inst_done < inst_node.getCount()) {
516 const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId();
517 if (object_map.find(node_id) == object_map.end()) {
518 fprintf(stderr, "Cannot find object for node referenced by <instance_node name=\"%s\">.\n", inst_node[inst_done]->getName().c_str());
522 std::pair<std::multimap<COLLADAFW::UniqueId, Object *>::iterator, std::multimap<COLLADAFW::UniqueId, Object *>::iterator> pair_iter = object_map.equal_range(node_id);
523 for (std::multimap<COLLADAFW::UniqueId, Object *>::iterator it2 = pair_iter.first; it2 != pair_iter.second; it2++) {
524 Object *source_ob = (Object *)it2->second;
525 COLLADAFW::Node *source_node = node_map[node_id];
526 ob = create_instance_node(source_ob, source_node, node, sce, is_library_node);
529 if (ob != NULL) objects_done->push_back(ob);
532 read_transform = false;
535 // if node is empty - create empty object
536 // XXX empty node may not mean it is empty object, not sure about this
537 if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
538 //Check if Object is armature, by checking if immediate child is a JOINT node.
539 if(is_armature(node))
540 ob = bc_add_object(sce, OB_ARMATURE, NULL);
541 else ob = bc_add_object(sce, OB_EMPTY, NULL);
543 objects_done->push_back(ob);
546 // XXX: if there're multiple instances, only one is stored
549 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
551 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
552 rename_id(&ob->id, (char *)nodename.c_str());
553 object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), ob));
554 node_map[node->getUniqueId()] = node;
557 libnode_ob.push_back(ob);
560 //create_constraints(et,ob);
564 for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
568 anim_importer.read_node_transform(node, ob); // overwrites location set earlier
571 // if par was given make this object child of the previous
573 bc_set_parent(ob, par, mContext);
576 // if node has child nodes write them
577 COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
578 if (objects_done->size() > 0) {
579 ob = *objects_done->begin();
580 for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
581 write_node(child_nodes[i], node, sce, ob, is_library_node);
586 /** When this method is called, the writer must write the entire visual scene.
587 * \return The writer should return true, if writing succeeded, false otherwise.*/
588 bool DocumentImporter::writeVisualScene(const COLLADAFW::VisualScene *visualScene)
590 if (mImportStage != General)
593 // this method called on post process after writeGeometry, writeMaterial, etc.
595 // for each <node> in <visual_scene>:
597 // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh
599 // update: since we cannot link a Mesh with Object in
600 // writeGeometry because <geometry> does not reference <node>,
601 // we link Objects with Meshes here
603 vscenes.push_back(visualScene);
608 /** When this method is called, the writer must handle all nodes contained in the
610 * \return The writer should return true, if writing succeeded, false otherwise.*/
611 bool DocumentImporter::writeLibraryNodes(const COLLADAFW::LibraryNodes *libraryNodes)
613 if (mImportStage != General)
616 Scene *sce = CTX_data_scene(mContext);
618 const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes();
620 for (unsigned int i = 0; i < nodes.getCount(); i++) {
621 write_node(nodes[i], NULL, sce, NULL, true);
627 /** When this method is called, the writer must write the geometry.
628 * \return The writer should return true, if writing succeeded, false otherwise.*/
629 bool DocumentImporter::writeGeometry(const COLLADAFW::Geometry *geom)
631 if (mImportStage != General)
634 return mesh_importer.write_geometry(geom);
637 /** When this method is called, the writer must write the material.
638 * \return The writer should return true, if writing succeeded, false otherwise.*/
639 bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
641 if (mImportStage != General)
644 const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
645 Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
647 this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
648 this->uid_material_map[cmat->getUniqueId()] = ma;
653 // create mtex, create texture, set texture image
654 MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma,
655 int i, TexIndexTextureArrayMap &texindex_texarray_map)
657 COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray();
658 COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()];
660 const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage();
662 if (uid_image_map.find(ima_uid) == uid_image_map.end()) {
663 fprintf(stderr, "Couldn't find an image by UID.\n");
667 ma->mtex[i] = add_mtex();
668 ma->mtex[i]->texco = TEXCO_UV;
669 ma->mtex[i]->tex = add_texture(G.main, "Texture");
670 ma->mtex[i]->tex->type = TEX_IMAGE;
671 ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
673 texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]);
678 void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma)
680 COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
683 if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
684 ma->spec_shader = MA_SPEC_BLINN;
685 ma->spec = ef->getShininess().getFloatValue();
688 else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
689 ma->spec_shader = MA_SPEC_PHONG;
690 ma->har = ef->getShininess().getFloatValue();
693 else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
694 ma->diff_shader = MA_DIFF_LAMBERT;
698 ma->diff_shader = MA_DIFF_LAMBERT;
699 fprintf(stderr, "Current shader type is not supported, default to lambert.\n");
702 ma->ray_mirror = ef->getReflectivity().getFloatValue();
703 // index of refraction
704 ma->ang = ef->getIndexOfRefraction().getFloatValue();
707 COLLADAFW::Color col;
709 TexIndexTextureArrayMap texindex_texarray_map;
713 if (ef->getDiffuse().isColor()) {
714 col = ef->getDiffuse().getColor();
715 ma->r = col.getRed();
716 ma->g = col.getGreen();
717 ma->b = col.getBlue();
720 else if (ef->getDiffuse().isTexture()) {
721 COLLADAFW::Texture ctex = ef->getDiffuse().getTexture();
722 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
724 mtex->mapto = MAP_COL;
731 if (ef->getAmbient().isColor()) {
732 col = ef->getAmbient().getColor();
733 ma->ambr = col.getRed();
734 ma->ambg = col.getGreen();
735 ma->ambb = col.getBlue();
738 else if (ef->getAmbient().isTexture()) {
739 COLLADAFW::Texture ctex = ef->getAmbient().getTexture();
740 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
742 mtex->mapto = MAP_AMB;
748 if (ef->getSpecular().isColor()) {
749 col = ef->getSpecular().getColor();
750 ma->specr = col.getRed();
751 ma->specg = col.getGreen();
752 ma->specb = col.getBlue();
755 else if (ef->getSpecular().isTexture()) {
756 COLLADAFW::Texture ctex = ef->getSpecular().getTexture();
757 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
759 mtex->mapto = MAP_SPEC;
765 if (ef->getReflective().isColor()) {
766 col = ef->getReflective().getColor();
767 ma->mirr = col.getRed();
768 ma->mirg = col.getGreen();
769 ma->mirb = col.getBlue();
772 else if (ef->getReflective().isTexture()) {
773 COLLADAFW::Texture ctex = ef->getReflective().getTexture();
774 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
776 mtex->mapto = MAP_REF;
782 if (ef->getEmission().isColor()) {
783 // XXX there is no emission color in blender
787 else if (ef->getEmission().isTexture()) {
788 COLLADAFW::Texture ctex = ef->getEmission().getTexture();
789 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
791 mtex->mapto = MAP_EMIT;
796 if (ef->getOpacity().isTexture()) {
797 COLLADAFW::Texture ctex = ef->getOpacity().getTexture();
798 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
800 mtex->mapto = MAP_ALPHA;
802 ma->spectra = ma->alpha = 0;
803 ma->mode |= MA_ZTRANSP | MA_TRANSP;
809 if (ef->getOpacity().isColor()) {
810 // XXX don't know what to do here
813 else if (ef->getOpacity().isTexture()) {
814 ctex = ef->getOpacity().getTexture();
815 if (mtex != NULL) mtex->mapto &= MAP_ALPHA;
817 mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
818 if (mtex != NULL) mtex->mapto = MAP_ALPHA;
822 material_texture_mapping_map[ma] = texindex_texarray_map;
825 /** When this method is called, the writer must write the effect.
826 * \return The writer should return true, if writing succeeded, false otherwise.*/
828 bool DocumentImporter::writeEffect(const COLLADAFW::Effect *effect)
830 if (mImportStage != General)
833 const COLLADAFW::UniqueId& uid = effect->getUniqueId();
835 if (uid_effect_map.find(uid) == uid_effect_map.end()) {
836 fprintf(stderr, "Couldn't find a material by UID.\n");
840 Material *ma = uid_effect_map[uid];
841 std::map<COLLADAFW::UniqueId, Material *>::iterator iter;
842 for (iter = uid_material_map.begin(); iter != uid_material_map.end(); iter++) {
843 if (iter->second == ma) {
844 this->FW_object_map[iter->first] = effect;
848 COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects();
849 if (common_efs.getCount() < 1) {
850 fprintf(stderr, "Couldn't find <profile_COMMON>.\n");
853 // XXX TODO: Take all <profile_common>s
854 // Currently only first <profile_common> is supported
855 COLLADAFW::EffectCommon *ef = common_efs[0];
856 write_profile_COMMON(ef, ma);
857 this->FW_object_map[effect->getUniqueId()] = effect;
863 /** When this method is called, the writer must write the camera.
864 * \return The writer should return true, if writing succeeded, false otherwise.*/
865 bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
867 if (mImportStage != General)
871 std::string cam_id, cam_name;
873 cam_id = camera->getOriginalId();
874 cam_name = camera->getName();
875 if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
876 else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
879 fprintf(stderr, "Cannot create camera.\n");
882 cam->clipsta = camera->getNearClippingPlane().getValue();
883 cam->clipend = camera->getFarClippingPlane().getValue();
885 COLLADAFW::Camera::CameraType type = camera->getCameraType();
887 case COLLADAFW::Camera::ORTHOGRAPHIC:
889 cam->type = CAM_ORTHO;
892 case COLLADAFW::Camera::PERSPECTIVE:
894 cam->type = CAM_PERSP;
897 case COLLADAFW::Camera::UNDEFINED_CAMERATYPE:
899 fprintf(stderr, "Current camera type is not supported.\n");
900 cam->type = CAM_PERSP;
905 switch (camera->getDescriptionType()) {
906 case COLLADAFW::Camera::ASPECTRATIO_AND_Y:
911 double ymag = 2 * camera->getYMag().getValue();
912 double aspect = camera->getAspectRatio().getValue();
913 double xmag = aspect * ymag;
914 cam->ortho_scale = (float)xmag;
920 double yfov = camera->getYFov().getValue();
921 double aspect = camera->getAspectRatio().getValue();
923 // NOTE: Needs more testing (As we curretnly have no official test data for this)
925 double xfov = 2.0f * atanf(aspect * tanf(DEG2RADF(yfov) * 0.5f));
926 cam->lens = fov_to_focallength(xfov, cam->sensor_x);
932 /* XXX correct way to do following four is probably to get also render
933 * size and determine proper settings from that somehow */
934 case COLLADAFW::Camera::ASPECTRATIO_AND_X:
935 case COLLADAFW::Camera::SINGLE_X:
936 case COLLADAFW::Camera::X_AND_Y:
940 cam->ortho_scale = (float)camera->getXMag().getValue() * 2;
945 double x = camera->getXFov().getValue();
946 // x is in degrees, cam->lens is in millimiters
947 cam->lens = fov_to_focallength(DEG2RADF(x), cam->sensor_x);
953 case COLLADAFW::Camera::SINGLE_Y:
957 cam->ortho_scale = (float)camera->getYMag().getValue();
962 double yfov = camera->getYFov().getValue();
963 // yfov is in degrees, cam->lens is in millimiters
964 cam->lens = fov_to_focallength(DEG2RADF(yfov), cam->sensor_x);
970 case COLLADAFW::Camera::UNDEFINED:
971 // read nothing, use blender defaults.
975 this->uid_camera_map[camera->getUniqueId()] = cam;
976 this->FW_object_map[camera->getUniqueId()] = camera;
977 // XXX import camera options
981 /** When this method is called, the writer must write the image.
982 * \return The writer should return true, if writing succeeded, false otherwise.*/
983 bool DocumentImporter::writeImage(const COLLADAFW::Image *image)
985 if (mImportStage != General)
988 // XXX maybe it is necessary to check if the path is absolute or relative
989 const std::string& filepath = image->getImageURI().toNativePath();
990 const char *filename = (const char *)filepath.c_str();
992 char full_path[FILE_MAX];
994 BLI_split_dir_part(filename, dir, sizeof(dir));
995 BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
996 Image *ima = BKE_image_load_exists(full_path);
998 fprintf(stderr, "Cannot create image.\n");
1001 this->uid_image_map[image->getUniqueId()] = ima;
1006 /** When this method is called, the writer must write the light.
1007 * \return The writer should return true, if writing succeeded, false otherwise.*/
1008 bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
1010 if (mImportStage != General)
1014 std::string la_id, la_name;
1016 ExtraTags *et = getExtraTags(light->getUniqueId());
1017 /*TagsMap::iterator etit;
1019 etit = uid_tags_map.find(light->getUniqueId().toAscii());
1020 if (etit != uid_tags_map.end())
1021 et = etit->second;*/
1023 la_id = light->getOriginalId();
1024 la_name = light->getName();
1025 if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
1026 else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
1029 fprintf(stderr, "Cannot create lamp.\n");
1033 // if we find an ExtraTags for this, use that instead.
1034 if (et && et->isProfile("blender")) {
1035 et->setData("type", &(lamp->type));
1036 et->setData("flag", &(lamp->flag));
1037 et->setData("mode", &(lamp->mode));
1038 et->setData("gamma", &(lamp->k));
1039 et->setData("red", &(lamp->r));
1040 et->setData("green", &(lamp->g));
1041 et->setData("blue", &(lamp->b));
1042 et->setData("shadow_r", &(lamp->shdwr));
1043 et->setData("shadow_g", &(lamp->shdwg));
1044 et->setData("shadow_b", &(lamp->shdwb));
1045 et->setData("energy", &(lamp->energy));
1046 et->setData("dist", &(lamp->dist));
1047 et->setData("spotsize", &(lamp->spotsize));
1048 et->setData("spotblend", &(lamp->spotblend));
1049 et->setData("halo_intensity", &(lamp->haint));
1050 et->setData("att1", &(lamp->att1));
1051 et->setData("att2", &(lamp->att2));
1052 et->setData("falloff_type", &(lamp->falloff_type));
1053 et->setData("clipsta", &(lamp->clipsta));
1054 et->setData("clipend", &(lamp->clipend));
1055 et->setData("shadspotsize", &(lamp->shadspotsize));
1056 et->setData("bias", &(lamp->bias));
1057 et->setData("soft", &(lamp->soft));
1058 et->setData("compressthresh", &(lamp->compressthresh));
1059 et->setData("bufsize", &(lamp->bufsize));
1060 et->setData("samp", &(lamp->samp));
1061 et->setData("buffers", &(lamp->buffers));
1062 et->setData("filtertype", &(lamp->filtertype));
1063 et->setData("bufflag", &(lamp->bufflag));
1064 et->setData("buftype", &(lamp->buftype));
1065 et->setData("ray_samp", &(lamp->ray_samp));
1066 et->setData("ray_sampy", &(lamp->ray_sampy));
1067 et->setData("ray_sampz", &(lamp->ray_sampz));
1068 et->setData("ray_samp_type", &(lamp->ray_samp_type));
1069 et->setData("area_shape", &(lamp->area_shape));
1070 et->setData("area_size", &(lamp->area_size));
1071 et->setData("area_sizey", &(lamp->area_sizey));
1072 et->setData("area_sizez", &(lamp->area_sizez));
1073 et->setData("adapt_thresh", &(lamp->adapt_thresh));
1074 et->setData("ray_samp_method", &(lamp->ray_samp_method));
1075 et->setData("shadhalostep", &(lamp->shadhalostep));
1076 et->setData("sun_effect_type", &(lamp->shadhalostep));
1077 et->setData("skyblendtype", &(lamp->skyblendtype));
1078 et->setData("horizon_brightness", &(lamp->horizon_brightness));
1079 et->setData("spread", &(lamp->spread));
1080 et->setData("sun_brightness", &(lamp->sun_brightness));
1081 et->setData("sun_size", &(lamp->sun_size));
1082 et->setData("backscattered_light", &(lamp->backscattered_light));
1083 et->setData("sun_intensity", &(lamp->sun_intensity));
1084 et->setData("atm_turbidity", &(lamp->atm_turbidity));
1085 et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor));
1086 et->setData("atm_distance_factor", &(lamp->atm_distance_factor));
1087 et->setData("skyblendfac", &(lamp->skyblendfac));
1088 et->setData("sky_exposure", &(lamp->sky_exposure));
1089 et->setData("sky_colorspace", &(lamp->sky_colorspace));
1092 float constatt = light->getConstantAttenuation().getValue();
1093 float linatt = light->getLinearAttenuation().getValue();
1094 float quadatt = light->getQuadraticAttenuation().getValue();
1100 if (light->getColor().isValid()) {
1101 COLLADAFW::Color col = light->getColor();
1102 lamp->r = col.getRed();
1103 lamp->g = col.getGreen();
1104 lamp->b = col.getBlue();
1107 if (IS_EQ(linatt, 0.0f) && quadatt > 0.0f) {
1109 d = sqrt(1.0f / quadatt);
1112 else if (IS_EQ(quadatt, 0.0f) && linatt > 0.0f) {
1114 d = (1.0f / linatt);
1116 else if (IS_EQ(constatt, 1.0f)) {
1120 // assuming point light (const att = 1.0);
1124 d *= (1.0f / unit_converter.getLinearMeter());
1129 COLLADAFW::Light::LightType type = light->getLightType();
1131 case COLLADAFW::Light::AMBIENT_LIGHT:
1133 lamp->type = LA_HEMI;
1136 case COLLADAFW::Light::SPOT_LIGHT:
1138 lamp->type = LA_SPOT;
1141 if (IS_EQ(att1, 0.0f) && att2 > 0)
1142 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1143 if (IS_EQ(att2, 0.0f) && att1 > 0)
1144 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1145 lamp->spotsize = light->getFallOffAngle().getValue();
1146 lamp->spotblend = light->getFallOffExponent().getValue();
1149 case COLLADAFW::Light::DIRECTIONAL_LIGHT:
1151 /* our sun is very strong, so pick a smaller energy level */
1152 lamp->type = LA_SUN;
1153 lamp->mode |= LA_NO_SPEC;
1156 case COLLADAFW::Light::POINT_LIGHT:
1158 lamp->type = LA_LOCAL;
1161 if (IS_EQ(att1, 0.0f) && att2 > 0)
1162 lamp->falloff_type = LA_FALLOFF_INVSQUARE;
1163 if (IS_EQ(att2, 0.0f) && att1 > 0)
1164 lamp->falloff_type = LA_FALLOFF_INVLINEAR;
1167 case COLLADAFW::Light::UNDEFINED:
1169 fprintf(stderr, "Current lamp type is not supported.\n");
1170 lamp->type = LA_LOCAL;
1176 this->uid_lamp_map[light->getUniqueId()] = lamp;
1177 this->FW_object_map[light->getUniqueId()] = light;
1181 // this function is called only for animations that pass COLLADAFW::validate
1182 bool DocumentImporter::writeAnimation(const COLLADAFW::Animation *anim)
1184 if (mImportStage != General)
1188 return anim_importer.write_animation(anim);
1191 // called on post-process stage after writeVisualScenes
1192 bool DocumentImporter::writeAnimationList(const COLLADAFW::AnimationList *animationList)
1194 if (mImportStage != General)
1198 return anim_importer.write_animation_list(animationList);
1201 /** When this method is called, the writer must write the skin controller data.
1202 * \return The writer should return true, if writing succeeded, false otherwise.*/
1203 bool DocumentImporter::writeSkinControllerData(const COLLADAFW::SkinControllerData *skin)
1205 return armature_importer.write_skin_controller_data(skin);
1208 // this is called on postprocess, before writeVisualScenes
1209 bool DocumentImporter::writeController(const COLLADAFW::Controller *controller)
1211 if (mImportStage != General)
1214 return armature_importer.write_controller(controller);
1217 bool DocumentImporter::writeFormulas(const COLLADAFW::Formulas *formulas)
1222 bool DocumentImporter::writeKinematicsScene(const COLLADAFW::KinematicsScene *kinematicsScene)
1227 ExtraTags *DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid)
1229 if (uid_tags_map.find(uid.toAscii()) == uid_tags_map.end()) {
1232 return uid_tags_map[uid.toAscii()];
1235 bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags)
1237 uid_tags_map[uid.toAscii()] = extra_tags;
1241 bool DocumentImporter::is_armature(COLLADAFW::Node *node){
1242 COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
1243 for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
1244 if(child_nodes[i]->getType() == COLLADAFW::Node::JOINT) return true;