Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/collada/DocumentImporter.cpp')
-rw-r--r--source/blender/collada/DocumentImporter.cpp252
1 files changed, 186 insertions, 66 deletions
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 084f71e0afc..49db6f033d9 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -54,6 +54,7 @@ extern "C" {
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLI_fileops.h"
#include "BKE_camera.h"
#include "BKE_main.h"
@@ -76,6 +77,9 @@ extern "C" {
#include "MEM_guardedalloc.h"
+#include "WM_api.h"
+#include "WM_types.h"
+
}
#include "ExtraHandler.h"
@@ -96,11 +100,11 @@ extern "C" {
// creates empties for each imported bone on layer 2, for debugging
// #define ARMATURE_TEST
-DocumentImporter::DocumentImporter(bContext *C, const char *filename) :
+DocumentImporter::DocumentImporter(bContext *C, const ImportSettings *import_settings) :
+ import_settings(import_settings),
mImportStage(General),
- mFilename(filename),
mContext(C),
- armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
+ armature_importer(&unit_converter, &mesh_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))
{
@@ -128,7 +132,9 @@ bool DocumentImporter::import()
// deselect all to select new objects
BKE_scene_base_deselect_all(CTX_data_scene(mContext));
- if (!root.loadDocument(mFilename)) {
+ std::string mFilename = std::string(this->import_settings->filepath);
+ const std::string encodedFilename = bc_url_encode(mFilename);
+ if (!root.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 1st pass\n");
return false;
}
@@ -143,7 +149,7 @@ bool DocumentImporter::import()
COLLADASaxFWL::Loader loader2;
COLLADAFW::Root root2(&loader2, this);
- if (!root2.loadDocument(mFilename)) {
+ if (!root2.loadDocument(encodedFilename)) {
fprintf(stderr, "COLLADAFW::Root::loadDocument() returned false on 2nd pass\n");
return false;
}
@@ -151,7 +157,8 @@ bool DocumentImporter::import()
delete ehandler;
- mesh_importer.bmeshConversion();
+ //XXX No longer needed (geometries are now created as bmesh)
+ //mesh_importer.bmeshConversion();
return true;
}
@@ -174,46 +181,68 @@ void DocumentImporter::finish()
{
if (mImportStage != General)
return;
-
+
+ Main *bmain = CTX_data_main(mContext);
+ // TODO: create a new scene except the selected <visual_scene> - use current blender scene for it
+ Scene *sce = CTX_data_scene(mContext);
+
/** 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;
+
+ if (this->import_settings->import_units) {
+
+ 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;
+ }
+ float unit_factor = unit_converter.getLinearMeter();
+ RNA_property_float_set(&unit_settings, scale, unit_factor);
+ fprintf(stdout, "Collada: Adjusting Blender units to Importset units: %f.\n", unit_factor);
+
}
- RNA_property_float_set(&unit_settings, scale, unit_converter.getLinearMeter());
-
- const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
+ // Write nodes to scene
+ const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
for (unsigned int i = 0; i < roots.getCount(); i++) {
- write_node(roots[i], NULL, sce, NULL, false);
+ std::vector<Object *> *objects_done;
+ objects_done = write_node(roots[i], NULL, sce, NULL, false);
+
+ if (!this->import_settings->import_units) {
+ // Match incoming scene with current unit settings
+ bc_match_scale(objects_done, *sce, unit_converter);
+ }
}
+
+ // update scene
+ DAG_relations_tag_update(bmain);
+ WM_event_add_notifier(mContext, NC_OBJECT | ND_TRANSFORM, NULL);
+
}
- mesh_importer.optimize_material_assignments();
+ mesh_importer.optimize_material_assignements();
armature_importer.set_tags_map(this->uid_tags_map);
armature_importer.make_armatures(mContext);
+ armature_importer.make_shape_keys();
+ DAG_relations_tag_update(bmain);
#if 0
armature_importer.fix_animation();
@@ -222,8 +251,9 @@ void DocumentImporter::finish()
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++)
+ for (unsigned int i = 0; i < roots.getCount(); i++) {
translate_anim_recursive(roots[i], NULL, NULL);
+ }
}
if (libnode_ob.size()) {
@@ -246,8 +276,7 @@ void DocumentImporter::finish()
}
libnode_ob.clear();
- DAG_scene_sort(CTX_data_main(mContext), sce);
- DAG_ids_flush_update(CTX_data_main(mContext), 0);
+ DAG_relations_tag_update(bmain);
}
}
@@ -256,7 +285,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
{
// The split in #29246, rootmap must point at actual root when
- // calculating bones in apply_curves_as_matrix.
+ // calculating bones in apply_curves_as_matrix. - actual root is the root node.
// This has to do with inverse bind poses being world space
// (the sources for skinned bones' restposes) and the way
// non-skinning nodes have their "restpose" recursively calculated.
@@ -265,7 +294,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
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;
+ root_map[node->getUniqueId()] = node;
else
root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
}
@@ -282,13 +311,22 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
#endif
unsigned int i;
+
//for (i = 0; i < 4; i++)
// ob =
anim_importer.translate_Animations(node, root_map, object_map, FW_object_map);
- COLLADAFW::NodePointerArray &children = node->getChildNodes();
- for (i = 0; i < children.getCount(); i++) {
- translate_anim_recursive(children[i], node, NULL);
+ if (node->getType() == COLLADAFW::Node::JOINT && par == NULL) {
+ // For Skeletons without root node we have to simulate the
+ // root node here and recursively enter the same function
+ // XXX: maybe this can be made more elegant.
+ translate_anim_recursive(node, node, parob);
+ }
+ else {
+ COLLADAFW::NodePointerArray &children = node->getChildNodes();
+ for (i = 0; i < children.getCount(); i++) {
+ translate_anim_recursive(children[i], node, NULL);
+ }
}
}
@@ -349,7 +387,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
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);
Object *obn = BKE_object_copy(source_ob);
- obn->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
BKE_scene_base_add(sce, obn);
if (instance_node) {
@@ -376,8 +414,7 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
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);
+ /*DAG_relations_tag_update(CTX_data_main(mContext));*/
COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
if (children.getCount()) {
@@ -406,23 +443,50 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
return obn;
}
-void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
+// to create constraints off node <extra> tags. Assumes only constraint data in
+// current <extra> with blender profile.
+void DocumentImporter::create_constraints(ExtraTags *et, Object *ob)
+{
+ if (et && et->isProfile("blender")) {
+ std::string name;
+ short* type = 0;
+ et->setData("type", type);
+ BKE_add_ob_constraint(ob, "Test_con", *type);
+
+ }
+}
+
+std::vector<Object *> *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;
bool read_transform = true;
+ std::string id = node->getOriginalId();
+ std::string name = node->getName();
std::vector<Object *> *objects_done = new std::vector<Object *>();
+ fprintf(stderr,
+ "Writing node id='%s', name='%s'\n",
+ id.c_str(),
+ name.c_str());
+
if (is_joint) {
- if (par) {
- Object *empty = par;
- par = bc_add_object(sce, OB_ARMATURE, NULL);
- bc_set_parent(par, empty->parent, mContext);
- //remove empty : todo
- object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(parent_node->getUniqueId(), par));
+ if (parent_node == NULL) {
+ // A Joint on root level is a skeleton without root node.
+ // Here we add the armature "on the fly":
+ par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
+ objects_done->push_back(par);
+ object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(node->getUniqueId(), par));
+ node_map[node->getUniqueId()] = node;
}
armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
+
+ if (parent_node == NULL) {
+ // for skeletons without root node all has been done above.
+ // Skeletons with root node are handled further down.
+ return objects_done;
+ }
}
else {
COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
@@ -442,13 +506,21 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
while (geom_done < geom.getCount()) {
ob = mesh_importer.create_mesh_object(node, geom[geom_done], false, uid_material_map,
material_texture_mapping_map);
- objects_done->push_back(ob);
+ if (ob == NULL) {
+ fprintf(stderr,
+ "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_mesh.\n",
+ id.c_str(),
+ name.c_str());
+ }
+ else {
+ objects_done->push_back(ob);
+ }
++geom_done;
}
while (camera_done < camera.getCount()) {
ob = create_camera_object(camera[camera_done], sce);
if (ob == NULL) {
- std::string id = node->getOriginalId();
+ std::string id = node->getOriginalId();
std::string name = node->getName();
fprintf(stderr, "<node id=\"%s\", name=\"%s\" >...contains a reference to an unknown instance_camera.\n", id.c_str(), name.c_str());
}
@@ -487,16 +559,25 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
read_transform = false;
}
+
// 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 = bc_add_object(sce, OB_EMPTY, NULL);
+ //Check if Object is armature, by checking if immediate child is a JOINT node.
+ if (is_armature(node)) {
+ ob = bc_add_object(sce, OB_ARMATURE, name.c_str());
+ }
+ else {
+ ob = bc_add_object(sce, OB_EMPTY, NULL);
+ }
objects_done->push_back(ob);
+
}
// XXX: if there're multiple instances, only one is stored
- if (!ob) return;
+ if (!ob) return objects_done;
+
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
ob = *it;
std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
@@ -508,6 +589,9 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
libnode_ob.push_back(ob);
}
+
+ //create_constraints(et,ob);
+
}
for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
@@ -524,9 +608,19 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
}
// if node has child nodes write them
COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+
+ if (objects_done->size() > 0) {
+ ob = *objects_done->begin();
+ }
+ else {
+ ob = NULL;
+ }
+
for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
write_node(child_nodes[i], node, sce, ob, is_library_node);
}
+
+ return objects_done;
}
/** When this method is called, the writer must write the entire visual scene.
@@ -588,7 +682,7 @@ bool DocumentImporter::writeMaterial(const COLLADAFW::Material *cmat)
return true;
const std::string& str_mat_id = cmat->getName().size() ? cmat->getName() : cmat->getOriginalId();
- Material *ma = BKE_material_add((char *)str_mat_id.c_str());
+ Material *ma = BKE_material_add(G.main, (char *)str_mat_id.c_str());
this->uid_effect_map[cmat->getInstantiatedEffect()] = ma;
this->uid_material_map[cmat->getUniqueId()] = ma;
@@ -612,9 +706,8 @@ MTex *DocumentImporter::create_texture(COLLADAFW::EffectCommon *ef, COLLADAFW::T
ma->mtex[i] = add_mtex();
ma->mtex[i]->texco = TEXCO_UV;
- ma->mtex[i]->tex = add_texture("Texture");
+ ma->mtex[i]->tex = add_texture(G.main, "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]);
@@ -745,7 +838,6 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia
mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map);
if (mtex != NULL) {
mtex->mapto = MAP_ALPHA;
- mtex->tex->imaflag |= TEX_USEALPHA;
i++;
ma->spectra = ma->alpha = 0;
ma->mode |= MA_ZTRANSP | MA_TRANSP;
@@ -820,8 +912,8 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera)
cam_id = camera->getOriginalId();
cam_name = camera->getName();
- if (cam_name.size()) cam = (Camera *)BKE_camera_add((char *)cam_name.c_str());
- else cam = (Camera *)BKE_camera_add((char *)cam_id.c_str());
+ if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str());
+ else cam = (Camera *)BKE_camera_add(G.main, (char *)cam_id.c_str());
if (!cam) {
fprintf(stderr, "Cannot create camera.\n");
@@ -933,17 +1025,29 @@ 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();
+ const std::string& imagepath = image->getImageURI().toNativePath();
+
char dir[FILE_MAX];
- char full_path[FILE_MAX];
-
- BLI_split_dir_part(filename, dir, sizeof(dir));
- BLI_join_dirfile(full_path, sizeof(full_path), dir, filepath.c_str());
- Image *ima = BKE_image_load_exists(full_path);
+ char absolute_path[FILE_MAX];
+ const char *workpath;
+
+ BLI_split_dir_part(this->import_settings->filepath, dir, sizeof(dir));
+ BLI_join_dirfile(absolute_path, sizeof(absolute_path), dir, imagepath.c_str());
+ if (BLI_exists(absolute_path)) {
+ workpath = absolute_path;
+ }
+ else {
+ // Maybe imagepath was already absolute ?
+ if (!BLI_exists(imagepath.c_str())) {
+ fprintf(stderr, "Image not found: %s.\n", imagepath.c_str() );
+ return true;
+ }
+ workpath = imagepath.c_str();
+ }
+
+ Image *ima = BKE_image_load_exists(workpath);
if (!ima) {
- fprintf(stderr, "Cannot create image.\n");
+ fprintf(stderr, "Cannot create image: %s\n", workpath);
return true;
}
this->uid_image_map[image->getUniqueId()] = ima;
@@ -961,16 +1065,17 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
Lamp *lamp = NULL;
std::string la_id, la_name;
- TagsMap::iterator etit;
+ ExtraTags *et = getExtraTags(light->getUniqueId());
+ /*TagsMap::iterator etit;
ExtraTags *et = 0;
etit = uid_tags_map.find(light->getUniqueId().toAscii());
if (etit != uid_tags_map.end())
- et = etit->second;
+ et = etit->second;*/
la_id = light->getOriginalId();
la_name = light->getName();
- if (la_name.size()) lamp = (Lamp *)BKE_lamp_add((char *)la_name.c_str());
- else lamp = (Lamp *)BKE_lamp_add((char *)la_id.c_str());
+ if (la_name.size()) lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_name.c_str());
+ else lamp = (Lamp *)BKE_lamp_add(G.main, (char *)la_id.c_str());
if (!lamp) {
fprintf(stderr, "Cannot create lamp.\n");
@@ -1185,3 +1290,18 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e
return true;
}
+bool DocumentImporter::is_armature(COLLADAFW::Node *node)
+{
+ COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+ for (unsigned int i = 0; i < child_nodes.getCount(); i++) {
+ if (child_nodes[i]->getType() == COLLADAFW::Node::JOINT) {
+ return true;
+ }
+ else {
+ continue;
+ }
+ }
+
+ //no child is JOINT
+ return false;
+}