Revision: 22060
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=22060
Author:   kazanbas
Date:     2009-07-30 19:05:16 +0200 (Thu, 30 Jul 2009)

Log Message:
-----------
COLLADA importer is reading armature from DAE. "Leaf" bones, bones having more 
than one child and zero-length bones get the size of 
a minimum bone length in skeleton and are assigned a sphere shape.

Also fixed rotation reading by re-ordering items in matrix multiplication.

Images:
http://img339.imageshack.us/img339/8778/flufty.png
http://img117.imageshack.us/img117/4641/astroboy.png

Modified Paths:
--------------
    branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp

Modified: 
branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp
===================================================================
--- branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp  
2009-07-30 16:38:00 UTC (rev 22059)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp  
2009-07-30 17:05:16 UTC (rev 22060)
@@ -17,13 +17,14 @@
 #include "COLLADAFWMeshPrimitiveWithFaceVertexCount.h"
 #include "COLLADAFWNode.h"
 #include "COLLADAFWPolygons.h"
-#include "COLLADAFWRotate.h"
 #include "COLLADAFWSampler.h"
-#include "COLLADAFWScale.h"
 #include "COLLADAFWSkinController.h"
 #include "COLLADAFWSkinControllerData.h"
 #include "COLLADAFWTransformation.h"
 #include "COLLADAFWTranslate.h"
+#include "COLLADAFWRotate.h"
+#include "COLLADAFWScale.h"
+#include "COLLADAFWMatrix.h"
 #include "COLLADAFWTypes.h"
 #include "COLLADAFWVisualScene.h"
 #include "COLLADAFWFileInfo.h"
@@ -53,6 +54,7 @@
 #include "BKE_image.h"
 #include "BKE_material.h"
 #include "BKE_utildefines.h"
+#include "BKE_action.h"
 
 #include "BLI_arithb.h"
 #include "BLI_listbase.h"
@@ -78,6 +80,8 @@
 #include <string>
 #include <map>
 
+#include <math.h>
+#include <float.h>
 
 #define COLLADA_DEBUG
 
@@ -141,22 +145,24 @@
        struct LeafBone {
                // COLLADAFW::Node *node;
                EditBone *bone;
+               char name[32];
                float mat[4][4]; // bone matrix, derived from inv_bind_mat
        };
        std::vector<LeafBone> leaf_bones;
-       int bone_direction_row;
+       // int bone_direction_row; // XXX not used
        float leaf_bone_length;
        int totbone;
-       float min_angle; // minimum angle between bone head-tail and a row of 
bone matrix
+       // XXX not used
+       // float min_angle; // minimum angle between bone head-tail and a row 
of bone matrix
 
-       /*
-       struct ArmatureData {
-               bArmature *arm;
-               COLLADAFW::SkinController *controller;
+       struct ArmatureJoints {
+               Object *ob_arm;
+               std::vector<COLLADAFW::Node*> root_joints;
        };
-       std::map<COLLADAFW::UniqueId, ArmatureData> 
controller_id_to_arm_info_map;
-       */
+       std::vector<ArmatureJoints> armature_joints;
 
+       Object *empty; // empty for leaf bones
+
        std::vector<COLLADAFW::Node*> root_joints;
        std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> 
controller_id_to_geom_id_map;
 
@@ -185,86 +191,177 @@
        {
                JointData* jd = get_joint_data(node);
 
+               float mat[4][4];
+
                if (jd) {
-                       float mat[4][4];
-
                        // get original world-space matrix
                        Mat4Invert(mat, jd->inv_bind_mat);
+               }
+               // create a bone even if there's no jd for it (i.e. it has no 
influence)
+               else {
+                       float obmat[4][4];
 
-                       // TODO rename from Node "name" attrs later
-                       EditBone *bone = addEditBone(arm, 
(char*)get_dae_name(node));
+                       // object-space
+                       get_node_mat(obmat, node);
 
-                       if (parent) bone->parent = parent;
+                       // get world-space
+                       if (parent)
+                               Mat4MulMat4(mat, obmat, parent_mat);
+                       else
+                               Mat4CpyMat4(mat, obmat);
+               }
 
-                       // set head
-                       VecCopyf(bone->head, mat[3]);
+               // TODO rename from Node "name" attrs later
+               EditBone *bone = addEditBone(arm, (char*)get_dae_name(node));
 
-                       // set parent tail
-                       if (parent && totchild == 1) {
-                               VecCopyf(parent->tail, bone->head);
+               if (parent) bone->parent = parent;
 
-                               // derive leaf bone length
-                               float length = VecLenf(parent->head, 
bone->head);
-                               if (length < leaf_bone_length || totbone == 0) {
-                                       leaf_bone_length = length;
-                               }
+               // set head
+               VecCopyf(bone->head, mat[3]);
 
-                               // and which row in mat is bone direction
-                               float vec[3];
-                               VecSubf(vec, parent->tail, parent->head);
+               // set tail, don't set it to head because 0-length bones are 
not allowed
+               float vec[3] = {0.0f, 0.5f, 0.0f};
+               VecAddf(bone->tail, bone->head, vec);
+
+               // set parent tail
+               if (parent && totchild == 1) {
+                       VecCopyf(parent->tail, bone->head);
+
+                       // derive leaf bone length
+                       float length = VecLenf(parent->head, parent->tail);
+                       if ((length < leaf_bone_length || totbone == 0) && 
length > FLT_EPSILON) {
+                               leaf_bone_length = length;
+                       }
+
+                       // treat zero-sized bone like a leaf bone
+                       if (length < FLT_EPSILON) {
+                               add_leaf_bone(parent_mat, parent);
+                       }
+
+                       /*
+#if 0
+                       // and which row in mat is bone direction
+                       float vec[3];
+                       VecSubf(vec, parent->tail, parent->head);
 #ifdef COLLADA_DEBUG
-                               printvecf("tail - head", vec);
-                               printmatrix4("matrix", parent_mat);
+                       printvecf("tail - head", vec);
+                       printmatrix4("matrix", parent_mat);
 #endif
-                               for (int i = 0; i < 3; i++) {
+                       for (int i = 0; i < 3; i++) {
 #ifdef COLLADA_DEBUG
-                                       char *axis_names[] = {"X", "Y", "Z"};
-                                       printf("%s-axis length is %f\n", 
axis_names[i], VecLength(parent_mat[i]));
+                               char *axis_names[] = {"X", "Y", "Z"};
+                               printf("%s-axis length is %f\n", axis_names[i], 
VecLength(parent_mat[i]));
 #endif
-                                       float angle = VecAngle2(vec, 
parent_mat[i]);
-                                       if (angle < min_angle) {
+                               float angle = VecAngle2(vec, parent_mat[i]);
+                               if (angle < min_angle) {
 #ifdef COLLADA_DEBUG
-                                               printvecf("picking", 
parent_mat[i]);
-                                               printf("^ %s axis of %s's 
matrix\n", axis_names[i], get_dae_name(node));
+                                       printvecf("picking", parent_mat[i]);
+                                       printf("^ %s axis of %s's matrix\n", 
axis_names[i], get_dae_name(node));
 #endif
-                                               bone_direction_row = i;
-                                               min_angle = angle;
-                                       }
+                                       bone_direction_row = i;
+                                       min_angle = angle;
                                }
                        }
-                       else {
-                               // set tail anyway, don't set it to head 
because 0-length bones are not allowed
-                               float vec[3] = {0.0f, 0.5f, 0.0f};
-                               VecAddf(bone->tail, bone->head, vec);
-                       }
+#endif
+                       */
+               }
 
-                       totbone++;
+               totbone++;
 
-                       COLLADAFW::NodePointerArray& children = 
node->getChildNodes();
-                       for (int i = 0; i < children.getCount(); i++) {
-                               create_bone(children[i], bone, 
children.getCount(), mat, arm);
-                       }
+               COLLADAFW::NodePointerArray& children = node->getChildNodes();
+               for (int i = 0; i < children.getCount(); i++) {
+                       create_bone(children[i], bone, children.getCount(), 
mat, arm);
+               }
 
-                       // in second case it's not a leaf bone, but we handle 
it the same way
-                       if (!children.getCount() || children.getCount() > 1) {
-                               LeafBone leaf;
+               // in second case it's not a leaf bone, but we handle it the 
same way
+               if (!children.getCount() || children.getCount() > 1) {
+                       add_leaf_bone(mat, bone);
+               }
+       }
 
-                               leaf.bone = bone;
-                               Mat4CpyMat4(leaf.mat, mat);
+       void add_leaf_bone(float mat[][4], EditBone *bone)
+       {
+               LeafBone leaf;
 
-                               leaf_bones.push_back(leaf);
+               leaf.bone = bone;
+               Mat4CpyMat4(leaf.mat, mat);
+               BLI_strncpy(leaf.name, bone->name, sizeof(leaf.name));
+
+               leaf_bones.push_back(leaf);
+       }
+
+       void get_node_mat(float mat[][4], COLLADAFW::Node *node)
+       {
+               float cur[4][4];
+               float copy[4][4];
+
+               Mat4One(mat);
+               
+               for (int i = 0; i < node->getTransformations().getCount(); i++) 
{
+
+                       COLLADAFW::Transformation *tm = 
node->getTransformations()[i];
+                       COLLADAFW::Transformation::TransformationType type = 
tm->getTransformationType();
+
+                       switch(type) {
+                       case COLLADAFW::Transformation::TRANSLATE:
+                               {
+                                       COLLADAFW::Translate *tra = 
(COLLADAFW::Translate*)tm;
+                                       COLLADABU::Math::Vector3& t = 
tra->getTranslation();
+
+                                       Mat4One(cur);
+                                       cur[3][0] = (float)t[0];
+                                       cur[3][1] = (float)t[1];
+                                       cur[3][2] = (float)t[2];
+                               }
+                               break;
+                       case COLLADAFW::Transformation::ROTATE:
+                               {
+                                       COLLADAFW::Rotate *ro = 
(COLLADAFW::Rotate*)tm;
+                                       COLLADABU::Math::Vector3& raxis = 
ro->getRotationAxis();
+                                       float angle = 
(float)(ro->getRotationAngle() * M_PI / 180.0f);
+                                       float axis[] = {raxis[0], raxis[1], 
raxis[2]};
+                                       float quat[4];
+                                       float rot_copy[3][3];
+                                       float mat[3][3];
+                                       AxisAngleToQuat(quat, axis, angle);
+                                       
+                                       QuatToMat4(quat, cur);
+                               }
+                               break;
+                       case COLLADAFW::Transformation::SCALE:
+                               {
+                                       COLLADABU::Math::Vector3& s = 
((COLLADAFW::Scale*)tm)->getScale();
+                                       float size[3] = {(float)s[0], 
(float)s[1], (float)s[2]};
+                                       SizeToMat4(size, cur);
+                               }
+                               break;
+                       case COLLADAFW::Transformation::MATRIX:
+                               {
+                                       unit_converter->mat4_from_dae(cur, 
((COLLADAFW::Matrix*)tm)->getMatrix());
+                               }
+                               break;
+                       case COLLADAFW::Transformation::LOOKAT:
+                       case COLLADAFW::Transformation::SKEW:
+                               fprintf(stderr, "LOOKAT and SKEW 
transformations are not supported yet.\n");
+                               break;
                        }
+
+                       Mat4CpyMat4(copy, mat);
+                       Mat4MulMat4(mat, cur, copy);
                }
        }
 
        void fix_leaf_bones()
        {
+               // just setting tail for leaf bones here
+
                std::vector<LeafBone>::iterator it;
                for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
                        LeafBone& leaf = *it;
-                       float vec[3];
 
-                       VecCopyf(vec, leaf.mat[bone_direction_row]);
+                       // pointing up
+                       float vec[3] = {0.0f, 0.0f, 1.0f};
+
                        VecMulf(vec, leaf_bone_length);
 
                        VecCopyf(leaf.bone->tail, leaf.bone->head);
@@ -272,7 +369,35 @@
                }
        }
 
-       /*
+       void set_leaf_bone_shapes(Object *ob_arm)
+       {
+               bPose *pose = ob_arm->pose;
+
+               std::vector<LeafBone>::iterator it;
+               for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
+                       LeafBone& leaf = *it;
+
+                       bPoseChannel *pchan = get_pose_channel(pose, leaf.name);
+                       if (pchan) {
+                               pchan->custom = get_empty_for_leaves();
+                       }
+                       else {
+                               fprintf(stderr, "Cannot find a pose channel for 
leaf bone %s\n", leaf.name);
+                       }
+               }
+
+       }
+
+       Object *get_empty_for_leaves()
+       {
+               if (empty) return empty;
+               
+               empty = add_object(scene, OB_EMPTY);
+               empty->empty_drawtype = OB_EMPTY_SPHERE;
+
+               return empty;
+       }
+
        Object *find_armature(COLLADAFW::Node *node)
        {
                JointData* jd = get_joint_data(node);
@@ -286,88 +411,102 @@
 
                return NULL;
        }
-       */
 
-       void create_bone_branch(COLLADAFW::Node *root)
+       ArmatureJoints& get_armature_joints(Object *ob_arm)
        {
-               Object *ob_arm;
-               
-               JointData* jd = get_joint_data(root);
-               if (jd) {
-                       ob_arm = jd->ob_arm;
+               // try finding it
+               std::vector<ArmatureJoints>::iterator it;
+               for (it = armature_joints.begin(); it != armature_joints.end(); 
it++) {
+                       if ((*it).ob_arm == ob_arm) return *it;
                }
-               // sometimes root joint may not be in <controller>, then we get 
armature from the first child
-               else {
-                       COLLADAFW::NodePointerArray& children = 
root->getChildNodes();
-                       if (children.getCount()) {
-                               jd = get_joint_data(children[0]);
-                               if (jd) ob_arm = jd->ob_arm;
-                       }
-               }
 
-               if (!ob_arm) {
-                       fprintf(stderr, "Cannot find armature for %s\n", 
get_dae_name(root));
-                       return;
-               }
+               // not found, create one
+               ArmatureJoints aj;
+               aj.ob_arm = ob_arm;
+               armature_joints.push_back(aj);
 
+               return armature_joints.back();
+       }
+

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to