diff options
Diffstat (limited to 'source/blender/collada/DocumentImporter.cpp')
-rw-r--r-- | source/blender/collada/DocumentImporter.cpp | 1676 |
1 files changed, 880 insertions, 796 deletions
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 2267cf747b1..72341e1caa2 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -21,6 +21,11 @@ * * ***** END GPL LICENSE BLOCK ***** */ + +/** \file blender/collada/DocumentImporter.cpp + * \ingroup collada + */ + // TODO: // * name imported objects // * import object rotation as euler @@ -44,6 +49,7 @@ #include "COLLADAFWLight.h" #include "COLLADASaxFWLLoader.h" +#include "COLLADASaxFWLIExtraDataCallbackHandler.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -69,9 +75,11 @@ #include "MEM_guardedalloc.h" +#include "ExtraHandler.h" #include "DocumentImporter.h" -#include "collada_internal.h" +#include "TransformReader.h" +#include "collada_internal.h" #include "collada_utils.h" @@ -84,589 +92,587 @@ // creates empties for each imported bone on layer 2, for debugging // #define ARMATURE_TEST -/** Class that needs to be implemented by a writer. - IMPORTANT: The write functions are called in arbitrary order.*/ -/* -private: - std::string mFilename; +DocumentImporter::DocumentImporter(bContext *C, const char *filename) : + mImportStage(General), + mFilename(filename), + mContext(C), + armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)), + mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)), + anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C)) +{} + +DocumentImporter::~DocumentImporter() +{ + TagsMap::iterator etit; + etit = uid_tags_map.begin(); + while(etit!=uid_tags_map.end()) { + delete etit->second; + etit++; + } +} + +bool DocumentImporter::import() +{ + /** TODO Add error handler (implement COLLADASaxFWL::IErrorHandler */ + COLLADASaxFWL::Loader loader; + COLLADAFW::Root root(&loader, this); + ExtraHandler *ehandler = new ExtraHandler(this); - bContext *mContext; - - UnitConverter unit_converter; - ArmatureImporter armature_importer; - MeshImporter mesh_importer; - AnimationImporter anim_importer; - - std::map<COLLADAFW::UniqueId, Image*> uid_image_map; - std::map<COLLADAFW::UniqueId, Material*> uid_material_map; - std::map<COLLADAFW::UniqueId, Material*> uid_effect_map; - std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map; - std::map<COLLADAFW::UniqueId, Lamp*> uid_lamp_map; - std::map<Material*, TexIndexTextureArrayMap> material_texture_mapping_map; - std::map<COLLADAFW::UniqueId, Object*> object_map; - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> node_map; - std::vector<const COLLADAFW::VisualScene*> vscenes; - std::vector<Object*> libnode_ob; - - std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> root_map; - */ - // find root joint by child joint uid, for bone tree evaluation during resampling - - // animation - // std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map; - // Nodes don't share AnimationLists (Arystan) - // std::map<COLLADAFW::UniqueId, Animation> uid_animated_map; // AnimationList->uniqueId to AnimatedObject map - -//public: - - /** Constructor. */ - DocumentImporter::DocumentImporter(bContext *C, const char *filename) : - mImportStage(General), - mFilename(filename), - mContext(C), - armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)), - mesh_importer(&unit_converter, &armature_importer, CTX_data_scene(C)), - anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C)) - {} - - /** Destructor. */ - DocumentImporter::~DocumentImporter() {} - - bool DocumentImporter::import() - { - /** TODO Add error handler (implement COLLADASaxFWL::IErrorHandler */ - COLLADASaxFWL::Loader loader; - COLLADAFW::Root root(&loader, this); - - if (!root.loadDocument(mFilename)) - return false; - - /** TODO set up scene graph and such here */ + loader.registerExtraDataCallbackHandler(ehandler); + + + if (!root.loadDocument(mFilename)) + return false; + + /** TODO set up scene graph and such here */ + + mImportStage = Controller; + + COLLADASaxFWL::Loader loader2; + COLLADAFW::Root root2(&loader2, this); + + if (!root2.loadDocument(mFilename)) + return false; + + + delete ehandler; + + return true; +} + +void DocumentImporter::cancel(const COLLADAFW::String& errorMessage) +{ + // TODO: if possible show error info + // + // Should we get rid of invisible Meshes that were created so far + // or maybe create objects at coordinate space origin? + // + // The latter sounds better. +} + +void DocumentImporter::start(){} + +void DocumentImporter::finish() +{ + if(mImportStage!=General) + return; - mImportStage = Controller; + /** TODO Break up and put into 2-pass parsing of DAE */ + std::vector<const COLLADAFW::VisualScene*>::iterator it; + for (it = vscenes.begin(); it != vscenes.end(); it++) { + PointerRNA sceneptr, unit_settings; + PropertyRNA *system, *scale; + // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it + Scene *sce = CTX_data_scene(mContext); - COLLADASaxFWL::Loader loader2; - COLLADAFW::Root root2(&loader2, this); + // for scene unit settings: system, scale_length + RNA_id_pointer_create(&sce->id, &sceneptr); + unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); + system = RNA_struct_find_property(&unit_settings, "system"); + scale = RNA_struct_find_property(&unit_settings, "scale_length"); - if (!root2.loadDocument(mFilename)) - return false; + switch(unit_converter.isMetricSystem()) { + case UnitConverter::Metric: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); + break; + case UnitConverter::Imperial: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); + break; + default: + RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); + break; + } + RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter()); + const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - return true; - } - - void DocumentImporter::cancel(const COLLADAFW::String& errorMessage) - { - // TODO: if possible show error info - // - // Should we get rid of invisible Meshes that were created so far - // or maybe create objects at coordinate space origin? - // - // The latter sounds better. - } - - void DocumentImporter::start(){} - - /** This method is called after the last write* method. No other methods will be called after this.*/ - void DocumentImporter::finish() - { - if(mImportStage!=General) - return; - - /** TODO Break up and put into 2-pass parsing of DAE */ - std::vector<const COLLADAFW::VisualScene*>::iterator it; - for (it = vscenes.begin(); it != vscenes.end(); it++) { - PointerRNA sceneptr, unit_settings; - PropertyRNA *system, *scale; - // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it - Scene *sce = CTX_data_scene(mContext); - - // for scene unit settings: system, scale_length - RNA_id_pointer_create(&sce->id, &sceneptr); - unit_settings = RNA_pointer_get(&sceneptr, "unit_settings"); - system = RNA_struct_find_property(&unit_settings, "system"); - scale = RNA_struct_find_property(&unit_settings, "scale_length"); - - switch(unit_converter.isMetricSystem()) { - case UnitConverter::Metric: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_METRIC); - break; - case UnitConverter::Imperial: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_IMPERIAL); - break; - default: - RNA_property_enum_set(&unit_settings, system, USER_UNIT_NONE); - break; - } - RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter()); - - const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - - for (unsigned int i = 0; i < roots.getCount(); i++) { - write_node(roots[i], NULL, sce, NULL, false); - } + for (unsigned int i = 0; i < roots.getCount(); i++) { + write_node(roots[i], NULL, sce, NULL, false); } + } - armature_importer.make_armatures(mContext); + armature_importer.make_armatures(mContext); #if 0 - armature_importer.fix_animation(); + armature_importer.fix_animation(); #endif - for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) { - const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - - for (unsigned int i = 0; i < roots.getCount(); i++) - translate_anim_recursive(roots[i],NULL,NULL); - } + for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) { + const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes(); - if (libnode_ob.size()) { - Scene *sce = CTX_data_scene(mContext); - - fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size()); - // free all library_nodes - std::vector<Object*>::iterator it; - for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { - Object *ob = *it; - - Base *base = object_in_scene(ob, sce); - if (base) { - BLI_remlink(&sce->base, base); - free_libblock_us(&G.main->object, base->object); - if (sce->basact==base) - sce->basact= NULL; - MEM_freeN(base); - } - } - libnode_ob.clear(); - - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); - } + for (unsigned int i = 0; i < roots.getCount(); i++) + translate_anim_recursive(roots[i],NULL,NULL); } + if (libnode_ob.size()) { + Scene *sce = CTX_data_scene(mContext); - void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL) - { - if (par && par->getType() == COLLADAFW::Node::JOINT) { - // par is root if there's no corresp. key in root_map - if (root_map.find(par->getUniqueId()) == root_map.end()) - root_map[node->getUniqueId()] = par; - else - root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; + fprintf(stderr, "got %d library nodes to free\n", (int)libnode_ob.size()); + // free all library_nodes + std::vector<Object*>::iterator it; + for (it = libnode_ob.begin(); it != libnode_ob.end(); it++) { + Object *ob = *it; + + Base *base = object_in_scene(ob, sce); + if (base) { + BLI_remlink(&sce->base, base); + free_libblock_us(&G.main->object, base->object); + if (sce->basact==base) + sce->basact= NULL; + MEM_freeN(base); + } } + libnode_ob.clear(); - COLLADAFW::Transformation::TransformationType types[] = { - COLLADAFW::Transformation::ROTATE, - COLLADAFW::Transformation::SCALE, - COLLADAFW::Transformation::TRANSLATE, - COLLADAFW::Transformation::MATRIX - }; - - unsigned int i; - Object *ob; + DAG_scene_sort(CTX_data_main(mContext), sce); + DAG_ids_flush_update(CTX_data_main(mContext), 0); + } +} - for (i = 0; i < 4; i++) - ob = anim_importer.translate_animation(node, object_map, root_map, types[i]); - COLLADAFW::NodePointerArray &children = node->getChildNodes(); - for (i = 0; i < children.getCount(); i++) { - translate_anim_recursive(children[i], node, ob); - } +void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL) +{ + if (par && par->getType() == COLLADAFW::Node::JOINT) { + // par is root if there's no corresp. key in root_map + if (root_map.find(par->getUniqueId()) == root_map.end()) + root_map[node->getUniqueId()] = par; + else + root_map[node->getUniqueId()] = root_map[par->getUniqueId()]; } - /** When this method is called, the writer must write the global document asset. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) - { - unit_converter.read_asset(asset); + COLLADAFW::Transformation::TransformationType types[] = { + COLLADAFW::Transformation::ROTATE, + COLLADAFW::Transformation::SCALE, + COLLADAFW::Transformation::TRANSLATE, + COLLADAFW::Transformation::MATRIX + }; - return true; - } + unsigned int i; + Object *ob; - /** When this method is called, the writer must write the scene. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeScene ( const COLLADAFW::Scene* scene ) - { - // XXX could store the scene id, but do nothing for now - return true; + for (i = 0; i < 4; i++) + ob = anim_importer.translate_animation(node, object_map, root_map, types[i]); + + COLLADAFW::NodePointerArray &children = node->getChildNodes(); + for (i = 0; i < children.getCount(); i++) { + translate_anim_recursive(children[i], node, ob); } - Object* DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce) - { - const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId(); - if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { - fprintf(stderr, "Couldn't find camera by UID.\n"); - return NULL; - } - Object *ob = add_object(sce, OB_CAMERA); - Camera *cam = uid_camera_map[cam_uid]; - Camera *old_cam = (Camera*)ob->data; - ob->data = cam; - old_cam->id.us--; - if (old_cam->id.us == 0) - free_libblock(&G.main->camera, old_cam); - return ob; +} + +/** When this method is called, the writer must write the global document asset. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeGlobalAsset ( const COLLADAFW::FileInfo* asset ) +{ + unit_converter.read_asset(asset); + + return true; +} + +/** When this method is called, the writer must write the scene. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeScene ( const COLLADAFW::Scene* scene ) +{ + // XXX could store the scene id, but do nothing for now + return true; +} +Object* DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera, Scene *sce) +{ + const COLLADAFW::UniqueId& cam_uid = camera->getInstanciatedObjectId(); + if (uid_camera_map.find(cam_uid) == uid_camera_map.end()) { + fprintf(stderr, "Couldn't find camera by UID.\n"); + return NULL; } - - Object* DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce) - { - const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId(); - if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) { - fprintf(stderr, "Couldn't find lamp by UID. \n"); - return NULL; - } - Object *ob = add_object(sce, OB_LAMP); - Lamp *la = uid_lamp_map[lamp_uid]; - Lamp *old_lamp = (Lamp*)ob->data; - ob->data = la; - old_lamp->id.us--; - if (old_lamp->id.us == 0) - free_libblock(&G.main->lamp, old_lamp); - return ob; - } - - Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node) - { - Object *obn = copy_object(source_ob); - obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; - scene_add_base(sce, obn); - - if (instance_node) - anim_importer.read_node_transform(instance_node, obn); - else - anim_importer.read_node_transform(source_node, obn); - - DAG_scene_sort(CTX_data_main(mContext), sce); - DAG_ids_flush_update(CTX_data_main(mContext), 0); - - COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); - if (children.getCount()) { - for (unsigned int i = 0; i < children.getCount(); i++) { - COLLADAFW::Node *child_node = children[i]; - const COLLADAFW::UniqueId& child_id = child_node->getUniqueId(); - if (object_map.find(child_id) == object_map.end()) - continue; - COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes(); - Object *new_child = NULL; - if (inodes.getCount()) { - const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId(); - new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, is_library_node); - } - else { - new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, is_library_node); + Object *ob = add_object(sce, OB_CAMERA); + Camera *cam = uid_camera_map[cam_uid]; + Camera *old_cam = (Camera*)ob->data; + ob->data = cam; + old_cam->id.us--; + if (old_cam->id.us == 0) + free_libblock(&G.main->camera, old_cam); + return ob; +} + +Object* DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Scene *sce) +{ + const COLLADAFW::UniqueId& lamp_uid = lamp->getInstanciatedObjectId(); + if (uid_lamp_map.find(lamp_uid) == uid_lamp_map.end()) { + fprintf(stderr, "Couldn't find lamp by UID. \n"); + return NULL; + } + Object *ob = add_object(sce, OB_LAMP); + Lamp *la = uid_lamp_map[lamp_uid]; + Lamp *old_lamp = (Lamp*)ob->data; + ob->data = la; + old_lamp->id.us--; + if (old_lamp->id.us == 0) + free_libblock(&G.main->lamp, old_lamp); + return ob; +} + +Object* DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Node *source_node, COLLADAFW::Node *instance_node, Scene *sce, bool is_library_node) +{ + Object *obn = copy_object(source_ob); + obn->recalc |= OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME; + scene_add_base(sce, obn); + + if (instance_node) { + anim_importer.read_node_transform(instance_node, obn); + // if we also have a source_node (always ;), take its + // transformation matrix and apply it to the newly instantiated + // object to account for node hierarchy transforms in + // .dae + if(source_node) { + COLLADABU::Math::Matrix4 mat4 = source_node->getTransformationMatrix(); + COLLADABU::Math::Matrix4 bmat4 = mat4.transpose(); // transpose to get blender row-major order + float mat[4][4]; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + mat[i][j] = bmat4[i][j]; } - bc_set_parent(new_child, obn, mContext, true); - - if (is_library_node) - libnode_ob.push_back(new_child); } + // calc new matrix and apply + mul_m4_m4m4(obn->obmat, mat, obn->obmat); + object_apply_mat4(obn, obn->obmat, 0, 0); } - - return obn; } - - void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) - { - Object *ob = NULL; - bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - - if (is_joint) { - armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par); - } - else { - COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); - COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras(); - COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights(); - COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers(); - COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes(); - int geom_done = 0; - int camera_done = 0; - int lamp_done = 0; - int controller_done = 0; - int inst_done = 0; - - // XXX linking object with the first <instance_geometry>, though a node may have more of them... - // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure... - // <instance_geometry> - while (geom_done < geom.getCount()) { - ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map, - material_texture_mapping_map); - ++geom_done; - } - while (camera_done < camera.getCount()) { - ob = create_camera_object(camera[camera_done], sce); - ++camera_done; - } - while (lamp_done < lamp.getCount()) { - ob = create_lamp_object(lamp[lamp_done], sce); - ++lamp_done; - } - while (controller_done < controller.getCount()) { - COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done]; - ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map); - ++controller_done; - } - // XXX instance_node is not supported yet - while (inst_done < inst_node.getCount()) { - const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId(); - if (object_map.find(node_id) == object_map.end()) { - fprintf(stderr, "Cannot find node to instanciate.\n"); - ob = NULL; - } - else { - Object *source_ob = object_map[node_id]; - COLLADAFW::Node *source_node = node_map[node_id]; + else { + anim_importer.read_node_transform(source_node, obn); + } - ob = create_instance_node(source_ob, source_node, node, sce, is_library_node); - } - ++inst_done; + DAG_scene_sort(CTX_data_main(mContext), sce); + DAG_ids_flush_update(CTX_data_main(mContext), 0); + + COLLADAFW::NodePointerArray &children = source_node->getChildNodes(); + if (children.getCount()) { + for (unsigned int i = 0; i < children.getCount(); i++) { + COLLADAFW::Node *child_node = children[i]; + const COLLADAFW::UniqueId& child_id = child_node->getUniqueId(); + if (object_map.find(child_id) == object_map.end()) + continue; + COLLADAFW::InstanceNodePointerArray &inodes = child_node->getInstanceNodes(); + Object *new_child = NULL; + if (inodes.getCount()) { // \todo loop through instance nodes + const COLLADAFW::UniqueId& id = inodes[0]->getInstanciatedObjectId(); + new_child = create_instance_node(object_map[id], node_map[id], child_node, sce, is_library_node); } - // if node is empty - create empty object - // XXX empty node may not mean it is empty object, not sure about this - if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { - ob = add_object(sce, OB_EMPTY); + else { + new_child = create_instance_node(object_map[child_id], child_node, NULL, sce, is_library_node); } - - // check if object is not NULL - if (!ob) return; - - rename_id(&ob->id, (char*)node->getOriginalId().c_str()); - - object_map[node->getUniqueId()] = ob; - node_map[node->getUniqueId()] = node; + bc_set_parent(new_child, obn, mContext, true); if (is_library_node) - libnode_ob.push_back(ob); + libnode_ob.push_back(new_child); } + } - anim_importer.read_node_transform(node, ob); + // when we have an instance_node, don't return the object, because otherwise + // its correct location gets overwritten in write_node(). Fixes bug #26012. + if(instance_node) return NULL; + else return obn; +} - if (!is_joint) { - // if par was given make this object child of the previous - if (par && ob) - bc_set_parent(ob, par, mContext); +void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node) +{ + Object *ob = NULL; + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + + if (is_joint) { + armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par); + } + else { + COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); + COLLADAFW::InstanceCameraPointerArray &camera = node->getInstanceCameras(); + COLLADAFW::InstanceLightPointerArray &lamp = node->getInstanceLights(); + COLLADAFW::InstanceControllerPointerArray &controller = node->getInstanceControllers(); + COLLADAFW::InstanceNodePointerArray &inst_node = node->getInstanceNodes(); + int geom_done = 0; + int camera_done = 0; + int lamp_done = 0; + int controller_done = 0; + int inst_done = 0; + + // XXX linking object with the first <instance_geometry>, though a node may have more of them... + // maybe join multiple <instance_...> meshes into 1, and link object with it? not sure... + // <instance_geometry> + while (geom_done < geom.getCount()) { + ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map, + material_texture_mapping_map); + ++geom_done; + } + while (camera_done < camera.getCount()) { + ob = create_camera_object(camera[camera_done], sce); + ++camera_done; + } + while (lamp_done < lamp.getCount()) { + ob = create_lamp_object(lamp[lamp_done], sce); + ++lamp_done; } + while (controller_done < controller.getCount()) { + COLLADAFW::InstanceGeometry *geom = (COLLADAFW::InstanceGeometry*)controller[controller_done]; + ob = mesh_importer.create_mesh_object(node, geom, true, uid_material_map, material_texture_mapping_map); + ++controller_done; + } + // XXX instance_node is not supported yet + while (inst_done < inst_node.getCount()) { + const COLLADAFW::UniqueId& node_id = inst_node[inst_done]->getInstanciatedObjectId(); + if (object_map.find(node_id) == object_map.end()) { + fprintf(stderr, "Cannot find node to instanciate.\n"); + ob = NULL; + } + else { + Object *source_ob = object_map[node_id]; + COLLADAFW::Node *source_node = node_map[node_id]; - // if node has child nodes write them - COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); - for (unsigned int i = 0; i < child_nodes.getCount(); i++) { - write_node(child_nodes[i], node, sce, ob, is_library_node); + ob = create_instance_node(source_ob, source_node, node, sce, is_library_node); + } + ++inst_done; } - } + // if node is empty - create empty object + // XXX empty node may not mean it is empty object, not sure about this + if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) { + ob = add_object(sce, OB_EMPTY); + } + + // check if object is not NULL + if (!ob) return; + + rename_id(&ob->id, (char*)node->getOriginalId().c_str()); - /** When this method is called, the writer must write the entire visual scene. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) - { - if(mImportStage!=General) - return true; - - // this method called on post process after writeGeometry, writeMaterial, etc. + object_map[node->getUniqueId()] = ob; + node_map[node->getUniqueId()] = node; - // for each <node> in <visual_scene>: - // create an Object - // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh + if (is_library_node) + libnode_ob.push_back(ob); + } - // update: since we cannot link a Mesh with Object in - // writeGeometry because <geometry> does not reference <node>, - // we link Objects with Meshes here + anim_importer.read_node_transform(node, ob); // overwrites location set earlier - vscenes.push_back(visualScene); - - return true; + if (!is_joint) { + // if par was given make this object child of the previous + if (par && ob) + bc_set_parent(ob, par, mContext); } - /** When this method is called, the writer must handle all nodes contained in the - library nodes. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) - { - if(mImportStage!=General) - return true; - - Scene *sce = CTX_data_scene(mContext); + // if node has child nodes write them + COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); + for (unsigned int i = 0; i < child_nodes.getCount(); i++) { + write_node(child_nodes[i], node, sce, ob, is_library_node); + } +} - const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes(); +/** When this method is called, the writer must write the entire visual scene. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeVisualScene ( const COLLADAFW::VisualScene* visualScene ) +{ + if(mImportStage!=General) + return true; + + // this method called on post process after writeGeometry, writeMaterial, etc. - for (unsigned int i = 0; i < nodes.getCount(); i++) { - write_node(nodes[i], NULL, sce, NULL, true); - } + // for each <node> in <visual_scene>: + // create an Object + // if Mesh (previously created in writeGeometry) to which <node> corresponds exists, link Object with that mesh + + // update: since we cannot link a Mesh with Object in + // writeGeometry because <geometry> does not reference <node>, + // we link Objects with Meshes here + vscenes.push_back(visualScene); + + return true; +} + +/** When this method is called, the writer must handle all nodes contained in the + library nodes. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeLibraryNodes ( const COLLADAFW::LibraryNodes* libraryNodes ) +{ + if(mImportStage!=General) return true; + + Scene *sce = CTX_data_scene(mContext); + + const COLLADAFW::NodePointerArray& nodes = libraryNodes->getNodes(); + + for (unsigned int i = 0; i < nodes.getCount(); i++) { + write_node(nodes[i], NULL, sce, NULL, true); } - /** When this method is called, the writer must write the geometry. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeGeometry ( const COLLADAFW::Geometry* geom ) - { - if(mImportStage!=General) - return true; - - return mesh_importer.write_geometry(geom); - } - - /** When this method is called, the writer must write the material. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeMaterial( const COLLADAFW::Material* cmat ) - { - if(mImportStage!=General) - return true; - - const std::string& str_mat_id = cmat->getOriginalId(); - Material *ma = add_material((char*)str_mat_id.c_str()); - - this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; - this->uid_material_map[cmat->getUniqueId()] = ma; - + return true; +} + +/** When this method is called, the writer must write the geometry. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeGeometry ( const COLLADAFW::Geometry* geom ) +{ + if(mImportStage!=General) return true; - } - - // create mtex, create texture, set texture image - MTex* DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma, - int i, TexIndexTextureArrayMap &texindex_texarray_map) - { - COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray(); - COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()]; - - const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage(); - - if (uid_image_map.find(ima_uid) == uid_image_map.end()) { - fprintf(stderr, "Couldn't find an image by UID.\n"); - return NULL; - } - ma->mtex[i] = add_mtex(); - ma->mtex[i]->texco = TEXCO_UV; - ma->mtex[i]->tex = add_texture("Texture"); - ma->mtex[i]->tex->type = TEX_IMAGE; - ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA; - ma->mtex[i]->tex->ima = uid_image_map[ima_uid]; + return mesh_importer.write_geometry(geom); +} + +/** When this method is called, the writer must write the material. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeMaterial( const COLLADAFW::Material* cmat ) +{ + if(mImportStage!=General) + return true; - texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]); + const std::string& str_mat_id = cmat->getOriginalId(); + Material *ma = add_material((char*)str_mat_id.c_str()); + + this->uid_effect_map[cmat->getInstantiatedEffect()] = ma; + this->uid_material_map[cmat->getUniqueId()] = ma; + + return true; +} + +// create mtex, create texture, set texture image +MTex* DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::Texture &ctex, Material *ma, + int i, TexIndexTextureArrayMap &texindex_texarray_map) +{ + COLLADAFW::SamplerPointerArray& samp_array = ef->getSamplerPointerArray(); + COLLADAFW::Sampler *sampler = samp_array[ctex.getSamplerId()]; - return ma->mtex[i]; + const COLLADAFW::UniqueId& ima_uid = sampler->getSourceImage(); + + if (uid_image_map.find(ima_uid) == uid_image_map.end()) { + fprintf(stderr, "Couldn't find an image by UID.\n"); + return NULL; } - void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma) - { - COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType(); - - // blinn - if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) { - ma->spec_shader = MA_SPEC_BLINN; - ma->spec = ef->getShininess().getFloatValue(); - } - // phong - else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) { - ma->spec_shader = MA_SPEC_PHONG; - ma->har = ef->getShininess().getFloatValue(); - } - // lambert - else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) { - ma->diff_shader = MA_DIFF_LAMBERT; - } - // default - lambert - else { - ma->diff_shader = MA_DIFF_LAMBERT; - fprintf(stderr, "Current shader type is not supported.\n"); - } - // reflectivity - ma->ray_mirror = ef->getReflectivity().getFloatValue(); - // index of refraction - ma->ang = ef->getIndexOfRefraction().getFloatValue(); - - int i = 0; - COLLADAFW::Color col; - MTex *mtex = NULL; - TexIndexTextureArrayMap texindex_texarray_map; - - // DIFFUSE - // color - if (ef->getDiffuse().isColor()) { - col = ef->getDiffuse().getColor(); - ma->r = col.getRed(); - ma->g = col.getGreen(); - ma->b = col.getBlue(); - } - // texture - else if (ef->getDiffuse().isTexture()) { - COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) { - mtex->mapto = MAP_COL; - ma->texact = (int)i; - i++; - } - } - // AMBIENT - // color - if (ef->getAmbient().isColor()) { - col = ef->getAmbient().getColor(); - ma->ambr = col.getRed(); - ma->ambg = col.getGreen(); - ma->ambb = col.getBlue(); - } - // texture - else if (ef->getAmbient().isTexture()) { - COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) { - mtex->mapto = MAP_AMB; - i++; - } - } - // SPECULAR - // color - if (ef->getSpecular().isColor()) { - col = ef->getSpecular().getColor(); - ma->specr = col.getRed(); - ma->specg = col.getGreen(); - ma->specb = col.getBlue(); - } - // texture - else if (ef->getSpecular().isTexture()) { - COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) { - mtex->mapto = MAP_SPEC; - i++; - } + ma->mtex[i] = add_mtex(); + ma->mtex[i]->texco = TEXCO_UV; + ma->mtex[i]->tex = add_texture("Texture"); + ma->mtex[i]->tex->type = TEX_IMAGE; + ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA; + ma->mtex[i]->tex->ima = uid_image_map[ima_uid]; + + texindex_texarray_map[ctex.getTextureMapId()].push_back(ma->mtex[i]); + + return ma->mtex[i]; +} + +void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Material *ma) +{ + COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType(); + + // blinn + if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) { + ma->spec_shader = MA_SPEC_BLINN; + ma->spec = ef->getShininess().getFloatValue(); + } + // phong + else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) { + ma->spec_shader = MA_SPEC_PHONG; + ma->har = ef->getShininess().getFloatValue(); + } + // lambert + else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) { + ma->diff_shader = MA_DIFF_LAMBERT; + } + // default - lambert + else { + ma->diff_shader = MA_DIFF_LAMBERT; + fprintf(stderr, "Current shader type is not supported, default to lambert.\n"); + } + // reflectivity + ma->ray_mirror = ef->getReflectivity().getFloatValue(); + // index of refraction + ma->ang = ef->getIndexOfRefraction().getFloatValue(); + + int i = 0; + COLLADAFW::Color col; + MTex *mtex = NULL; + TexIndexTextureArrayMap texindex_texarray_map; + + // DIFFUSE + // color + if (ef->getDiffuse().isColor()) { + col = ef->getDiffuse().getColor(); + ma->r = col.getRed(); + ma->g = col.getGreen(); + ma->b = col.getBlue(); + } + // texture + else if (ef->getDiffuse().isTexture()) { + COLLADAFW::Texture ctex = ef->getDiffuse().getTexture(); + mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); + if (mtex != NULL) { + mtex->mapto = MAP_COL; + ma->texact = (int)i; + i++; } - // REFLECTIVE - // color - if (ef->getReflective().isColor()) { - col = ef->getReflective().getColor(); - ma->mirr = col.getRed(); - ma->mirg = col.getGreen(); - ma->mirb = col.getBlue(); + } + // AMBIENT + // color + if (ef->getAmbient().isColor()) { + col = ef->getAmbient().getColor(); + ma->ambr = col.getRed(); + ma->ambg = col.getGreen(); + ma->ambb = col.getBlue(); + } + // texture + else if (ef->getAmbient().isTexture()) { + COLLADAFW::Texture ctex = ef->getAmbient().getTexture(); + mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); + if (mtex != NULL) { + mtex->mapto = MAP_AMB; + i++; } - // texture - else if (ef->getReflective().isTexture()) { - COLLADAFW::Texture ctex = ef->getReflective().getTexture(); - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) { - mtex->mapto = MAP_REF; - i++; - } + } + // SPECULAR + // color + if (ef->getSpecular().isColor()) { + col = ef->getSpecular().getColor(); + ma->specr = col.getRed(); + ma->specg = col.getGreen(); + ma->specb = col.getBlue(); + } + // texture + else if (ef->getSpecular().isTexture()) { + COLLADAFW::Texture ctex = ef->getSpecular().getTexture(); + mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); + if (mtex != NULL) { + mtex->mapto = MAP_SPEC; + i++; } - // EMISSION - // color - if (ef->getEmission().isColor()) { - // XXX there is no emission color in blender - // but I am not sure + } + // REFLECTIVE + // color + if (ef->getReflective().isColor()) { + col = ef->getReflective().getColor(); + ma->mirr = col.getRed(); + ma->mirg = col.getGreen(); + ma->mirb = col.getBlue(); + } + // texture + else if (ef->getReflective().isTexture()) { + COLLADAFW::Texture ctex = ef->getReflective().getTexture(); + mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); + if (mtex != NULL) { + mtex->mapto = MAP_REF; + i++; } - // texture - else if (ef->getEmission().isTexture()) { - COLLADAFW::Texture ctex = ef->getEmission().getTexture(); - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) { - mtex->mapto = MAP_EMIT; - i++; - } + } + // EMISSION + // color + if (ef->getEmission().isColor()) { + // XXX there is no emission color in blender + // but I am not sure + } + // texture + else if (ef->getEmission().isTexture()) { + COLLADAFW::Texture ctex = ef->getEmission().getTexture(); + mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); + if (mtex != NULL) { + mtex->mapto = MAP_EMIT; + i++; } - // TRANSPARENT - // color - // if (ef->getOpacity().isColor()) { + } + // TRANSPARENT + // color +// if (ef->getOpacity().isColor()) { // // XXX don't know what to do here // } // // texture @@ -678,323 +684,401 @@ private: // if (mtex != NULL) mtex->mapto = MAP_ALPHA; // } // } - material_texture_mapping_map[ma] = texindex_texarray_map; + material_texture_mapping_map[ma] = texindex_texarray_map; +} + +/** When this method is called, the writer must write the effect. + @return The writer should return true, if writing succeeded, false otherwise.*/ + +bool DocumentImporter::writeEffect( const COLLADAFW::Effect* effect ) +{ + if(mImportStage!=General) + return true; + + const COLLADAFW::UniqueId& uid = effect->getUniqueId(); + if (uid_effect_map.find(uid) == uid_effect_map.end()) { + fprintf(stderr, "Couldn't find a material by UID.\n"); + return true; } - /** When this method is called, the writer must write the effect. - @return The writer should return true, if writing succeeded, false otherwise.*/ + Material *ma = uid_effect_map[uid]; - bool DocumentImporter::writeEffect( const COLLADAFW::Effect* effect ) - { - if(mImportStage!=General) - return true; - - const COLLADAFW::UniqueId& uid = effect->getUniqueId(); - if (uid_effect_map.find(uid) == uid_effect_map.end()) { - fprintf(stderr, "Couldn't find a material by UID.\n"); - return true; - } - - Material *ma = uid_effect_map[uid]; - - COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects(); - if (common_efs.getCount() < 1) { - fprintf(stderr, "Couldn't find <profile_COMMON>.\n"); - return true; - } - // XXX TODO: Take all <profile_common>s - // Currently only first <profile_common> is supported - COLLADAFW::EffectCommon *ef = common_efs[0]; - write_profile_COMMON(ef, ma); - + COLLADAFW::CommonEffectPointerArray common_efs = effect->getCommonEffects(); + if (common_efs.getCount() < 1) { + fprintf(stderr, "Couldn't find <profile_COMMON>.\n"); return true; } + // XXX TODO: Take all <profile_common>s + // Currently only first <profile_common> is supported + COLLADAFW::EffectCommon *ef = common_efs[0]; + write_profile_COMMON(ef, ma); - - /** When this method is called, the writer must write the camera. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeCamera( const COLLADAFW::Camera* camera ) - { - if(mImportStage!=General) - return true; - - Camera *cam = NULL; - std::string cam_id, cam_name; - - cam_id = camera->getOriginalId(); - cam_name = camera->getName(); - if (cam_name.size()) cam = (Camera*)add_camera((char*)cam_name.c_str()); - else cam = (Camera*)add_camera((char*)cam_id.c_str()); + return true; +} + + +/** When this method is called, the writer must write the camera. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeCamera( const COLLADAFW::Camera* camera ) +{ + if(mImportStage!=General) + return true; - if (!cam) { - fprintf(stderr, "Cannot create camera. \n"); - return true; + Camera *cam = NULL; + std::string cam_id, cam_name; + + cam_id = camera->getOriginalId(); + cam_name = camera->getName(); + if (cam_name.size()) cam = (Camera*)add_camera((char*)cam_name.c_str()); + else cam = (Camera*)add_camera((char*)cam_id.c_str()); + + if (!cam) { + fprintf(stderr, "Cannot create camera. \n"); + return true; + } + cam->clipsta = camera->getNearClippingPlane().getValue(); + cam->clipend = camera->getFarClippingPlane().getValue(); + + COLLADAFW::Camera::CameraType type = camera->getCameraType(); + switch(type) { + case COLLADAFW::Camera::ORTHOGRAPHIC: + { + cam->type = CAM_ORTHO; } - cam->clipsta = camera->getNearClippingPlane().getValue(); - cam->clipend = camera->getFarClippingPlane().getValue(); - - COLLADAFW::Camera::CameraType type = camera->getCameraType(); - switch(type) { - case COLLADAFW::Camera::ORTHOGRAPHIC: - { - cam->type = CAM_ORTHO; - } - break; - case COLLADAFW::Camera::PERSPECTIVE: - { - cam->type = CAM_PERSP; - } - break; - case COLLADAFW::Camera::UNDEFINED_CAMERATYPE: - { - fprintf(stderr, "Current camera type is not supported. \n"); - cam->type = CAM_PERSP; - } - break; + break; + case COLLADAFW::Camera::PERSPECTIVE: + { + cam->type = CAM_PERSP; } - - switch(camera->getDescriptionType()) { - case COLLADAFW::Camera::ASPECTRATIO_AND_Y: - { - switch(cam->type) { - case CAM_ORTHO: - { - double ymag = camera->getYMag().getValue(); - double aspect = camera->getAspectRatio().getValue(); - double xmag = aspect*ymag; - cam->ortho_scale = (float)xmag; - } - break; - case CAM_PERSP: - default: - { - double yfov = camera->getYFov().getValue(); - double aspect = camera->getAspectRatio().getValue(); - double xfov = aspect*yfov; - // xfov is in degrees, cam->lens is in millimiters - cam->lens = angle_to_lens((float)xfov*(M_PI/180.0f)); - } - break; - } + break; + case COLLADAFW::Camera::UNDEFINED_CAMERATYPE: + { + fprintf(stderr, "Current camera type is not supported. \n"); + cam->type = CAM_PERSP; + } + break; + } + + switch(camera->getDescriptionType()) { + case COLLADAFW::Camera::ASPECTRATIO_AND_Y: + { + switch(cam->type) { + case CAM_ORTHO: + { + double ymag = camera->getYMag().getValue(); + double aspect = camera->getAspectRatio().getValue(); + double xmag = aspect*ymag; + cam->ortho_scale = (float)xmag; + } + break; + case CAM_PERSP: + default: + { + double yfov = camera->getYFov().getValue(); + double aspect = camera->getAspectRatio().getValue(); + double xfov = aspect*yfov; + // xfov is in degrees, cam->lens is in millimiters + cam->lens = angle_to_lens((float)xfov*(M_PI/180.0f)); + } + break; } - break; - /* XXX correct way to do following four is probably to get also render - size and determine proper settings from that somehow */ - case COLLADAFW::Camera::ASPECTRATIO_AND_X: - case COLLADAFW::Camera::SINGLE_X: - case COLLADAFW::Camera::X_AND_Y: - { - switch(cam->type) { - case CAM_ORTHO: - cam->ortho_scale = (float)camera->getXMag().getValue(); - break; - case CAM_PERSP: - default: - { - double x = camera->getXFov().getValue(); - // x is in degrees, cam->lens is in millimiters - cam->lens = angle_to_lens((float)x*(M_PI/180.0f)); - } - break; - } + } + break; + /* XXX correct way to do following four is probably to get also render + size and determine proper settings from that somehow */ + case COLLADAFW::Camera::ASPECTRATIO_AND_X: + case COLLADAFW::Camera::SINGLE_X: + case COLLADAFW::Camera::X_AND_Y: + { + switch(cam->type) { + case CAM_ORTHO: + cam->ortho_scale = (float)camera->getXMag().getValue(); + break; + case CAM_PERSP: + default: + { + double x = camera->getXFov().getValue(); + // x is in degrees, cam->lens is in millimiters + cam->lens = angle_to_lens((float)x*(M_PI/180.0f)); + } + break; } - break; - case COLLADAFW::Camera::SINGLE_Y: - { - switch(cam->type) { - case CAM_ORTHO: - cam->ortho_scale = (float)camera->getYMag().getValue(); - break; - case CAM_PERSP: - default: - { - double yfov = camera->getYFov().getValue(); - // yfov is in degrees, cam->lens is in millimiters - cam->lens = angle_to_lens((float)yfov*(M_PI/180.0f)); - } - break; - } + } + break; + case COLLADAFW::Camera::SINGLE_Y: + { + switch(cam->type) { + case CAM_ORTHO: + cam->ortho_scale = (float)camera->getYMag().getValue(); + break; + case CAM_PERSP: + default: + { + double yfov = camera->getYFov().getValue(); + // yfov is in degrees, cam->lens is in millimiters + cam->lens = angle_to_lens((float)yfov*(M_PI/180.0f)); + } + break; } - break; - case COLLADAFW::Camera::UNDEFINED: - // read nothing, use blender defaults. - break; } + break; + case COLLADAFW::Camera::UNDEFINED: + // read nothing, use blender defaults. + break; + } + + this->uid_camera_map[camera->getUniqueId()] = cam; + // XXX import camera options + return true; +} + +/** When this method is called, the writer must write the image. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeImage( const COLLADAFW::Image* image ) +{ + if(mImportStage!=General) + return true; - this->uid_camera_map[camera->getUniqueId()] = cam; - // XXX import camera options + // XXX maybe it is necessary to check if the path is absolute or relative + const std::string& filepath = image->getImageURI().toNativePath(); + const char *filename = (const char*)mFilename.c_str(); + char dir[FILE_MAX]; + char full_path[FILE_MAX]; + + BLI_split_dirfile(filename, dir, NULL); + BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str()); + Image *ima = BKE_add_image_file(full_path); + if (!ima) { + fprintf(stderr, "Cannot create image. \n"); return true; } + this->uid_image_map[image->getUniqueId()] = ima; + + return true; +} + +/** When this method is called, the writer must write the light. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) +{ + if(mImportStage!=General) + return true; - /** When this method is called, the writer must write the image. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeImage( const COLLADAFW::Image* image ) - { - if(mImportStage!=General) - return true; - - // XXX maybe it is necessary to check if the path is absolute or relative - const std::string& filepath = image->getImageURI().toNativePath(); - const char *filename = (const char*)mFilename.c_str(); - char dir[FILE_MAX]; - char full_path[FILE_MAX]; - - BLI_split_dirfile(filename, dir, NULL); - BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str()); - Image *ima = BKE_add_image_file(full_path); - if (!ima) { - fprintf(stderr, "Cannot create image. \n"); - return true; - } - this->uid_image_map[image->getUniqueId()] = ima; - + Lamp *lamp = NULL; + std::string la_id, la_name; + + TagsMap::iterator etit; + ExtraTags *et = 0; + etit = uid_tags_map.find(light->getUniqueId().toAscii()); + if(etit != uid_tags_map.end()) + et = etit->second; + + la_id = light->getOriginalId(); + la_name = light->getName(); + if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str()); + else lamp = (Lamp*)add_lamp((char*)la_id.c_str()); + + if (!lamp) { + fprintf(stderr, "Cannot create lamp. \n"); return true; } - /** When this method is called, the writer must write the light. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) - { - if(mImportStage!=General) - return true; - - Lamp *lamp = NULL; - std::string la_id, la_name; - - la_id = light->getOriginalId(); - la_name = light->getName(); - if (la_name.size()) lamp = (Lamp*)add_lamp((char*)la_name.c_str()); - else lamp = (Lamp*)add_lamp((char*)la_id.c_str()); - - if (!lamp) { - fprintf(stderr, "Cannot create lamp. \n"); - return true; - } - if (light->getColor().isValid()) { - COLLADAFW::Color col = light->getColor(); - lamp->r = col.getRed(); - lamp->g = col.getGreen(); - lamp->b = col.getBlue(); - } + // if we find an ExtraTags for this, use that instead. + if(et && et->isProfile("blender")) { + et->setData("type", &(lamp->type)); + et->setData("flag", &(lamp->flag)); + et->setData("mode", &(lamp->mode)); + et->setData("gamma", &(lamp->k)); + et->setData("red", &(lamp->r)); + et->setData("green", &(lamp->g)); + et->setData("blue", &(lamp->b)); + et->setData("shadow_r", &(lamp->shdwr)); + et->setData("shadow_g", &(lamp->shdwg)); + et->setData("shadow_b", &(lamp->shdwb)); + et->setData("energy", &(lamp->energy)); + et->setData("dist", &(lamp->dist)); + et->setData("spotsize", &(lamp->spotsize)); + et->setData("spotblend", &(lamp->spotblend)); + et->setData("halo_intensity", &(lamp->haint)); + et->setData("att1", &(lamp->att1)); + et->setData("att2", &(lamp->att2)); + et->setData("falloff_type", &(lamp->falloff_type)); + et->setData("clipsta", &(lamp->clipsta)); + et->setData("clipend", &(lamp->clipend)); + et->setData("shadspotsize", &(lamp->shadspotsize)); + et->setData("bias", &(lamp->bias)); + et->setData("soft", &(lamp->soft)); + et->setData("compressthresh", &(lamp->compressthresh)); + et->setData("bufsize", &(lamp->bufsize)); + et->setData("samp", &(lamp->samp)); + et->setData("buffers", &(lamp->buffers)); + et->setData("filtertype", &(lamp->filtertype)); + et->setData("bufflag", &(lamp->bufflag)); + et->setData("buftype", &(lamp->buftype)); + et->setData("ray_samp", &(lamp->ray_samp)); + et->setData("ray_sampy", &(lamp->ray_sampy)); + et->setData("ray_sampz", &(lamp->ray_sampz)); + et->setData("ray_samp_type", &(lamp->ray_samp_type)); + et->setData("area_shape", &(lamp->area_shape)); + et->setData("area_size", &(lamp->area_size)); + et->setData("area_sizey", &(lamp->area_sizey)); + et->setData("area_sizez", &(lamp->area_sizez)); + et->setData("adapt_thresh", &(lamp->adapt_thresh)); + et->setData("ray_samp_method", &(lamp->ray_samp_method)); + et->setData("shadhalostep", &(lamp->shadhalostep)); + et->setData("sun_effect_type", &(lamp->shadhalostep)); + et->setData("skyblendtype", &(lamp->skyblendtype)); + et->setData("horizon_brightness", &(lamp->horizon_brightness)); + et->setData("spread", &(lamp->spread)); + et->setData("sun_brightness", &(lamp->sun_brightness)); + et->setData("sun_size", &(lamp->sun_size)); + et->setData("backscattered_light", &(lamp->backscattered_light)); + et->setData("sun_intensity", &(lamp->sun_intensity)); + et->setData("atm_turbidity", &(lamp->atm_turbidity)); + et->setData("atm_extinction_factor", &(lamp->atm_extinction_factor)); + et->setData("atm_distance_factor", &(lamp->atm_distance_factor)); + et->setData("skyblendfac", &(lamp->skyblendfac)); + et->setData("sky_exposure", &(lamp->sky_exposure)); + et->setData("sky_colorspace", &(lamp->sky_colorspace)); + } + else { float constatt = light->getConstantAttenuation().getValue(); float linatt = light->getLinearAttenuation().getValue(); float quadatt = light->getQuadraticAttenuation().getValue(); float d = 25.0f; float att1 = 0.0f; float att2 = 0.0f; - - float e = 1.0f/constatt; - - /* NOTE: We assume for now that inv square is used for quadratic light - * and inv linear for linear light. Exported blender lin/quad weighted - * most likely will result in wrong import. */ - /* quadratic light */ + float e = 1.0f; + + if (light->getColor().isValid()) { + COLLADAFW::Color col = light->getColor(); + lamp->r = col.getRed(); + lamp->g = col.getGreen(); + lamp->b = col.getBlue(); + } + if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) { - //quadatt = att2/(d*d*(e*2)); - float invquadatt = 1.0f/quadatt; - float d2 = invquadatt / (2 * e); - d = sqrtf(d2); + att2 = quadatt; + d = (1.0f/quadatt) * 2; } // linear light else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) { - //linatt = att1/(d*e); - float invlinatt = 1.0f/linatt; - d = invlinatt / e; + att1 = linatt; + d = (1.0f/linatt) * 2; + } else if (IS_EQ(constatt, 1.0f)) { + att1 = 1.0f; } else { - printf("no linear nor quad light, using defaults for attenuation, import will be incorrect: Lamp %s\n", lamp->id.name); - att2 = 1.0f; + // assuming point light (const att = 1.0); + att1 = 1.0f; } - lamp->dist = d; + d *= ( 1.0f / unit_converter.getLinearMeter()); + lamp->energy = e; - + lamp->dist = d; + COLLADAFW::Light::LightType type = light->getLightType(); switch(type) { - case COLLADAFW::Light::AMBIENT_LIGHT: - { - lamp->type = LA_HEMI; - } - break; - case COLLADAFW::Light::SPOT_LIGHT: - { - lamp->type = LA_SPOT; - lamp->falloff_type = LA_FALLOFF_INVSQUARE; - lamp->att1 = att1; - lamp->att2 = att2; - lamp->spotsize = light->getFallOffAngle().getValue(); - lamp->spotblend = light->getFallOffExponent().getValue(); - } - break; - case COLLADAFW::Light::DIRECTIONAL_LIGHT: - { - lamp->type = LA_SUN; - } - break; - case COLLADAFW::Light::POINT_LIGHT: - { - lamp->type = LA_LOCAL; - lamp->falloff_type = LA_FALLOFF_INVSQUARE; - lamp->att1 = att1; - lamp->att2 = att2; - } - break; - case COLLADAFW::Light::UNDEFINED: - { - fprintf(stderr, "Current lamp type is not supported. \n"); - lamp->type = LA_LOCAL; - } - break; + case COLLADAFW::Light::AMBIENT_LIGHT: + { + lamp->type = LA_HEMI; + } + break; + case COLLADAFW::Light::SPOT_LIGHT: + { + lamp->type = LA_SPOT; + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + lamp->att1 = att1; + lamp->att2 = att2; + lamp->spotsize = light->getFallOffAngle().getValue(); + lamp->spotblend = light->getFallOffExponent().getValue(); + } + break; + case COLLADAFW::Light::DIRECTIONAL_LIGHT: + { + /* our sun is very strong, so pick a smaller energy level */ + lamp->type = LA_SUN; + lamp->mode |= LA_NO_SPEC; + } + break; + case COLLADAFW::Light::POINT_LIGHT: + { + lamp->type = LA_LOCAL; + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + lamp->att1 = att1; + lamp->att2 = att2; + } + break; + case COLLADAFW::Light::UNDEFINED: + { + fprintf(stderr, "Current lamp type is not supported. \n"); + lamp->type = LA_LOCAL; + } + break; } - - this->uid_lamp_map[light->getUniqueId()] = lamp; - return true; - } - - // this function is called only for animations that pass COLLADAFW::validate - bool DocumentImporter::writeAnimation( const COLLADAFW::Animation* anim ) - { - if(mImportStage!=General) - return true; - - // return true; - return anim_importer.write_animation(anim); - } - - // called on post-process stage after writeVisualScenes - bool DocumentImporter::writeAnimationList( const COLLADAFW::AnimationList* animationList ) - { - if(mImportStage!=General) - return true; - - // return true; - return anim_importer.write_animation_list(animationList); - } - - /** When this method is called, the writer must write the skin controller data. - @return The writer should return true, if writing succeeded, false otherwise.*/ - bool DocumentImporter::writeSkinControllerData( const COLLADAFW::SkinControllerData* skin ) - { - return armature_importer.write_skin_controller_data(skin); } - // this is called on postprocess, before writeVisualScenes - bool DocumentImporter::writeController( const COLLADAFW::Controller* controller ) - { - if(mImportStage!=General) - return true; - - return armature_importer.write_controller(controller); - } + this->uid_lamp_map[light->getUniqueId()] = lamp; + return true; +} - bool DocumentImporter::writeFormulas( const COLLADAFW::Formulas* formulas ) - { +// this function is called only for animations that pass COLLADAFW::validate +bool DocumentImporter::writeAnimation( const COLLADAFW::Animation* anim ) +{ + if(mImportStage!=General) return true; - } - - bool DocumentImporter::writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene ) - { + + // return true; + return anim_importer.write_animation(anim); +} + +// called on post-process stage after writeVisualScenes +bool DocumentImporter::writeAnimationList( const COLLADAFW::AnimationList* animationList ) +{ + if(mImportStage!=General) + return true; + + // return true; + return anim_importer.write_animation_list(animationList); +} + +/** When this method is called, the writer must write the skin controller data. + @return The writer should return true, if writing succeeded, false otherwise.*/ +bool DocumentImporter::writeSkinControllerData( const COLLADAFW::SkinControllerData* skin ) +{ + return armature_importer.write_skin_controller_data(skin); +} + +// this is called on postprocess, before writeVisualScenes +bool DocumentImporter::writeController( const COLLADAFW::Controller* controller ) +{ + if(mImportStage!=General) return true; + + return armature_importer.write_controller(controller); +} + +bool DocumentImporter::writeFormulas( const COLLADAFW::Formulas* formulas ) +{ + return true; +} + +bool DocumentImporter::writeKinematicsScene( const COLLADAFW::KinematicsScene* kinematicsScene ) +{ + return true; +} + +ExtraTags* DocumentImporter::getExtraTags(const COLLADAFW::UniqueId &uid) +{ + if(uid_tags_map.find(uid.toAscii())==uid_tags_map.end()) { + return NULL; } - - + return uid_tags_map[uid.toAscii()]; +} + +bool DocumentImporter::addExtraTags( const COLLADAFW::UniqueId &uid, ExtraTags *extra_tags) +{ + uid_tags_map[uid.toAscii()] = extra_tags; + return true; +} |