[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [22060] branches/soc-2009-chingachgook/ source/blender/collada/DocumentImporter.cpp: COLLADA importer is reading armature from DAE.
Arystanbek Dyussenov
arystan.d at gmail.com
Thu Jul 30 19:05:16 CEST 2009
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. @@
More information about the Bf-blender-cvs
mailing list