From 8e2611102090939f90fd5414e3717866f240020b Mon Sep 17 00:00:00 2001 From: Gaia Clary Date: Sat, 28 May 2016 18:41:54 +0200 Subject: Collada: Adding support for bone roll and bone layers Differential Revision: https://developer.blender.org/D2034 --- source/blender/collada/ArmatureExporter.cpp | 15 +++ source/blender/collada/ArmatureImporter.cpp | 145 +++++---------------- source/blender/collada/ArmatureImporter.h | 31 ----- source/blender/collada/ExtraTags.cpp | 23 +++- source/blender/collada/ExtraTags.h | 11 +- source/blender/collada/collada_utils.cpp | 191 ++++++++++++++++++++++++++++ source/blender/collada/collada_utils.h | 48 +++++++ 7 files changed, 313 insertions(+), 151 deletions(-) (limited to 'source/blender/collada') diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp index 47a0ffda3c6..c8d92f4d329 100644 --- a/source/blender/collada/ArmatureExporter.cpp +++ b/source/blender/collada/ArmatureExporter.cpp @@ -67,12 +67,19 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce, std::list& child_objects) { // write bone nodes + + bArmature * armature = (bArmature *)ob_arm->data; + ED_armature_to_edit(armature); + bArmature *arm = (bArmature *)ob_arm->data; for (Bone *bone = (Bone *)arm->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); } void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone) @@ -174,7 +181,15 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, node.addExtraTechniqueParameter("blender", "connect", true); } } + std::string layers = BoneExtended::get_bone_layers(bone->layer); + node.addExtraTechniqueParameter("blender", "layer", layers); + bArmature *armature = (bArmature *)ob_arm->data; + EditBone *ebone = bc_get_edit_bone(armature, bone->name); + if (ebone && ebone->roll > 0) + { + node.addExtraTechniqueParameter("blender", "roll", ebone->roll); + } if (bc_is_leaf_bone(bone)) { node.addExtraTechniqueParameter("blender", "tip_x", bone->arm_tail[0] - bone->arm_head[0]); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 4c318cd97cc..496ca4efd06 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -50,19 +50,6 @@ static const char *bc_get_joint_name(T *node) return id.size() ? id.c_str() : node->getOriginalId().c_str(); } -static EditBone *get_edit_bone(bArmature * armature, char *name) { - EditBone *eBone; - - for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) { - if (STREQ(name, eBone->name)) - return eBone; - } - - return NULL; - -} - - ArmatureImporter::ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, Scene *sce, const ImportSettings *import_settings) : import_settings(import_settings), @@ -157,9 +144,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon if (parent) bone->parent = parent; float loc[3], size[3], rot[3][3]; - float angle; BoneExtended &be = add_bone_extended(bone, node); + int layer = be.get_bone_layers(); + if (layer) bone->layer = layer; + arm->layer |= layer; // ensure that all populated bone layers are visible after import float *tail = be.get_tail(); int use_connect = be.get_use_connect(); @@ -171,10 +160,16 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon case -1: break; // not defined } - mat4_to_loc_rot_size(loc, rot, size, mat); - mat3_to_vec_roll(rot, NULL, &angle); + if (be.has_roll()) { + bone->roll = be.get_roll(); + } + else { + 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]); add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero @@ -224,12 +219,12 @@ void ArmatureImporter::fix_leaf_bones(bArmature *armature, Bone *bone) if (bc_is_leaf_bone(bone)) { BoneExtended *be = extended_bones[bone->name]; - if (be == NULL || !be->has_custom_tail()) { + if (be == NULL || !be->has_tail()) { /* Collada only knows Joints, Here we guess a reasonable leaf bone length */ float leaf_length = (leaf_bone_length == FLT_MAX) ? 1.0 : leaf_bone_length; - EditBone *ebone = get_edit_bone(armature, bone->name); + EditBone *ebone = bc_get_edit_bone(armature, bone->name); float vec[3]; if (ebone->parent != NULL) { @@ -303,8 +298,8 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone BoneExtended *pbe = extended_bones[parentbone->name]; if (dominant_child != NULL) { /* Found a valid chain. Now connect current bone with that chain.*/ - EditBone *pebone = get_edit_bone(armature, parentbone->name); - EditBone *cebone = get_edit_bone(armature, dominant_child->get_name()); + 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]; @@ -467,6 +462,7 @@ void ArmatureImporter::create_armature_bones( ) clear_extended_boneset(); ED_armature_to_edit(armature); + armature->layer = 0; // layer is set according to imported bone set in create_bone() create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature); @@ -925,84 +921,6 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint) return found; } - -/** - * BoneExtended is a helper class needed for the Bone chain finder - * See ArmatureImporter::fix_leaf_bones() - * and ArmatureImporter::connect_bone_chains() - **/ - -BoneExtended::BoneExtended(EditBone *aBone) -{ - this->set_name(aBone->name); - this->chain_length = 0; - this->is_leaf = false; - this->tail[0] = 0.0f; - this->tail[1] = 0.5f; - this->tail[2] = 0.0f; - this->use_connect = -1; - this->has_tail = false; -} - -char *BoneExtended::get_name() -{ - return name; -} - -void BoneExtended::set_name(char *aName) -{ - BLI_strncpy(name, aName, MAXBONENAME); -} - -int BoneExtended::get_chain_length() -{ - return chain_length; -} - -void BoneExtended::set_chain_length(const int aLength) -{ - chain_length = aLength; -} - -void BoneExtended::set_leaf_bone(bool state) -{ - is_leaf = state; -} - -bool BoneExtended::is_leaf_bone() -{ - return is_leaf; -} - -void BoneExtended::set_tail(float vec[]) -{ - this->tail[0] = vec[0]; - this->tail[1] = vec[1]; - this->tail[2] = vec[2]; - this->has_tail = true; -} - -bool BoneExtended::has_custom_tail() -{ - return this->has_tail; -} - -float *BoneExtended::get_tail() -{ - return this->tail; -} - -void BoneExtended::set_use_connect(int use_connect) -{ - this->use_connect = use_connect; -} - -int BoneExtended::get_use_connect() -{ - return this->use_connect; -} - - BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node) { BoneExtended *be = new BoneExtended(bone); @@ -1014,23 +932,30 @@ BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Nod if (etit != uid_tags_map.end()) { float tail[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; - int use_connect = -1; + float roll = 0; + int use_connect = -1; + std::string layers; et = etit->second; - et->setData("tip_x", &tail[0]); - et->setData("tip_y", &tail[1]); - et->setData("tip_z", &tail[2]); - et->setData("connect", &use_connect); - if (!(tail[0] == FLT_MAX || tail[1] == FLT_MAX || tail[2] == FLT_MAX)) + bool has_tail = false; + has_tail |= et->setData("tip_x", &tail[0]); + has_tail |= et->setData("tip_y", &tail[1]); + has_tail |= et->setData("tip_z", &tail[2]); + + bool has_connect = et->setData("connect", &use_connect); + bool has_roll = et->setData("roll", &roll); + + layers = et->setData("layer", layers); + + if (has_tail && !has_connect) { - if (use_connect == -1) - { - use_connect = 0; // got a bone tail definition but no connect info -> bone is not connected - } + use_connect = 0; // got a bone tail definition but no connect info -> bone is not connected } - be->set_tail(tail); + be->set_bone_layers(layers); + if (has_tail) be->set_tail(tail); + if (has_roll) be->set_roll(roll); be->set_use_connect(use_connect); } be->set_leaf_bone(true); diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h index 4cef3d4fb38..fba8c5bd5d6 100644 --- a/source/blender/collada/ArmatureImporter.h +++ b/source/blender/collada/ArmatureImporter.h @@ -59,37 +59,6 @@ extern "C" { #define UNLIMITED_CHAIN_MAX INT_MAX #define MINIMUM_BONE_LENGTH 0.000001f -class BoneExtended { - -private: - char name[MAXBONENAME]; - int chain_length; - bool is_leaf; - float tail[3]; - bool use_connect; - bool has_tail; - -public: - - BoneExtended(EditBone *aBone); - - void set_name(char *aName); - char *get_name(); - - void set_chain_length(const int aLength); - int get_chain_length(); - - void set_leaf_bone(bool state); - bool is_leaf_bone(); - - void set_tail(float *vec); - float *get_tail(); - bool has_custom_tail(); - - void set_use_connect(int use_connect); - int get_use_connect(); -}; - class ArmatureImporter : private TransformReader { private: diff --git a/source/blender/collada/ExtraTags.cpp b/source/blender/collada/ExtraTags.cpp index 6af61432fda..ea225d8a4ae 100644 --- a/source/blender/collada/ExtraTags.cpp +++ b/source/blender/collada/ExtraTags.cpp @@ -85,32 +85,45 @@ std::string ExtraTags::asString(std::string tag, bool *ok) } -void ExtraTags::setData(std::string tag, short *data) +bool ExtraTags::setData(std::string tag, short *data) { bool ok = false; int tmp = asInt(tag, &ok); if (ok) *data = (short)tmp; + return ok; } -void ExtraTags::setData(std::string tag, int *data) + +bool ExtraTags::setData(std::string tag, int *data) { bool ok = false; int tmp = asInt(tag, &ok); if (ok) *data = tmp; + return ok; } -void ExtraTags::setData(std::string tag, float *data) + +bool ExtraTags::setData(std::string tag, float *data) { bool ok = false; float tmp = asFloat(tag, &ok); if (ok) *data = tmp; + return ok; } -void ExtraTags::setData(std::string tag, char *data) + +bool ExtraTags::setData(std::string tag, char *data) { bool ok = false; int tmp = asInt(tag, &ok); if (ok) *data = (char)tmp; + return ok; +} + +std::string ExtraTags::setData(std::string tag, std::string &data) +{ + bool ok = false; + std::string tmp = asString(tag, &ok); + return (ok) ? tmp : data; } - diff --git a/source/blender/collada/ExtraTags.h b/source/blender/collada/ExtraTags.h index 03a311a7e86..ad272dcba65 100644 --- a/source/blender/collada/ExtraTags.h +++ b/source/blender/collada/ExtraTags.h @@ -43,17 +43,18 @@ public: bool addTag(std::string tag, std::string data); /** Set given short pointer to value of tag, if it exists. */ - void setData(std::string tag, short *data); + bool setData(std::string tag, short *data); /** Set given int pointer to value of tag, if it exists. */ - void setData(std::string tag, int *data); + bool setData(std::string tag, int *data); /** Set given float pointer to value of tag, if it exists. */ - void setData(std::string tag, float *data); + bool setData(std::string tag, float *data); /** Set given char pointer to value of tag, if it exists. */ - void setData(std::string tag, char *data); - + bool setData(std::string tag, char *data); + std::string setData(std::string tag, std::string &data); + /** Return true if the extra tags is for specified profile. */ bool isProfile(std::string profile); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 30cf404cc3d..c510eb6e0e8 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -54,6 +54,8 @@ extern "C" { #include "BKE_scene.h" #include "BKE_DerivedMesh.h" +#include "ED_armature.h" + #include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" @@ -378,3 +380,192 @@ bool bc_is_leaf_bone(Bone *bone) } return true; } + +EditBone *bc_get_edit_bone(bArmature * armature, char *name) { + EditBone *eBone; + + for (eBone = (EditBone *)armature->edbo->first; eBone; eBone = eBone->next) { + if (STREQ(name, eBone->name)) + return eBone; + } + + return NULL; + +} +int bc_set_layer(int bitfield, int layer) +{ + return bc_set_layer(bitfield, layer, true); /* enable */ +} + +int bc_set_layer(int bitfield, int layer, bool enable) +{ + int bit = 1u << layer; + + if (enable) + bitfield |= bit; + else + bitfield &= ~bit; + + return bitfield; +} + +/** +* BoneExtended is a helper class needed for the Bone chain finder +* See ArmatureImporter::fix_leaf_bones() +* and ArmatureImporter::connect_bone_chains() +**/ + +BoneExtended::BoneExtended(EditBone *aBone) +{ + this->set_name(aBone->name); + this->chain_length = 0; + this->is_leaf = false; + this->tail[0] = 0.0f; + this->tail[1] = 0.5f; + this->tail[2] = 0.0f; + this->use_connect = -1; + this->roll = 0; + this->bone_layers = 0; + + this->has_custom_tail = false; + this->has_custom_roll = false; +} + +char *BoneExtended::get_name() +{ + return name; +} + +void BoneExtended::set_name(char *aName) +{ + BLI_strncpy(name, aName, MAXBONENAME); +} + +int BoneExtended::get_chain_length() +{ + return chain_length; +} + +void BoneExtended::set_chain_length(const int aLength) +{ + chain_length = aLength; +} + +void BoneExtended::set_leaf_bone(bool state) +{ + is_leaf = state; +} + +bool BoneExtended::is_leaf_bone() +{ + return is_leaf; +} + +void BoneExtended::set_roll(float roll) +{ + this->roll = roll; + this->has_custom_roll = true; +} + +bool BoneExtended::has_roll() +{ + return this->has_custom_roll; +} + +float BoneExtended::get_roll() +{ + return this->roll; +} + +void BoneExtended::set_tail(float vec[]) +{ + this->tail[0] = vec[0]; + this->tail[1] = vec[1]; + this->tail[2] = vec[2]; + this->has_custom_tail = true; +} + +bool BoneExtended::has_tail() +{ + return this->has_custom_tail; +} + +float *BoneExtended::get_tail() +{ + return this->tail; +} + +inline bool isInteger(const std::string & s) +{ + if (s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false; + + char * p; + strtol(s.c_str(), &p, 10); + + return (*p == 0); +} + +void BoneExtended::set_bone_layers(std::string layerString) +{ + std::stringstream ss(layerString); + std::istream_iterator begin(ss); + std::istream_iterator end; + std::vector layers(begin, end); + + for (std::vector::iterator it = layers.begin(); it != layers.end(); ++it) { + std::string layer = *it; + int index = -1; + + if (isInteger(layer)) + { + index = std::stoi(layer); + if (index < 0 || index > 31) + index - 1; + } + + if (index == -1) + { + //TODO + int x = index; + } + + if (index != -1) + { + this->bone_layers = bc_set_layer(this->bone_layers, index); + } + } +} + +std::string BoneExtended::get_bone_layers(int bitfield) +{ + std::string result = ""; + std::string sep = ""; + int bit = 1u; + + for (int i = 0; i < 32; i++) + { + if (bit & bitfield) + { + result += sep + std::to_string(i); + sep = " "; + } + bit = bit << 1; + } + return result; +} + +int BoneExtended::get_bone_layers() +{ + return (bone_layers == 0) ? 1 : bone_layers; // ensure that the bone is in at least one bone layer! +} + + +void BoneExtended::set_use_connect(int use_connect) +{ + this->use_connect = use_connect; +} + +int BoneExtended::get_use_connect() +{ + return this->use_connect; +} diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 7f8e93736b5..e9f84afef61 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -46,6 +46,7 @@ extern "C" { #include "BLI_linklist.h" #include "BLI_utildefines.h" +#include "BLI_string.h" #include "BKE_context.h" #include "BKE_object.h" @@ -88,6 +89,9 @@ extern void bc_match_scale(std::vector *objects_done, UnitConverter &u 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); class BCPolygonNormalsIndices { @@ -105,4 +109,48 @@ class BCPolygonNormalsIndices }; +class BoneExtended { + +private: + char name[MAXBONENAME]; + int chain_length; + bool is_leaf; + float tail[3]; + float roll; + + int bone_layers; + bool use_connect; + bool has_custom_tail; + bool has_custom_roll; + +public: + + BoneExtended(EditBone *aBone); + + void set_name(char *aName); + char *get_name(); + + void set_chain_length(const int aLength); + int get_chain_length(); + + void set_leaf_bone(bool state); + bool is_leaf_bone(); + + void set_bone_layers(std::string layers); + int get_bone_layers(); + static std::string get_bone_layers(int bitfield); + + void set_roll(float roll); + bool has_roll(); + float get_roll(); + + void set_tail(float *vec); + float *get_tail(); + bool has_tail(); + + void set_use_connect(int use_connect); + int get_use_connect(); +}; + + #endif -- cgit v1.2.3