[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [22040] branches/soc-2009-chingachgook/ source/blender/collada/DocumentImporter.cpp: - setting leaf bone size to minimum bone size in bone branch
Arystanbek Dyussenov
arystan.d at gmail.com
Thu Jul 30 08:35:28 CEST 2009
Revision: 22040
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=22040
Author: kazanbas
Date: 2009-07-30 08:35:27 +0200 (Thu, 30 Jul 2009)
Log Message:
-----------
- setting leaf bone size to minimum bone size in bone branch
- trying to determine bone orientation from joint matrix
Looks like DAE joint matrix orientation cannot be relied upon as a source for bone direction. It can be axis-aligned or pointing in
totally different direction:
http://img75.imageshack.us/img75/8778/flufty.png
It seems to me the best solution is to add a bone with custom draw type that has no pointing direction, sphere for example. Will code
this after merge!
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 03:26:33 UTC (rev 22039)
+++ branches/soc-2009-chingachgook/source/blender/collada/DocumentImporter.cpp 2009-07-30 06:35:27 UTC (rev 22040)
@@ -73,12 +73,13 @@
#include "MEM_guardedalloc.h"
#include "DocumentImporter.h"
+#include "collada_internal.h"
#include <string>
#include <map>
-// #define COLLADA_DEBUG
+#define COLLADA_DEBUG
char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
@@ -121,39 +122,6 @@
return "UNKNOWN";
}
-class UnitConverter
-{
-private:
- COLLADAFW::FileInfo::Unit unit;
- COLLADAFW::FileInfo::UpAxisType up_axis;
-
-public:
-
- UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP) {}
-
- void read_asset(const COLLADAFW::FileInfo* asset)
- {
- }
-
- // TODO
- // convert vector vec from COLLADA format to Blender
- void convertVec3(float *vec)
- {
- }
-
- // TODO need also for angle conversion, time conversion...
-
- void mat4_from_dae_mat4(float out[][4], const COLLADABU::Math::Matrix4& in) {
- // in DAE, matrices use columns vectors, (see comments in COLLADABUMathMatrix4.h)
- // so here, to make a blender matrix, we simply swap columns and rows
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- out[i][j] = in[j][i];
- }
- }
- }
-};
-
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > TexIndexTextureArrayMap;
class ArmatureImporter
@@ -170,6 +138,17 @@
std::map<int, JointData> joint_index_to_joint_info_map;
std::map<COLLADAFW::UniqueId, int> joint_id_to_joint_index_map;
+ struct LeafBone {
+ // COLLADAFW::Node *node;
+ EditBone *bone;
+ float mat[4][4]; // bone matrix, derived from inv_bind_mat
+ };
+ std::vector<LeafBone> leaf_bones;
+ int bone_direction_row;
+ float leaf_bone_length;
+ int totbone;
+ float min_angle; // minimum angle between bone head-tail and a row of bone matrix
+
/*
struct ArmatureData {
bArmature *arm;
@@ -196,8 +175,14 @@
return &joint_index_to_joint_info_map[joint_index];
}
- void create_bone(COLLADAFW::Node *node, EditBone *parent, bArmature *arm)
+ const char *get_dae_name(COLLADAFW::Node *node)
{
+ const std::string& name = node->getName();
+ return name.size() ? name.c_str() : node->getOriginalId().c_str();
+ }
+
+ void create_bone(COLLADAFW::Node *node, EditBone *parent, int totchild, float parent_mat[][4], bArmature *arm)
+ {
JointData* jd = get_joint_data(node);
if (jd) {
@@ -207,45 +192,145 @@
Mat4Invert(mat, jd->inv_bind_mat);
// TODO rename from Node "name" attrs later
- EditBone *bone = addEditBone(arm, "Bone");
+ EditBone *bone = addEditBone(arm, (char*)get_dae_name(node));
if (parent) bone->parent = parent;
// set head
VecCopyf(bone->head, mat[3]);
- // set tail, can'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)
+ if (parent && totchild == 1) {
VecCopyf(parent->tail, bone->head);
+ // derive leaf bone length
+ float length = VecLenf(parent->head, bone->head);
+ if (length < leaf_bone_length || totbone == 0) {
+ leaf_bone_length = length;
+ }
+
+ // 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);
+#endif
+ 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]));
+#endif
+ 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));
+#endif
+ 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);
+ }
+
+ totbone++;
+
COLLADAFW::NodePointerArray& children = node->getChildNodes();
for (int i = 0; i < children.getCount(); i++) {
- create_bone(children[i], bone, arm);
+ 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;
+
+ leaf.bone = bone;
+ Mat4CpyMat4(leaf.mat, mat);
+
+ leaf_bones.push_back(leaf);
+ }
}
}
+ void fix_leaf_bones()
+ {
+ 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]);
+ VecMulf(vec, leaf_bone_length);
+
+ VecCopyf(leaf.bone->tail, leaf.bone->head);
+ VecAddf(leaf.bone->tail, leaf.bone->head, vec);
+ }
+ }
+
+ /*
+ Object *find_armature(COLLADAFW::Node *node)
+ {
+ JointData* jd = get_joint_data(node);
+ if (jd) return jd->ob_arm;
+
+ COLLADAFW::NodePointerArray& children = node->getChildNodes();
+ for (int i = 0; i < children.getCount(); i++) {
+ Object *ob_arm = find_armature(children[i]);
+ if (ob_arm) return ob_arm;
+ }
+
+ return NULL;
+ }
+ */
+
void create_bone_branch(COLLADAFW::Node *root)
{
+ Object *ob_arm;
+
JointData* jd = get_joint_data(root);
- if (!jd) return;
+ if (jd) {
+ ob_arm = jd->ob_arm;
+ }
+ // 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;
+ }
+ }
- Object *ob_arm = jd->ob_arm;
-
+ if (!ob_arm) {
+ fprintf(stderr, "Cannot find armature for %s\n", get_dae_name(root));
+ return;
+ }
+
// enter armature edit mode
ED_armature_to_edit(ob_arm);
+ totbone = 0;
+ leaf_bones.clear();
+ bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
+ leaf_bone_length = 0.1f;
+ min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix
+
COLLADAFW::NodePointerArray& children = root->getChildNodes();
for (int i = 0; i < children.getCount(); i++) {
- create_bone(children[i], NULL, (bArmature*)ob_arm->data);
+ create_bone(children[i], NULL, children.getCount(), NULL, (bArmature*)ob_arm->data);
}
+ // handle leaf bones
+ fix_leaf_bones();
+
// exit armature edit mode
ED_armature_from_edit(scene, ob_arm);
+ ED_armature_edit_free(ob_arm);
+ DAG_object_flush_update(scene, ob_arm, OB_RECALC_OB|OB_RECALC_DATA);
}
public:
@@ -265,7 +350,6 @@
// here we add bones to armature, having armatures previously created in write_controller
void build_armatures()
{
- this->scene = scene;
std::vector<COLLADAFW::Node*>::iterator it;
for (it = root_joints.begin(); it != root_joints.end(); it++) {
create_bone_branch(*it);
@@ -289,7 +373,7 @@
int i;
for (i = 0; i < skin->getJointsCount(); i++) {
JointData jd;
- unit_converter->mat4_from_dae_mat4(jd.inv_bind_mat, inv_bind_mats[i]);
+ unit_converter->mat4_from_dae(jd.inv_bind_mat, inv_bind_mats[i]);
joint_index_to_joint_info_map[i] = jd;
}
@@ -307,13 +391,13 @@
if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
- Object *ob_arm = add_object(this->scene, OB_ARMATURE);
+ Object *ob_arm = add_object(scene, OB_ARMATURE);
COLLADAFW::SkinController *skinco = (COLLADAFW::SkinController*)controller;
const COLLADAFW::UniqueId& id = skinco->getSkinControllerData();
// to find geom id by controller id
- this->controller_id_to_geom_id_map[skin_id] = skinco->getSource();
+ controller_id_to_geom_id_map[skin_id] = skinco->getSource();
// "Node" ids
const COLLADAFW::UniqueIdArray& joint_ids = skinco->getJoints();
@@ -373,9 +457,27 @@
void print()
{
fprintf(stderr, "UVs:\n");
- COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
- for (int i = 0; i < values->getCount(); i += 2) {
- fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]);
+ switch(mVData->getType()) {
+ case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
+ {
+ COLLADAFW::ArrayPrimitiveType<float>* values = mVData->getFloatValues();
+ if (values->getCount()) {
+ for (int i = 0; i < values->getCount(); i += 2) {
+ fprintf(stderr, "%.1f, %.1f\n", (*values)[i], (*values)[i+1]);
+ }
+ }
+ }
+ break;
+ case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
+ {
+ COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
+ if (values->getCount()) {
+ for (int i = 0; i < values->getCount(); i += 2) {
+ fprintf(stderr, "%.1f, %.1f\n", (float)(*values)[i], (float)(*values)[i+1]);
+ }
+ }
+ }
+ break;
}
fprintf(stderr, "\n");
}
@@ -391,8 +493,8 @@
uv[0] = (*values)[uv_index[0]];
uv[1] = (*values)[uv_index[1]];
- break;
}
+ break;
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
{
COLLADAFW::ArrayPrimitiveType<double>* values = mVData->getDoubleValues();
@@ -400,8 +502,8 @@
uv[0] = (float)(*values)[uv_index[0]];
uv[1] = (float)(*values)[uv_index[1]];
- break;
}
+ break;
}
}
};
@@ -1086,6 +1188,8 @@
Mat3One(rot);
// transform Object and store animation linking info
+ // TODO: apply transforms sequentially and then extract location/scale/rotation from final matrix
+ // this will be the correct way
for (k = 0; k < node->getTransformations().getCount(); k ++) {
COLLADAFW::Transformation *tm = node->getTransformations()[k];
@@ -1499,6 +1603,7 @@
return (*values)[i];
else return 0;
}
+ break;
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
{
COLLADAFW::ArrayPrimitiveType<double> *values = array.getDoubleValues();
@@ -1506,6 +1611,7 @@
return (float)(*values)[i];
else return 0;
}
+ break;
}
}
More information about the Bf-blender-cvs
mailing list