diff options
Diffstat (limited to 'source/blender/collada')
33 files changed, 1087 insertions, 423 deletions
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 3bff20e846b..d4f434d56fd 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -312,12 +312,12 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa if (ob->type == OB_ARMATURE) { ob_name = getObjectBoneName(ob, fcu); BLI_snprintf( - anim_id, - sizeof(anim_id), - "%s_%s.%s", - (char *)translate_id(ob_name).c_str(), - (char *)translate_id(transformName).c_str(), - axis_name); + anim_id, + sizeof(anim_id), + "%s_%s.%s", + (char *)translate_id(ob_name).c_str(), + (char *)translate_id(transformName).c_str(), + axis_name); } else { if (ma) @@ -326,12 +326,12 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa ob_name = id_name(ob); BLI_snprintf( - anim_id, - sizeof(anim_id), - "%s_%s_%s", - (char *)translate_id(ob_name).c_str(), - (char *)getAnimationPathId(fcu).c_str(), - axis_name); + anim_id, + sizeof(anim_id), + "%s_%s_%s", + (char *)translate_id(ob_name).c_str(), + (char *)getAnimationPathId(fcu).c_str(), + axis_name); } openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); @@ -530,7 +530,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_ addSampler(sampler); - std::string target = translate_id(bone_name) + "/transform"; + std::string target = get_joint_id(bone, ob_arm) + "/transform"; addChannel(COLLADABU::URI(empty, sampler_id), target); closeAnimation(); diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 5cd01eff263..bd47ee0214d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -35,8 +35,8 @@ #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_string_utils.h" #include "BLT_translation.h" @@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No mul_m4_m4m4(mat, ipar, temp); } - TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size); + bc_decompose(mat, job->loc, NULL, job->quat, job->size); if (par_job) { job->parent = par_job; diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 4f5cf83f5ca..d2495a8cb9f 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -69,17 +69,21 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce, // write bone nodes bArmature * armature = (bArmature *)ob_arm->data; - ED_armature_to_edit(armature); + bool is_edited = armature->edbo != NULL; - bArmature *arm = (bArmature *)ob_arm->data; - for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) { + if (!is_edited) + ED_armature_to_edit(armature); + + for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) { // start from root bones if (!bone->parent) add_bone_node(bone, ob_arm, sce, se, child_objects); } - ED_armature_from_edit(armature); - ED_armature_edit_free(armature); + if (!is_edited) { + ED_armature_from_edit(armature); + ED_armature_edit_free(armature); + } } void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) @@ -112,7 +116,10 @@ bool ArmatureExporter::add_instance_controller(Object *ob) write_bone_URLs(ins, ob_arm, bone); } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(ins.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); ins.add(); return true; @@ -152,11 +159,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O } #endif -std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm) -{ - return get_joint_id(bone, ob_arm); -} - // parent_mat is armature-space void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se, @@ -257,47 +259,59 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW: //bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); float mat[4][4]; + float bone_rest_mat[4][4]; /* derived from bone->arm_mat */ + float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */ - if (bone->parent) { - // get bone-space matrix from parent pose - /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); - float invpar[4][4]; - invert_m4_m4(invpar, parchan->pose_mat); - mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ - - float invpar[4][4]; - invert_m4_m4(invpar, bone->parent->arm_mat); - mul_m4_m4m4(mat, invpar, bone->arm_mat); + bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat); - } - else { + if (!has_restmat) { + + /* Have no restpose matrix stored, try old style <= Blender 2.78 */ - //copy_m4_m4(mat, pchan->pose_mat); - //pose mat is object space - //New change: export bone->arm_mat - copy_m4_m4(mat, bone->arm_mat); - } + bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true); - // OPEN_SIM_COMPATIBILITY - if (export_settings->open_sim) { - // Remove rotations vs armature from transform - // parent_rest_rot * mat * irest_rot - float temp[4][4]; - copy_m4_m4(temp, bone->arm_mat); - temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; - invert_m4(temp); + if (bone->parent) { + // get bone-space matrix from parent pose + /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name); + float invpar[4][4]; + invert_m4_m4(invpar, parchan->pose_mat); + mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/ + float invpar[4][4]; + bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true); - mul_m4_m4m4(mat, mat, temp); + invert_m4_m4(invpar, parent_rest_mat); + mul_m4_m4m4(mat, invpar, bone_rest_mat); - if (bone->parent) { - copy_m4_m4(temp, bone->parent->arm_mat); + } + else { + copy_m4_m4(mat, bone_rest_mat); + } + + // OPEN_SIM_COMPATIBILITY + if (export_settings->open_sim) { + // Remove rotations vs armature from transform + // parent_rest_rot * mat * irest_rot + float temp[4][4]; + copy_m4_m4(temp, bone_rest_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + invert_m4(temp); + + mul_m4_m4m4(mat, mat, temp); - mul_m4_m4m4(mat, temp, mat); + if (bone->parent) { + copy_m4_m4(temp, parent_rest_mat); + temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; + + mul_m4_m4m4(mat, temp, mat); + } } } + if (this->export_settings->limit_precision) + bc_sanitize_mat(mat, 6); + TransformWriter::add_node_transform(node, mat, NULL); + } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h index 883a6aca847..d271b505aa9 100644 --- a/source/blender/collada/ArmatureExporter.h +++ b/source/blender/collada/ArmatureExporter.h @@ -83,8 +83,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - std::string get_joint_sid(Bone *bone, Object *ob_arm); - // Scene, SceneExporter and the list of child_objects // are required for writing bone parented objects void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se, diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index ae43c0a69d2..0ea8324ed7c 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -32,6 +32,7 @@ #include "COLLADAFWUniqueId.h" +extern "C" { #include "BKE_action.h" #include "BKE_depsgraph.h" #include "BKE_object.h" @@ -39,7 +40,9 @@ #include "BLI_string.h" #include "BLI_listbase.h" #include "ED_armature.h" +} +#include "collada_utils.h" #include "ArmatureImporter.h" // use node name, or fall back to original id if not present (name is optional) @@ -91,6 +94,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon { float mat[4][4]; float joint_inv_bind_mat[4][4]; + float joint_bind_mat[4][4]; int chain_length = 0; //Checking if bone is already made. @@ -106,7 +110,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon */ std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it; - bool bone_is_not_skinned = true; + bool bone_is_skinned = false; for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) { SkinInfo *b = &skin_it->second; @@ -114,7 +118,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon // get original world-space matrix invert_m4_m4(mat, joint_inv_bind_mat); - + copy_m4_m4(joint_bind_mat, mat); // And make local to armature Object *ob_arm = skin->BKE_armature_from_object(); if (ob_arm) { @@ -123,24 +127,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon mul_m4_m4m4(mat, invmat, mat); } - bone_is_not_skinned = false; + bone_is_skinned = true; break; } } // create a bone even if there's no joint data for it (i.e. it has no influence) - if (bone_is_not_skinned) { - float obmat[4][4]; - // bone-space - get_node_mat(obmat, node, NULL, NULL); - - // get world-space - if (parent) { - mul_m4_m4m4(mat, parent_mat, obmat); - } - else { - copy_m4_m4(mat, obmat); - } + if (!bone_is_skinned) { + get_node_mat(mat, node, NULL, NULL, parent_mat); } if (parent) bone->parent = parent; @@ -156,10 +150,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon int use_connect = be.get_use_connect(); switch (use_connect) { - case 1: bone->flag |= BONE_CONNECTED; - break; - case 0: bone->flag &= ~BONE_CONNECTED; - case -1: break; // not defined + case 1: bone->flag |= BONE_CONNECTED; + break; + case -1:/* Connect type not specified */ + case 0: bone->flag &= ~BONE_CONNECTED; + break; } if (be.has_roll()) { @@ -169,8 +164,18 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon float angle; mat4_to_loc_rot_size(loc, rot, size, mat); mat3_to_vec_roll(rot, NULL, &angle); + bone->roll = angle; } copy_v3_v3(bone->head, mat[3]); + + if (bone_is_skinned) + { + float rest_mat[4][4]; + get_node_mat(rest_mat, node, NULL, NULL, NULL); + bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat); + bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat); + } + add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero /* find smallest bone length in armature (used later for leaf bone length) */ @@ -272,7 +277,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone) } - void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip) { BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature); @@ -288,12 +292,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone for (; child; child = child->next) { BoneExtended *be = extended_bones[child->name]; if (be != NULL) { - if (be->get_chain_length() <= clip) { - if (be->get_chain_length() > maxlen) { + int chain_len = be->get_chain_length(); + if (chain_len <= clip) { + if (chain_len > maxlen) { dominant_child = be; - maxlen = be->get_chain_length(); + maxlen = chain_len; } - else if (be->get_chain_length() == maxlen) { + else if (chain_len == maxlen) { dominant_child = NULL; } } @@ -307,7 +312,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone EditBone *pebone = bc_get_edit_bone(armature, parentbone->name); EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name()); if (pebone && !(cebone->flag & BONE_CONNECTED)) { - float vec[3]; sub_v3_v3v3(vec, cebone->head, pebone->head); @@ -320,14 +324,16 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH) { - pebone->tail[0] = cebone->head[0]; - pebone->tail[1] = cebone->head[1]; - pebone->tail[2] = cebone->head[2]; - + copy_v3_v3(pebone->tail, cebone->head); + pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/ if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) { + + BoneExtended *cbe = extended_bones[cebone->name]; + cbe->set_use_connect(true); + cebone->flag |= BONE_CONNECTED; - printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name); pbe->set_leaf_bone(false); + printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name); } } } diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 06e151c363b..5cd5e6d271a 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -98,7 +98,10 @@ bool ControllerExporter::add_instance_controller(Object *ob) write_bone_URLs(ins, ob_arm, bone); } - InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(ins.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); ins.add(); return true; @@ -157,11 +160,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O } #endif -std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm) -{ - return get_joint_id(bone, ob_arm); -} - std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob) { return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX; @@ -468,81 +466,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb return source_id; } -static float get_property(Bone *bone, const char *key, float def) -{ - float result = def; - if (bone->prop) { - IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key); - if (property) { - switch (property->type) { - case IDP_INT: - result = (float)(IDP_Int(property)); - break; - case IDP_FLOAT: - result = (float)(IDP_Float(property)); - break; - case IDP_DOUBLE: - result = (float)(IDP_Double(property)); - break; - default: - result = def; - } - } - } - return result; -} - -/** - * This function creates an arbitrary rest pose matrix from - * data provided as custom properties. This is a workaround - * for support of maya's restpose matrix which can be arbitrary - * in opposition to Blender where the Rest pose Matrix is always - * the Identity matrix. - * - * The custom properties are: - * - * restpose_scale_x - * restpose_scale_y - * restpose_scale_z - * - * restpose_rot_x - * restpose_rot_y - * restpose_rot_z - * - * restpose_loc_x - * restpose_loc_y - * restpose_loc_z - * - * The matrix is only setup if the scale AND the rot properties are defined. - * The presence of the loc properties is optional. - * - * This feature has been implemented to support Second Life "Fitted Mesh" - * TODO: Check if an arbitrary rest pose matrix makes sense within Blender. - * Eventually leverage the custom property data into an "official" - * Edit_bone Property - */ -static void create_restpose_mat(Bone *bone, float mat[4][4]) -{ - float loc[3] = { - get_property(bone, "restpose_loc_x", 0.0), - get_property(bone, "restpose_loc_y", 0.0), - get_property(bone, "restpose_loc_z", 0.0) - }; - - float rot[3] = { - DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)), - DEG2RADF(get_property(bone, "restpose_rot_z", 0.0)) - }; - - float scale[3] = { - get_property(bone, "restpose_scale_x", 1.0), - get_property(bone, "restpose_scale_y", 1.0), - get_property(bone, "restpose_scale_z", 1.0) - }; - - loc_eulO_size_to_mat4(mat, loc, rot, scale, 6); -} std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) { @@ -585,30 +508,36 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas float world[4][4]; float inv_bind_mat[4][4]; + float bind_mat[4][4]; /* derived from bone->arm_mat */ + + bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat); - // SL/OPEN_SIM COMPATIBILITY - if (export_settings->open_sim) { - // Only translations, no rotation vs armature - float temp[4][4]; - unit_m4(temp); - copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); - mul_m4_m4m4(world, ob_arm->obmat, temp); - - // Add Maya restpose matrix (if defined as properties) - float restpose_mat[4][4]; - create_restpose_mat(pchan->bone, restpose_mat); - mul_m4_m4m4(world, world, restpose_mat); + if (!has_bindmat) { - } - else { - // make world-space matrix, arm_mat is armature-space - mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); + /* Have no bind matrix stored, try old style <= Blender 2.78 */ + + bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true); + + // SL/OPEN_SIM COMPATIBILITY + if (export_settings->open_sim) { + + float loc[3]; + float rot[3] = { 0, 0, 0 }; + float scale[3]; + bc_decompose(bind_mat, loc, NULL, NULL, scale); + + // Only translations, no rotation vs armature + loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6); + } } + // make world-space matrix (bind_mat is armature-space) + mul_m4_m4m4(world, ob_arm->obmat, bind_mat); invert_m4_m4(mat, world); converter.mat4_to_dae(inv_bind_mat, mat); - + if (this->export_settings->limit_precision) + bc_sanitize_mat(inv_bind_mat, 6); source.appendValues(inv_bind_mat); } } diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h index 0be51187f6f..80b858ca6dd 100644 --- a/source/blender/collada/ControllerExporter.h +++ b/source/blender/collada/ControllerExporter.h @@ -84,8 +84,6 @@ private: void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce); #endif - std::string get_joint_sid(Bone *bone, Object *ob_arm); - std::string get_controller_id(Object *ob_arm, Object *ob); std::string get_controller_id(Key *key, Object *ob); diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index bd32e989ae3..dcfd062470c 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype); char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n) { int layer_index = CustomData_get_layer_index(data, type); - if (layer_index < 0) return NULL; + if (layer_index < 0) + return NULL; return data->layers[layer_index + n].name; } @@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type) { /* get the layer index of the active layer of type */ int layer_index = CustomData_get_active_layer_index(data, type); - if (layer_index < 0) return NULL; + if (layer_index < 1) + return NULL; - return data->layers[layer_index].name; + return bc_CustomData_get_layer_name(data, type, layer_index-1); } DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) { @@ -303,7 +305,10 @@ int DocumentExporter::exportCurrentScene(Scene *sce) // <library_visual_scenes> SceneExporter se(writer, &arm_exporter, this->export_settings); - +#if 0 + /* The following code seems to be an obsolete workaround + Comment out until it proofs correct that we no longer need it. + */ if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { // channels adressing <matrix> objects is not (yet) supported // So we force usage of <location>, <translation> and <scale> @@ -315,7 +320,9 @@ int DocumentExporter::exportCurrentScene(Scene *sce) else { se.setExportTransformationType(this->export_settings->export_transformation_type); } - +#else + se.setExportTransformationType(this->export_settings->export_transformation_type); +#endif se.exportScene(sce); // <scene> diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 226f319cefd..f7fdfb06a40 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -388,9 +388,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera Camera *cam = uid_camera_map[cam_uid]; Camera *old_cam = (Camera *)ob->data; ob->data = cam; - id_us_min(&old_cam->id); - if (old_cam->id.us == 0) - BKE_libblock_free(G.main, old_cam); + BKE_libblock_free_us(G.main, old_cam); return ob; } @@ -406,9 +404,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce Lamp *la = uid_lamp_map[lamp_uid]; Lamp *old_lamp = (Lamp *)ob->data; ob->data = la; - id_us_min(&old_lamp->id); - if (old_lamp->id.us == 0) - BKE_libblock_free(G.main, old_lamp); + BKE_libblock_free_us(G.main, old_lamp); return ob; } @@ -512,9 +508,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA std::vector<Object *> *root_objects = new std::vector<Object *>(); fprintf(stderr, - "Writing node id='%s', name='%s'\n", - id.c_str(), - name.c_str()); + "Writing node id='%s', name='%s'\n", + id.c_str(), + name.c_str()); if (is_joint) { if (parent_node == NULL && !is_library_node) { diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 76b51148509..2bf0859b0f0 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -27,7 +27,6 @@ #include <map> -#include <set> #include "COLLADASWEffectProfile.h" #include "COLLADAFWColorOrTexture.h" @@ -49,21 +48,10 @@ extern "C" { #include "BKE_material.h" } -// OB_MESH is assumed -static std::string getActiveUVLayerName(Object *ob) -{ - Mesh *me = (Mesh *)ob->data; - - int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - if (num_layers) - return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); - - return ""; -} - EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) { } + bool EffectsExporter::hasEffects(Scene *sce) { Base *base = (Base *)sce->base.first; @@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce) void EffectsExporter::exportEffects(Scene *sce) { - if (hasEffects(sce)) { - this->scene = sce; - openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); - - closeLibrary(); + this->scene = sce; + + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { + if (hasEffects(sce)) { + MaterialFunctor mf; + openLibrary(); + mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set); + closeLibrary(); + } + } + else { + std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only); + std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only); + if (uv_images.size() > 0) { + openLibrary(); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string key(id_name(ima)); + key = translate_id(key); + COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, + key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, + key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); + sampler.setImageId(key); + + openEffect(key + "-effect"); + COLLADASW::EffectProfile ep(mSW); + ep.setProfileType(COLLADASW::EffectProfile::COMMON); + ep.setShaderType(COLLADASW::EffectProfile::PHONG); + ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse"); + COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f); + ep.setSpecular(cot, false, "specular"); + ep.openProfile(); + ep.addProfileElements(); + ep.addExtraTechniques(mSW); + ep.closeProfile(); + closeEffect(); + } + closeLibrary(); + } } } @@ -176,8 +200,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) { // create a list of indices to textures of type TEX_IMAGE std::vector<int> tex_indices; - if (this->export_settings->include_material_textures) - createTextureIndices(ma, tex_indices); + createTextureIndices(ma, tex_indices); openEffect(translate_id(id_name(ma)) + "-effect"); @@ -311,61 +334,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob) } } - int active_uv_layer = -1; - std::set<Image *> uv_textures; - if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) { - bool active_uv_only = this->export_settings->active_uv_only; - Mesh *me = (Mesh *) ob->data; - active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); - - BKE_mesh_tessface_ensure(me); - for (int i = 0; i < me->pdata.totlayer; i++) { - if (!active_uv_only || active_uv_layer == i) - { - if (me->pdata.layers[i].type == CD_MTEXPOLY) { - MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; - MPoly *mpoly = me->mpoly; - for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { - - Material *mat = give_current_material(ob, mpoly->mat_nr + 1); - if (mat != ma) - continue; - - Image *ima = txface->tpage; - if (ima == NULL) - continue; - - - bool not_in_list = uv_textures.find(ima)==uv_textures.end(); - if (not_in_list) { - std::string name = id_name(ima); - std::string key(name); - key = translate_id(key); - - // create only one <sampler>/<surface> pair for each unique image - if (im_samp_map.find(key) == im_samp_map.end()) { - //<newparam> <sampler> <source> - COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, - key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX, - key + COLLADASW::Sampler::SURFACE_SID_SUFFIX); - sampler.setImageId(key); - samplers[a] = sampler; - samp_surf[b] = &samplers[a]; - im_samp_map[key] = b; - b++; - a++; - uv_textures.insert(ima); - } - } - } - } - } - } - } - // used as fallback when MTex->uvname is "" (this is pretty common) // it is indeed the correct value to use in that case - std::string active_uv(getActiveUVLayerName(ob)); + std::string active_uv(bc_get_active_uvlayer_name(ob)); // write textures // XXX very slow @@ -385,19 +356,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob) writeTextures(ep, key, sampler, t, ima, uvname); } - std::set<Image *>::iterator uv_t_iter; - int idx; - for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) { - if (active_uv_layer>-1 && idx==active_uv_layer) { - Image *ima = *uv_t_iter; - std::string key(id_name(ima)); - key = translate_id(key); - int i = im_samp_map[key]; - COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i]; - ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse"); - } - } - // performs the actual writing ep.addProfileElements(); bool twoSided = false; diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h index d20cbfdfe0b..7d45a085777 100644 --- a/source/blender/collada/EffectExporter.h +++ b/source/blender/collada/EffectExporter.h @@ -48,7 +48,6 @@ class EffectsExporter: COLLADASW::LibraryEffects public: EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings); void exportEffects(Scene *sce); - void operator()(Material *ma, Object *ob); COLLADASW::ColorOrTexture createTexture(Image *ima, diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index 98aa85f8a9b..32aa5636e08 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -49,7 +49,7 @@ ErrorHandler::~ErrorHandler() //-------------------------------------------------------------------- bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) { - bool isError = true; + bool isError = false; if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) { COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error; @@ -81,10 +81,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) * Accept non critical errors as warnings (i.e. texture not found) * This makes the importer more graceful, so it now imports what makes sense. */ - if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) { - isError = false; - } - + isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL); std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl; } else { @@ -93,5 +90,5 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) mError |= isError; - return false; // let OpenCollada decide when to abort + return isError; // let OpenCollada decide when to abort } diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 9451cac9dae..6d90edd2f67 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -28,7 +28,6 @@ #define __EXPORTSETTINGS_H__ #include "collada.h" -#include "collada.h" struct ExportSettings { public: @@ -42,8 +41,7 @@ public: bool deform_bones_only; bool active_uv_only; - bool include_uv_textures; - bool include_material_textures; + BC_export_texture_type export_texture_type; bool use_texture_copies; bool triangulate; @@ -51,7 +49,10 @@ public: bool use_blender_profile; bool sort_by_name; BC_export_transformation_type export_transformation_type; + bool open_sim; + bool limit_precision; + bool keep_bind_info; char *filepath; LinkNode *export_set; diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 7c7c57f3305..8a9ccbbed51 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -52,6 +52,7 @@ extern "C" { #include "collada_internal.h" #include "collada_utils.h" + // TODO: optimize UV sets by making indexed list with duplicates removed GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings) { @@ -134,13 +135,22 @@ void GeometryExporter::operator()(Object *ob) // Only create Polylists if number of faces > 0 if (me->totface > 0) { // XXX slow - if (ob->totcol) { - for (int a = 0; a < ob->totcol; a++) { - createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only); + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) { + if (ob->totcol) { + for (int a = 0; a < ob->totcol; a++) { + createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); + } + } + else { + int i = 0; + createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind); } } else { - createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + bool all_uv_layers = !this->export_settings->active_uv_only; + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind); } } @@ -220,13 +230,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb) //createLooseEdgeList(ob, me, geom_id, norind); // XXX slow - if (ob->totcol) { + if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { for (int a = 0; a < ob->totcol; a++) { createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind); } } else { - createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind); + bool all_uv_layers = !this->export_settings->active_uv_only; + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind); } closeMesh(); @@ -295,7 +307,44 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char return result; } -// powerful because it handles both cases when there is material and when there's not +static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list) +{ + // performs the actual writing + if (is_triangulated) { + ((COLLADASW::Triangles *)facelist)->prepareToAppendValues(); + } + else { + // sets <vcount> + facelist->setVCountList(vcount_list); + ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues(); + } +} + +static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist) +{ + if (is_triangulated) { + ((COLLADASW::Triangles *)facelist)->finish(); + } + else { + ((COLLADASW::Polylist *)facelist)->finish(); + } +} + +COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW) +{ + COLLADASW::PrimitivesBase *facelist; + + if (is_triangulated) + { + facelist = new COLLADASW::Triangles(mSW); + } + else { + facelist = new COLLADASW::Polylist(mSW); + } + return facelist; +} + +// Export meshes with Materials void GeometryExporter::createPolylist(short material_index, bool has_uvs, bool has_color, @@ -313,7 +362,7 @@ void GeometryExporter::createPolylist(short material_index, int i; int faces_in_polylist = 0; std::vector<unsigned long> vcount_list; - + bool is_triangulated = true; // count faces with this material for (i = 0; i < totpolys; i++) { MPoly *p = &mpolys[i]; @@ -321,6 +370,9 @@ void GeometryExporter::createPolylist(short material_index, if (p->mat_nr == material_index) { faces_in_polylist++; vcount_list.push_back(p->totloop); + if (p->totloop != 3) { + is_triangulated = false; + } } } @@ -331,20 +383,21 @@ void GeometryExporter::createPolylist(short material_index, } Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL; - COLLADASW::Polylist polylist(mSW); + COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW); + // sets count attribute in <polylist> - polylist.setCount(faces_in_polylist); + facelist->setCount(faces_in_polylist); // sets material name if (ma) { std::string material_id = get_material_id(ma); std::ostringstream ostr; ostr << translate_id(material_id); - polylist.setMaterial(ostr.str()); + facelist->setMaterial(ostr.str()); } - - COLLADASW::InputList &til = polylist.getInputList(); + + COLLADASW::InputList &til = facelist->getInputList(); // creates <input> in <polylist> for vertices COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); @@ -360,13 +413,21 @@ void GeometryExporter::createPolylist(short material_index, int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1; for (i = 0; i < num_layers; i++) { if (!this->export_settings->active_uv_only || i == active_uv_index) { - - // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i); + + std::string uv_name(bc_get_uvlayer_name(me, i)); + std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + i, this->export_settings->active_uv_only); + + /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements + For now this is always 2 (This may change sometime/maybe) + */ COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD, - makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)), - 2, // this is only until we have optimized UV sets - (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set - ); + makeUrl(layer_id), + 2, // this is only until we have optimized UV sets + (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set + ); til.push_back(input3); } } @@ -387,12 +448,10 @@ void GeometryExporter::createPolylist(short material_index, } } - // sets <vcount> - polylist.setVCountList(vcount_list); // performs the actual writing - polylist.prepareToAppendValues(); - + prepareToAppendValues(is_triangulated, facelist, vcount_list); + // <p> int texindex = 0; for (i = 0; i < totpolys; i++) { @@ -404,22 +463,202 @@ void GeometryExporter::createPolylist(short material_index, BCPolygonNormalsIndices normal_indices = norind[i]; for (int j = 0; j < loop_count; j++) { - polylist.appendValues(l[j].v); - polylist.appendValues(normal_indices[j]); + facelist->appendValues(l[j].v); + facelist->appendValues(normal_indices[j]); if (has_uvs) - polylist.appendValues(texindex + j); + facelist->appendValues(texindex + j); if (has_color) - polylist.appendValues(texindex + j); + facelist->appendValues(texindex + j); } } texindex += loop_count; } - - polylist.finish(); + + finishList(is_triangulated, facelist); + delete facelist; } +void GeometryExporter::createPolylists(std::set<Image *> uv_images, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind) +{ + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string imageid(id_name(ima)); + createPolylist(imageid, has_uvs, + has_color, + ob, + me, + geom_id, + norind); + } + + /* We msut add an additional collector for the case when + * some parts of the object are not textured at all. + * The next call creates a polylist for all untextured polygons + */ + + createPolylist("", has_uvs, + has_color, + ob, + me, + geom_id, + norind); + +} + +/* =========================================================================== + * Export Meshes with UV Textures (export as materials, see also in + * effectExporter and MaterialExporter) + * + * If imageid is the empty string, then collect only untextured polygons + * =========================================================================== */ +void GeometryExporter::createPolylist(std::string imageid, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind) +{ + + MPoly *mpolys = me->mpoly; + MLoop *mloops = me->mloop; + MTexPoly *mtpolys = me->mtpoly; + + int totpolys = me->totpoly; + + // <vcount> + int i; + int faces_in_polylist = 0; + std::vector<unsigned long> vcount_list; + bool is_triangulated = true; + // count faces with this material + for (i = 0; i < totpolys; i++) { + MTexPoly *tp = &mtpolys[i]; + MPoly *p = &mpolys[i]; + + std::string tpageid = (tp->tpage) ? id_name(tp->tpage):""; + if (tpageid == imageid) { + faces_in_polylist++; + vcount_list.push_back(p->totloop); + if (p->totloop != 3) { + is_triangulated = false; + } + } + } + + // no faces using this imageid + if (faces_in_polylist == 0) { + if (imageid != "") + fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str()); + return; + } + + COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW); + + // sets count attribute in <polylist> + facelist->setCount(faces_in_polylist); + + if (imageid != "") { + // sets material name + std::string material_id = get_material_id_from_id(imageid); + std::ostringstream ostr; + ostr << translate_id(material_id); + facelist->setMaterial(ostr.str()); + } + COLLADASW::InputList &til = facelist->getInputList(); + + // creates <input> in <polylist> for vertices + COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0); + + // creates <input> in <polylist> for normals + COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1); + + til.push_back(input1); + til.push_back(input2); + + // if mesh has uv coords writes <input> for TEXCOORD + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; + for (i = 0; i < num_layers; i++) { + if (!this->export_settings->active_uv_only || i == active_uv_index) { + + std::string uv_name(bc_get_uvlayer_name(me, i)); + std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + i, this->export_settings->active_uv_only); + + /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements + For now this is always 2 (This may change sometime/maybe) + */ + COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD, + makeUrl(layer_id), + 2, // this is only until we have optimized UV sets + (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set + ); + til.push_back(input3); + } + } + + int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + if (totlayer_mcol > 0) { + int map_index = 0; + + for (int a = 0; a < totlayer_mcol; a++) { + char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a); + COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, + makeUrl(makeVertexColorSourceId(geom_id, layer_name)), + (has_uvs) ? 3 : 2, // all color layers have same index order + map_index // set number equals color map index + ); + til.push_back(input4); + map_index++; + } + } + + // performs the actual writing + prepareToAppendValues(is_triangulated, facelist, vcount_list); + + // <p> + int texindex = 0; + for (i = 0; i < totpolys; i++) { + MTexPoly *tp = &mtpolys[i]; + MPoly *p = &mpolys[i]; + int loop_count = p->totloop; + std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : ""; + if (tpageid == imageid) { + MLoop *l = &mloops[p->loopstart]; + BCPolygonNormalsIndices normal_indices = norind[i]; + + for (int j = 0; j < loop_count; j++) { + facelist->appendValues(l[j].v); + facelist->appendValues(normal_indices[j]); + if (has_uvs) + facelist->appendValues(texindex + j); + + if (has_color) + facelist->appendValues(texindex + j); + } + } + + texindex += loop_count; + } + + finishList(is_triangulated, facelist); + delete facelist; +} // creates <source> for positions void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) @@ -479,12 +718,13 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.setArrayId(layer_id + ARRAY_ID_SUFFIX); source.setAccessorCount(me->totloop); - source.setAccessorStride(3); + source.setAccessorStride(4); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); param.push_back("R"); param.push_back("G"); param.push_back("B"); + param.push_back("A"); source.prepareToAppendValues(); @@ -496,7 +736,8 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.appendValues( mlc->r / 255.0f, mlc->g / 255.0f, - mlc->b / 255.0f + mlc->b / 255.0f, + mlc->a / 255.0f ); } } @@ -537,7 +778,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me) MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a); COLLADASW::FloatSourceF source(mSW); - std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only); + std::string active_uv_name(bc_get_active_uvlayer_name(me)); + std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name; + std::string layer_id = makeTexcoordSourceId( + effective_id, + a, + this->export_settings->active_uv_only ); + source.setId(layer_id); source.setArrayId(layer_id + ARRAY_ID_SUFFIX); diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 69d1067e6f4..890304f4568 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -85,15 +85,33 @@ public: Mesh *me, std::string& geom_id); - // powerful because it handles both cases when there is material and when there's not + // Create polylists for meshes with Materials void createPolylist(short material_index, - bool has_uvs, - bool has_color, - Object *ob, - Mesh *me, - std::string& geom_id, - std::vector<BCPolygonNormalsIndices>& norind); - + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + + // Create polylists for meshes with UV Textures + void createPolylists(std::set<Image *> uv_images, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + + // Create polylists for meshes with UV Textures + void createPolylist(std::string imageid, + bool has_uvs, + bool has_color, + Object *ob, + Mesh *me, + std::string& geom_id, + std::vector<BCPolygonNormalsIndices>& norind); + // creates <source> for positions void createVertsSource(std::string geom_id, Mesh *me); diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp index aac41e2e93c..93be7de6236 100644 --- a/source/blender/collada/ImageExporter.cpp +++ b/source/blender/collada/ImageExporter.cpp @@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings void ImagesExporter::export_UV_Image(Image *image, bool use_copies) { - std::string name(id_name(image)); - std::string translated_name(translate_id(name)); - bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end(); + std::string id(id_name(image)); + std::string translated_id(translate_id(id)); + bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end(); if (not_yet_exported) { @@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) // make absolute destination path - BLI_strncpy(export_file, name.c_str(), sizeof(export_file)); + BLI_strncpy(export_file, id.c_str(), sizeof(export_file)); BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat); BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file); @@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies) } } - COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ + /* set name also to mNameNC. This helps other viewers import files exported from Blender better */ + COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id); img.add(mSW); fprintf(stdout, "Collada export: Added image: %s\n", export_file); - mImages.push_back(translated_name); + mImages.push_back(translated_id); BKE_image_release_ibuf(image, imbuf, NULL); } @@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images() for (node = this->export_settings->export_set; node; node = node->next) { Object *ob = (Object *)node->link; - if (ob->type == OB_MESH && ob->totcol) { + if (ob->type == OB_MESH) { Mesh *me = (Mesh *) ob->data; BKE_mesh_tessface_ensure(me); int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); @@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images() } } - +/* ============================================================ + * Check if there are any images to be exported + * Returns true as soon as an object is detected that + * either has an UV Texture assigned, or has a material + * assigned that uses an Image Texture. + * ============================================================ + */ bool ImagesExporter::hasImages(Scene *sce) { LinkNode *node; @@ -232,11 +239,10 @@ void ImagesExporter::exportImages(Scene *sce) openLibrary(); MaterialFunctor mf; - if (this->export_settings->include_material_textures) { + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) { mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set); } - - if (this->export_settings->include_uv_textures) { + else { export_UV_Images(); } diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h index 2c52d73e756..4a2d4e8046a 100644 --- a/source/blender/collada/ImportSettings.h +++ b/source/blender/collada/ImportSettings.h @@ -37,6 +37,7 @@ public: bool fix_orientation; int min_chain_length; char *filepath; + bool keep_bind_info; }; #endif diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp index 71371d280df..de1a4075462 100644 --- a/source/blender/collada/InstanceWriter.cpp +++ b/source/blender/collada/InstanceWriter.cpp @@ -32,43 +32,76 @@ #include "COLLADASWInstanceMaterial.h" extern "C" { - #include "BKE_customdata.h" - #include "BKE_material.h" - #include "DNA_mesh_types.h" +#include "BKE_customdata.h" +#include "BKE_material.h" +#include "DNA_mesh_types.h" } #include "InstanceWriter.h" #include "collada_internal.h" #include "collada_utils.h" -void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only) +void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type) { - for (int a = 0; a < ob->totcol; a++) { - Material *ma = give_current_material(ob, a + 1); - - COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); + bool all_uv_layers = !active_uv_only; + COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList(); - if (ma) { - std::string matid(get_material_id(ma)); - matid = translate_id(matid); + if (export_texture_type == BC_TEXTURE_TYPE_UV) + { + std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + Image *ima = *uv_images_iter; + std::string matid(id_name(ima)); + matid = get_material_id_from_id(matid); std::ostringstream ostr; ostr << matid; COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); - + // create <bind_vertex_input> for each uv map Mesh *me = (Mesh *)ob->data; int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - + int map_index = 0; - int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1; + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; for (int b = 0; b < totlayer; b++) { if (!active_uv_only || b == active_uv_index) { char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b); im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); } } - + iml.push_back(im); } } + + else { + for (int a = 0; a < ob->totcol; a++) { + Material *ma = give_current_material(ob, a + 1); + if (ma) { + std::string matid(get_material_id(ma)); + matid = translate_id(matid); + std::ostringstream ostr; + ostr << matid; + COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid)); + + // create <bind_vertex_input> for each uv map + Mesh *me = (Mesh *)ob->data; + int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + + int map_index = 0; + int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1; + for (int b = 0; b < totlayer; b++) { + if (!active_uv_only || b == active_uv_index) { + char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b); + im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++)); + } + } + + iml.push_back(im); + } + } + } } diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h index 49ddf091b1c..a46027325a2 100644 --- a/source/blender/collada/InstanceWriter.h +++ b/source/blender/collada/InstanceWriter.h @@ -31,11 +31,12 @@ #include "COLLADASWBindMaterial.h" #include "DNA_object_types.h" +#include "collada.h" class InstanceWriter { protected: - void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only); + void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type); }; #endif diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index 4aece997f72..6e6cc24be20 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -38,14 +38,39 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe void MaterialsExporter::exportMaterials(Scene *sce) { - if (hasMaterials(sce)) { - openLibrary(); + if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) + { + if (hasMaterials(sce)) { + openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set); + MaterialFunctor mf; + mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set); - closeLibrary(); + closeLibrary(); + } } + + else { + std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only); + if (uv_images.size() > 0) { + openLibrary(); + std::set<Image *>::iterator uv_images_iter; + for (uv_images_iter = uv_images.begin(); + uv_images_iter != uv_images.end(); + uv_images_iter++) { + + Image *ima = *uv_images_iter; + std::string matid(id_name(ima)); + + openMaterial(get_material_id_from_id(matid), translate_id(matid)); + std::string efid = translate_id(matid) + "-effect"; + addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid)); + closeMaterial(); + } + closeLibrary(); + } + } + } bool MaterialsExporter::hasMaterials(Scene *sce) diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8f3bf88af65..6ca53c64299 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -27,7 +27,7 @@ #include <algorithm> -#if !defined(WIN32) || defined(FREE_WINDOWS) +#if !defined(WIN32) #include <iostream> #endif @@ -1173,8 +1173,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta BKE_mesh_assign_object(ob, new_mesh); BKE_mesh_calc_normals(new_mesh); - if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh); - + id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */ + BKE_libblock_free_us(G.main, old_mesh); + char layername[100]; layername[0] = '\0'; MTFace *texture_face = NULL; diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 30cd6ddf197..73945539931 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -151,7 +151,10 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) COLLADASW::InstanceGeometry instGeom(mSW); instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation))); instGeom.setName(translate_id(id_name(ob))); - InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only); + InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), + ob, + this->export_settings->active_uv_only, + this->export_settings->export_texture_type); instGeom.add(); } diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp index 7242a24523c..c48c060dc95 100644 --- a/source/blender/collada/SkinInfo.cpp +++ b/source/blender/collada/SkinInfo.cpp @@ -27,7 +27,7 @@ #include <algorithm> -#if !defined(WIN32) || defined(FREE_WINDOWS) +#if !defined(WIN32) #include <stdint.h> #endif @@ -230,7 +230,6 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature); ArmatureModifierData *amd = (ArmatureModifierData *)md; amd->object = ob_arm; - struct bArmature *armature = (bArmature *)ob_arm->data; #if 1 bc_set_parent(ob, ob_arm, C); diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp index f8f31304d28..7f742be7e30 100644 --- a/source/blender/collada/TransformReader.cpp +++ b/source/blender/collada/TransformReader.cpp @@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv) /* pass */ } -void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob) +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob) +{ + get_node_mat(mat, node, animation_map, ob, NULL); +} + +void TransformReader::get_node_mat( + float mat[4][4], + COLLADAFW::Node *node, + std::map<COLLADAFW::UniqueId, Animation> *animation_map, + Object *ob, + float parent_mat[4][4]) { float cur[4][4]; float copy[4][4]; @@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: // then this is considered as redundant information. // So if we find a Matrix we use that and return. dae_matrix_to_mat4(tm, mat); + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } return; case COLLADAFW::Transformation::TRANSLATE: dae_translate_to_mat4(tm, cur); @@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std:: (*animation_map)[anim_list_id] = anim; } } + + if (parent_mat) { + mul_m4_m4m4(mat, parent_mat, mat); + } } void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]) diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h index ab974b9ba85..08bb17ccac1 100644 --- a/source/blender/collada/TransformReader.h +++ b/source/blender/collada/TransformReader.h @@ -43,7 +43,7 @@ //struct Object; -class TransformReader : public TransformBase +class TransformReader { protected: @@ -59,7 +59,8 @@ public: TransformReader(UnitConverter *conv); void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob); - + void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]); + void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]); diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index 908111ebae6..b7eeff3b074 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -27,11 +27,10 @@ #include "BKE_object.h" +#include "BLI_math.h" #include "TransformWriter.h" -#include "BLI_math.h" - void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]) { float loc[3], rot[3], scale[3]; @@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], converter->mat4_to_dae_double(dmat, local); delete converter; - TransformBase::decompose(local, loc, rot, NULL, scale); + bc_decompose(local, loc, rot, NULL, scale); if (node.getType() == COLLADASW::Node::JOINT) { // XXX Why are joints handled differently ? @@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { float loc[3], rot[3], scale[3]; - TransformBase::decompose(f_obmat, loc, rot, NULL, scale); + bc_decompose(f_obmat, loc, rot, NULL, scale); add_transform(node, loc, rot, scale); break; } diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index 7f69a4b9c95..5bb13d4aac9 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -33,9 +33,10 @@ #include "DNA_object_types.h" #include "collada_internal.h" +#include "collada_utils.h" #include "collada.h" -class TransformWriter : protected TransformBase +class TransformWriter { protected: void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index fe8b1d2320a..024bc4a4a5c 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -48,7 +48,8 @@ int collada_import(bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length) + int min_chain_length, + int keep_bind_info) { ImportSettings import_settings; @@ -58,6 +59,7 @@ int collada_import(bContext *C, import_settings.find_chains = find_chains != 0; import_settings.fix_orientation = fix_orientation != 0; import_settings.min_chain_length = min_chain_length; + import_settings.keep_bind_info = keep_bind_info !=0; DocumentImporter imp(C, &import_settings); if (imp.import()) return 1; @@ -78,8 +80,7 @@ int collada_export(Scene *sce, int deform_bones_only, int active_uv_only, - int include_uv_textures, - int include_material_textures, + BC_export_texture_type export_texture_type, int use_texture_copies, int triangulate, @@ -87,7 +88,9 @@ int collada_export(Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim) + int open_sim, + int limit_precision, + int keep_bind_info) { ExportSettings export_settings; @@ -102,8 +105,7 @@ int collada_export(Scene *sce, export_settings.deform_bones_only = deform_bones_only != 0; export_settings.active_uv_only = active_uv_only != 0; - export_settings.include_uv_textures = include_uv_textures != 0; - export_settings.include_material_textures= include_material_textures != 0; + export_settings.export_texture_type = export_texture_type; export_settings.use_texture_copies = use_texture_copies != 0; export_settings.triangulate = triangulate != 0; @@ -112,7 +114,8 @@ int collada_export(Scene *sce, export_settings.sort_by_name = sort_by_name != 0; export_settings.export_transformation_type = export_transformation_type; export_settings.open_sim = open_sim != 0; - + export_settings.limit_precision = limit_precision != 0; + export_settings.keep_bind_info = keep_bind_info !=0; int includeFilter = OB_REL_NONE; if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index a4416608584..d31f5a8ba62 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -46,6 +46,11 @@ typedef enum BC_export_transformation_type { BC_TRANSFORMATION_TYPE_TRANSROTLOC } BC_export_transformation_type; +typedef enum BC_export_texture_type { + BC_TEXTURE_TYPE_MAT, + BC_TEXTURE_TYPE_UV +} BC_export_texture_type; + struct bContext; struct Scene; @@ -58,7 +63,9 @@ int collada_import(struct bContext *C, int find_chains, int auto_connect, int fix_orientation, - int min_chain_length); + int min_chain_length, + + int keep_bind_info); int collada_export(struct Scene *sce, const char *filepath, @@ -72,8 +79,7 @@ int collada_export(struct Scene *sce, int deform_bones_only, int active_uv_only, - int include_uv_textures, - int include_material_textures, + BC_export_texture_type export_texture_type, int use_texture_copies, int triangulate, @@ -81,9 +87,10 @@ int collada_export(struct Scene *sce, int use_blender_profile, int sort_by_name, BC_export_transformation_type export_transformation_type, - int open_sim); - + int open_sim, + int limit_precision, + int keep_bind_info); #ifdef __cplusplus } diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 38855013ee1..8974acb3460 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -33,11 +33,8 @@ UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) { - unit_m4(x_up_mat4); - rotate_m4(x_up_mat4, 'Y', -0.5 * M_PI); - - unit_m4(y_up_mat4); - rotate_m4(y_up_mat4, 'X', 0.5 * M_PI); + axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI); + axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI); unit_m4(z_up_mat4); unit_m4(scale_mat4); @@ -165,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce) size_to_mat4(scale_mat4, rescale); } -void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) -{ - mat4_to_size(size, mat); - if (eul) { - mat4_to_eul(eul, mat); - } - if (quat) { - mat4_to_quat(quat, mat); - } - copy_v3_v3(loc, mat[3]); -} - /** * Translation map. * Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be @@ -344,7 +329,12 @@ std::string get_light_id(Object *ob) std::string get_joint_id(Bone *bone, Object *ob_arm) { - return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name); + return translate_id(id_name(ob_arm) + "_" + bone->name); +} + +std::string get_joint_sid(Bone *bone, Object *ob_arm) +{ + return translate_id(bone->name); } std::string get_camera_id(Object *ob) @@ -354,7 +344,13 @@ std::string get_camera_id(Object *ob) std::string get_material_id(Material *mat) { - return translate_id(id_name(mat)) + "-material"; + std::string id = id_name(mat); + return get_material_id_from_id(id); +} + +std::string get_material_id_from_id(std::string id) +{ + return translate_id(id) + "-material"; } std::string get_morph_id(Object *ob) diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 4aa637a6876..5f3fa34edc1 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -85,12 +85,6 @@ public: }; -class TransformBase -{ -public: - void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); -}; - extern void clear_global_id_map(); /** Look at documentation of translate_map */ extern std::string translate_id(const std::string &id); @@ -104,10 +98,12 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation); extern std::string get_light_id(Object *ob); extern std::string get_joint_id(Bone *bone, Object *ob_arm); +extern std::string get_joint_sid(Bone *bone, Object *ob_arm); extern std::string get_camera_id(Object *ob); extern std::string get_material_id(Material *mat); +extern std::string get_material_id_from_id(std::string id); extern std::string get_morph_id(Object *ob); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 2efa8b21d81..b09732f9102 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -32,7 +32,7 @@ #include "COLLADAFWMeshPrimitive.h" #include "COLLADAFWMeshVertexData.h" -#include "collada_utils.h" +#include <set> extern "C" { #include "DNA_modifier_types.h" @@ -63,6 +63,9 @@ extern "C" { #include "bmesh_tools.h" } +#include "collada_utils.h" +#include "ExportSettings.h" + float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index) { if (index >= array.getValuesCount()) @@ -352,6 +355,28 @@ void bc_match_scale(std::vector<Object *> *objects_done, } } +/* + Convenience function to get only the needed components of a matrix +*/ +void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size) +{ + if (size) { + mat4_to_size(size, mat); + } + + if (eul) { + mat4_to_eul(eul, mat); + } + + if (quat) { + mat4_to_quat(quat, mat); + } + + if (loc) { + copy_v3_v3(loc, mat[3]); + } +} + void bc_triangulate_mesh(Mesh *me) { bool use_beauty = false; @@ -612,3 +637,356 @@ int BoneExtended::get_use_connect() { return this->use_connect; } + +/** +* Stores a 4*4 matrix as a custom bone property array of size 16 +*/ +void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]) +{ + IDProperty *idgroup = (IDProperty *)ebone->prop; + if (idgroup == NULL) + { + IDPropertyTemplate val = { 0 }; + idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + ebone->prop = idgroup; + } + + IDPropertyTemplate val = { 0 }; + val.array.len = 16; + val.array.type = IDP_FLOAT; + + IDProperty *data = IDP_New(IDP_ARRAY, &val, key); + float *array = (float *)IDP_Array(data); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + array[4 * i + j] = mat[i][j]; + + IDP_AddToGroup(idgroup, data); +} + +#if 0 +/** +* Stores a Float value as a custom bone property +* +* Note: This function is currently not needed. Keep for future usage +*/ +static void bc_set_IDProperty(EditBone *ebone, const char *key, float value) +{ + if (ebone->prop == NULL) + { + IDPropertyTemplate val = { 0 }; + ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties"); + } + + IDProperty *pgroup = (IDProperty *)ebone->prop; + IDPropertyTemplate val = { 0 }; + IDProperty *prop = IDP_New(IDP_FLOAT, &val, key); + IDP_Float(prop) = value; + IDP_AddToGroup(pgroup, prop); + +} +#endif + +/* +* Get a custom property when it exists. +* This function is also used to check if a property exists. +*/ +IDProperty *bc_get_IDProperty(Bone *bone, std::string key) +{ + return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str()); +} + +/** +* Read a custom bone property and convert to float +* Return def if the property does not exist. +*/ +float bc_get_property(Bone *bone, std::string key, float def) +{ + float result = def; + IDProperty *property = bc_get_IDProperty(bone, key); + if (property) { + switch (property->type) { + case IDP_INT: + result = (float)(IDP_Int(property)); + break; + case IDP_FLOAT: + result = (float)(IDP_Float(property)); + break; + case IDP_DOUBLE: + result = (float)(IDP_Double(property)); + break; + default: + result = def; + } + } + return result; +} + +/** +* Read a custom bone property and convert to matrix +* Return true if conversion was succesfull +* +* Return false if: +* - the property does not exist +* - is not an array of size 16 +*/ +bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]) +{ + IDProperty *property = bc_get_IDProperty(bone, key); + if (property && property->type == IDP_ARRAY && property->len == 16) { + float *array = (float *)IDP_Array(property); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = array[4 * i + j]; + return true; + } + return false; +} + +/** +* get a vector that is stored in 3 custom properties (used in Blender <= 2.78) +*/ +void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]) +{ + val[0] = bc_get_property(bone, key + "_x", def[0]); + val[1] = bc_get_property(bone, key + "_y", def[1]); + val[2] = bc_get_property(bone, key + "_z", def[2]); +} + +/** +* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78) +*/ +static bool has_custom_props(Bone *bone, bool enabled, std::string key) +{ + if (!enabled) + return false; + + return (bc_get_IDProperty(bone, key + "_x") + || bc_get_IDProperty(bone, key + "_y") + || bc_get_IDProperty(bone, key + "_z")); + +} + +/** +* Check if custom information about bind matrix exists and modify the from_mat +* accordingly. +* +* Note: This is old style for Blender <= 2.78 only kept for compatibility +*/ +void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space) +{ + float loc[3]; + float rot[3]; + float scale[3]; + static const float V0[3] = { 0, 0, 0 }; + + if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") && + !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale")) + { + /* No need */ + copy_m4_m4(to_mat, from_mat); + return; + } + + bc_decompose(from_mat, loc, rot, NULL, scale); + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_loc", loc, loc); + + if (use_local_space && bone->parent) { + Bone *b = bone; + while (b->parent) { + b = b->parent; + float ploc[3]; + bc_get_property_vector(b, "restpose_loc", ploc, V0); + loc[0] += ploc[0]; + loc[1] += ploc[1]; + loc[2] += ploc[2]; + } + } + } + + if (export_settings->keep_bind_info) { + if (bc_get_IDProperty(bone, "restpose_rot_x")) + rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_y")) + rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0)); + if (bc_get_IDProperty(bone, "restpose_rot_z")) + rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0)); + } + + if (export_settings->keep_bind_info) { + bc_get_property_vector(bone, "restpose_scale", scale, scale); + } + + loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6); + +} + +/* + Make 4*4 matrices better readable +*/ +void bc_sanitize_mat(float mat[4][4], int precision) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = double_round(mat[i][j], precision); +} + +/* +* Returns name of Active UV Layer or empty String if no active UV Layer defined. +* Assuming the Object is of type MESH +*/ +std::string bc_get_active_uvlayer_name(Object *ob) +{ + Mesh *me = (Mesh *)ob->data; + return bc_get_active_uvlayer_name(me); +} + +/* + * Returns name of Active UV Layer or empty String if no active UV Layer defined + */ +std::string bc_get_active_uvlayer_name(Mesh *me) +{ + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + if (num_layers) { + return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE)); + } + return ""; +} + +/* + * Returns UV Layer name or empty string if layer index is out of range + */ +std::string bc_get_uvlayer_name(Mesh *me, int layer) +{ + int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE); + if (num_layers && layer < num_layers) { + return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer)); + } + return ""; +} + +/********************************************************************** +* +* Return the list of Mesh objects with assigned UVtextures and Images +* Note: We need to create artificaial materials for each of them +* +***********************************************************************/ +std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers) +{ + std::set <Object *> UVObjects; + Base *base = (Base *)sce->base.first; + + while (base) { + Object *ob = base->object; + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + has_uvimage = true; + break; + } + } + } + } + } + + if (has_uvimage) { + UVObjects.insert(ob); + } + } + base = base->next; + } + return UVObjects; +} + +/********************************************************************** +* +* Return the list of UV Texture images from all exported Mesh Items +* Note: We need to create one artificial material for each Image. +* +***********************************************************************/ +std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers) +{ + std::set <Image *> UVImages; + Base *base = (Base *)sce->base.first; + + while (base) { + Object *ob = base->object; + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + if (UVImages.find(ima) == UVImages.end()) + UVImages.insert(ima); + } + } + } + } + } + } + base = base->next; + } + return UVImages; +} + +/********************************************************************** +* +* Return the list of UV Texture images for the given Object +* Note: We need to create one artificial material for each Image. +* +***********************************************************************/ +std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers) +{ + std::set <Image *> UVImages; + + bool has_uvimage = false; + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY); + + for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) { + if (all_uv_layers || active_uv_layer == i) + { + if (me->pdata.layers[i].type == CD_MTEXPOLY) { + MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { + + Image *ima = txface->tpage; + if (ima != NULL) { + if (UVImages.find(ima) == UVImages.end()) + UVImages.insert(ima); + } + } + } + } + } + } + return UVImages; +}
\ No newline at end of file diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 7fdbef3b6cb..5447c39e902 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -34,6 +34,7 @@ #include <vector> #include <map> +#include <set> #include <algorithm> extern "C" { @@ -53,8 +54,10 @@ extern "C" { #include "BKE_object.h" #include "BKE_DerivedMesh.h" #include "BKE_scene.h" +#include "BKE_idprop.h" } +#include "ImportSettings.h" #include "ExportSettings.h" #include "collada_internal.h" @@ -78,6 +81,7 @@ extern void bc_set_mark(Object *ob); extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n); extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type); +extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type); extern void bc_bubble_sort_by_Object_name(LinkNode *export_set); extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only); @@ -88,11 +92,32 @@ extern std::string bc_url_encode(std::string data); extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene); extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene); +extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size); + extern void bc_triangulate_mesh(Mesh *me); extern bool bc_is_leaf_bone(Bone *bone); extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); +extern void bc_sanitize_mat(float mat[4][4], int precision); + +extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key); +extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value); +extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]); + +extern float bc_get_property(Bone *bone, std::string key, float def); +extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]); +extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]); + +extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space); + +extern std::string bc_get_active_uvlayer_name(Object *ob); +extern std::string bc_get_active_uvlayer_name(Mesh *me); +extern std::string bc_get_uvlayer_name(Mesh *me, int layer); + +extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers); +extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers); +extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers); class BCPolygonNormalsIndices { |