diff options
Diffstat (limited to 'source/blender/collada')
-rw-r--r-- | source/blender/collada/AnimationImporter.cpp | 2 | ||||
-rw-r--r-- | source/blender/collada/ArmatureExporter.cpp | 68 | ||||
-rw-r--r-- | source/blender/collada/ArmatureImporter.cpp | 60 | ||||
-rw-r--r-- | source/blender/collada/ControllerExporter.cpp | 114 | ||||
-rw-r--r-- | source/blender/collada/ExportSettings.h | 2 | ||||
-rw-r--r-- | source/blender/collada/ImportSettings.h | 1 | ||||
-rw-r--r-- | source/blender/collada/TransformReader.cpp | 23 | ||||
-rw-r--r-- | source/blender/collada/TransformReader.h | 5 | ||||
-rw-r--r-- | source/blender/collada/TransformWriter.cpp | 7 | ||||
-rw-r--r-- | source/blender/collada/TransformWriter.h | 3 | ||||
-rw-r--r-- | source/blender/collada/collada.cpp | 9 | ||||
-rw-r--r-- | source/blender/collada/collada.h | 8 | ||||
-rw-r--r-- | source/blender/collada/collada_internal.cpp | 12 | ||||
-rw-r--r-- | source/blender/collada/collada_internal.h | 6 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.cpp | 232 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.h | 16 |
16 files changed, 387 insertions, 181 deletions
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index 3801c9300df..bd47ee0214d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -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 40065956ecb..49722873a91 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -256,47 +256,57 @@ 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); + } } } + bc_sanitize_mat(mat, 6); // XXX: Make this optional ? TransformWriter::add_node_transform(node, mat, NULL); + } std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob) diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index f4ce3992771..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. @@ -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) { @@ -130,18 +134,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon // create a bone even if there's no joint data for it (i.e. it has no influence) if (!bone_is_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); - } - + get_node_mat(mat, node, NULL, NULL, parent_mat); } if (parent) bone->parent = parent; @@ -157,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()) { @@ -173,6 +167,15 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon 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) */ @@ -274,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); @@ -290,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; } } @@ -309,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); @@ -322,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 a868adc1e66..5444c9dfa6b 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -463,81 +463,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) { @@ -580,30 +505,35 @@ 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); - + bc_sanitize_mat(inv_bind_mat, 6); // XXX: Make this optional ? source.appendValues(inv_bind_mat); } } diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 9451cac9dae..03e380dc198 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -51,7 +51,9 @@ public: bool use_blender_profile; bool sort_by_name; BC_export_transformation_type export_transformation_type; + bool open_sim; + bool keep_bind_info; char *filepath; LinkNode *export_set; 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/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..c0784ca8eb5 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; DocumentImporter imp(C, &import_settings); if (imp.import()) return 1; @@ -87,7 +89,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 keep_bind_info) { ExportSettings export_settings; @@ -113,6 +117,7 @@ int collada_export(Scene *sce, export_settings.export_transformation_type = export_transformation_type; export_settings.open_sim = open_sim != 0; + export_settings.keep_bind_info = keep_bind_info; 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..09acc4a064b 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -58,7 +58,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, @@ -81,9 +83,9 @@ 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 keep_bind_info); #ifdef __cplusplus } diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 70b44ebc222..6ebde6bd773 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -162,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 diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 482dbf9ab31..1c7aa160f57 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); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 2efa8b21d81..407f0799014 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -33,6 +33,7 @@ #include "COLLADAFWMeshVertexData.h" #include "collada_utils.h" +#include "ExportSettings.h" extern "C" { #include "DNA_modifier_types.h" @@ -352,6 +353,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 +635,212 @@ 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); + +} + +/* + To get rid of those lengthy float values which make the numbers unreadable. +*/ +float bc_sanitize_float(float value, float precision) +{ + float result = floor((value * pow(10, precision) + 0.5)) / pow(10, precision); + if (abs(result) < 1 / pow(10, precision)) { + result = 0; + } + return result; +} + +/* + Make 4*4 matrices better readable +*/ +void bc_sanitize_mat(float mat[4][4], float precision) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + mat[i][j] = bc_sanitize_float(mat[i][j], precision); +}
\ No newline at end of file diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 7fdbef3b6cb..b98f8bfb188 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -53,8 +53,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" @@ -88,11 +90,25 @@ 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 float bc_sanitize_float(float value, float precision); +extern void bc_sanitize_mat(float mat[4][4], float 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); class BCPolygonNormalsIndices { |