Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt4
-rw-r--r--config/linux2-config.py6
-rw-r--r--source/blender/blenkernel/BKE_texture.h2
-rw-r--r--source/blender/blenkernel/intern/texture.c2
-rw-r--r--source/blender/blenlib/BLI_util.h2
-rw-r--r--source/blender/blenlib/intern/util.c2
-rw-r--r--source/blender/collada/DocumentExporter.cpp2
-rw-r--r--source/blender/collada/DocumentImporter.cpp1046
-rw-r--r--source/blender/collada/collada_internal.h11
9 files changed, 908 insertions, 169 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 100d6065c77..602fec4b759 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,8 +216,8 @@ IF(UNIX AND NOT APPLE)
IF (WITH_OPENCOLLADA)
SET(OPENCOLLADA /usr/local/opencollada CACHE FILEPATH "OpenCollada Directory")
- SET(OPENCOLLADA_LIBPATH ${OPENCOLLADA})
- SET(OPENCOLLADA_LIB OpenCollada)
+ SET(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib)
+ SET(OPENCOLLADA_LIB OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre ftoa Buffer)
SET(OPENCOLLADA_INC ${OPENCOLLADA})
SET(PCRE /usr CACHE FILEPATH "PCRE Directory")
SET(PCRE_LIBPATH ${PCRE}/lib)
diff --git a/config/linux2-config.py b/config/linux2-config.py
index 3eccb913932..3e40b7af416 100644
--- a/config/linux2-config.py
+++ b/config/linux2-config.py
@@ -155,9 +155,9 @@ WITH_BF_COLLADA = False
BF_COLLADA = '#source/blender/collada'
BF_COLLADA_INC = '${BF_COLLADA}'
BF_COLLADA_LIB = 'bf_collada'
-BF_OPENCOLLADA = ''
-BF_OPENCOLLADA_LIB = 'OpenCollada'
-BF_OPENCOLLADA_LIBPATH = '/usr/lib'
+BF_OPENCOLLADA = '/usr'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre Buffer ftoa'
+BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
BF_PCRE = ''
BF_PCRE_LIB = 'pcre'
BF_PCRE_LIBPATH = '/usr/lib'
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index b9dc5916e69..95ada45f5d8 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -62,7 +62,7 @@ int do_colorband(struct ColorBand *coba, float in, float out[4]);
void colorband_table_RGBA(struct ColorBand *coba, float **array, int *size);
void default_tex(struct Tex *tex);
-struct Tex *add_texture(char *name);
+struct Tex *add_texture(const char *name);
void default_mtex(struct MTex *mtex);
struct MTex *add_mtex(void);
struct Tex *copy_texture(struct Tex *tex);
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 0171c58f2c6..818e6195049 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -518,7 +518,7 @@ void default_tex(Tex *tex)
/* ------------------------------------------------------------------------- */
-Tex *add_texture(char *name)
+Tex *add_texture(const char *name)
{
Tex *tex;
diff --git a/source/blender/blenlib/BLI_util.h b/source/blender/blenlib/BLI_util.h
index 7642b71eea0..ca483903d46 100644
--- a/source/blender/blenlib/BLI_util.h
+++ b/source/blender/blenlib/BLI_util.h
@@ -61,7 +61,7 @@ void BLI_split_dirfile_basic(const char *string, char *dir, char *file);
void BLI_join_dirfile(char *string, const char *dir, const char *file);
void BLI_getlastdir(const char* dir, char *last, int maxlen);
int BLI_testextensie(const char *str, const char *ext);
-void BLI_uniquename(struct ListBase *list, void *vlink, char defname[], char delim, short name_offs, short len);
+void BLI_uniquename(struct ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len);
void BLI_newname(char * name, int add);
int BLI_stringdec(char *string, char *kop, char *start, unsigned short *numlen);
void BLI_stringenc(char *string, char *kop, char *start, unsigned short numlen, int pic);
diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c
index 39afced92bc..5ff4dfe4e96 100644
--- a/source/blender/blenlib/intern/util.c
+++ b/source/blender/blenlib/intern/util.c
@@ -223,7 +223,7 @@ void BLI_newname(char *name, int add)
* defname: the name that should be used by default if none is specified already
* delim: the character which acts as a delimeter between parts of the name
*/
-void BLI_uniquename(ListBase *list, void *vlink, char defname[], char delim, short name_offs, short len)
+void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len)
{
Link *link;
char tempname[128];
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index fac7b2c882a..c3550dfd408 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -673,7 +673,7 @@ protected:
copy_m4_m4(local, mat);
}
- TransformBase::decompose(local, loc, rot, size);
+ TransformBase::decompose(local, loc, rot, NULL, size);
/*
// this code used to create a single <rotate> representing object rotation
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index f50df355a82..9ebcc8b191f 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -1,3 +1,7 @@
+// TODO:
+// * name imported objects
+// * import object rotation as euler
+
#include "COLLADAFWRoot.h"
#include "COLLADAFWIWriter.h"
#include "COLLADAFWStableHeaders.h"
@@ -51,6 +55,7 @@ extern "C"
#include "BLI_util.h"
#include "BKE_displist.h"
#include "BLI_math.h"
+#include "BKE_scene.h"
}
#include "BKE_armature.h"
#include "BKE_mesh.h"
@@ -91,6 +96,7 @@ extern "C"
#include <float.h>
// #define COLLADA_DEBUG
+#define ARMATURE_TEST
char *CustomData_get_layer_name(const struct CustomData *data, int type, int n);
@@ -129,8 +135,10 @@ const char *geomTypeToStr(COLLADAFW::Geometry::GeometryType type)
return "SPLINE";
case COLLADAFW::Geometry::GEO_TYPE_CONVEX_MESH:
return "CONVEX_MESH";
+ case COLLADAFW::Geometry::GEO_TYPE_UNKNOWN:
+ default:
+ return "UNKNOWN";
}
- return "UNKNOWN";
}
// works for COLLADAFW::Node, COLLADAFW::Geometry
@@ -193,41 +201,16 @@ public:
switch(type) {
case COLLADAFW::Transformation::TRANSLATE:
- {
- COLLADAFW::Translate *tra = (COLLADAFW::Translate*)tm;
- COLLADABU::Math::Vector3& t = tra->getTranslation();
-
- unit_m4(cur);
- cur[3][0] = (float)t[0];
- cur[3][1] = (float)t[1];
- cur[3][2] = (float)t[2];
- }
+ dae_translate_to_mat4(tm, cur);
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];
- axis_angle_to_quat(quat, axis, angle);
-
- quat_to_mat4( cur,quat);
- }
+ dae_rotate_to_mat4(tm, 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]};
- size_to_mat4( cur,size);
- }
+ dae_scale_to_mat4(tm, cur);
break;
case COLLADAFW::Transformation::MATRIX:
- {
- unit_converter->mat4_from_dae(cur, ((COLLADAFW::Matrix*)tm)->getMatrix());
- }
+ dae_matrix_to_mat4(tm, cur);
break;
case COLLADAFW::Transformation::LOOKAT:
case COLLADAFW::Transformation::SKEW:
@@ -248,6 +231,42 @@ public:
}
}
}
+
+ void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
+ {
+ COLLADAFW::Rotate *ro = (COLLADAFW::Rotate*)tm;
+ COLLADABU::Math::Vector3& axis = ro->getRotationAxis();
+ float angle = (float)(ro->getRotationAngle() * M_PI / 180.0f);
+ float ax[] = {axis[0], axis[1], axis[2]};
+ // float quat[4];
+ // axis_angle_to_quat(quat, axis, angle);
+ // quat_to_mat4(m, quat);
+ axis_angle_to_mat4(m, ax, angle);
+ }
+
+ void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
+ {
+ COLLADAFW::Translate *tra = (COLLADAFW::Translate*)tm;
+ COLLADABU::Math::Vector3& t = tra->getTranslation();
+
+ unit_m4(m);
+
+ m[3][0] = (float)t[0];
+ m[3][1] = (float)t[1];
+ m[3][2] = (float)t[2];
+ }
+
+ void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
+ {
+ COLLADABU::Math::Vector3& s = ((COLLADAFW::Scale*)tm)->getScale();
+ float size[3] = {(float)s[0], (float)s[1], (float)s[2]};
+ size_to_mat4(m, size);
+ }
+
+ void dae_matrix_to_mat4(COLLADAFW::Transformation *tm, float m[][4])
+ {
+ unit_converter->dae_matrix_to_mat4(m, ((COLLADAFW::Matrix*)tm)->getMatrix());
+ }
};
// only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid
@@ -261,7 +280,7 @@ public:
class AnimationImporterBase
{
public:
- virtual void change_eul_to_quat(Object *ob, bAction *act) = 0;
+ // virtual void change_eul_to_quat(Object *ob, bAction *act) = 0;
};
class ArmatureImporter : private TransformReader
@@ -387,7 +406,7 @@ private:
for (int i = 0; i < weight.getValuesCount(); i++)
weights.push_back(get_float_value(weight, i));
- unit_converter->mat4_from_dae(bind_shape_matrix, skin->getBindShapeMatrix());
+ unit_converter->dae_matrix_to_mat4(bind_shape_matrix, skin->getBindShapeMatrix());
}
void free()
@@ -404,7 +423,7 @@ private:
void add_joint(const COLLADABU::Math::Matrix4& matrix)
{
JointData jd;
- unit_converter->mat4_from_dae(jd.inv_bind_mat, matrix);
+ unit_converter->dae_matrix_to_mat4(jd.inv_bind_mat, matrix);
joint_data.push_back(jd);
}
@@ -478,7 +497,7 @@ private:
void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid,
TransformReader *tm)
{
- tm->decompose(bind_shape_matrix, ob->loc, ob->rot, ob->size);
+ tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size);
ob->parent = ob_arm;
ob->partype = PARSKEL;
@@ -705,6 +724,7 @@ private:
}
}
+#if 0
void set_euler_rotmode()
{
// just set rotmode = ROT_MODE_EUL on pose channel for each joint
@@ -735,6 +755,7 @@ private:
}
}
}
+#endif
Object *get_empty_for_leaves()
{
@@ -817,7 +838,7 @@ private:
set_leaf_bone_shapes(ob_arm);
- set_euler_rotmode();
+ // set_euler_rotmode();
}
@@ -989,6 +1010,7 @@ public:
BLI_snprintf(joint_path, count, "pose.bones[\"%s\"]", get_joint_name(node));
}
+#if 0
void fix_animation()
{
/* Change Euler rotation to Quaternion for bone animation */
@@ -999,6 +1021,23 @@ public:
anim_importer->change_eul_to_quat(ob, ob->adt->action);
}
}
+#endif
+
+ // gives a world-space mat
+ bool get_joint_bind_mat(float m[][4], COLLADAFW::Node *joint)
+ {
+ std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
+ bool found = false;
+ for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
+ SkinInfo& skin = it->second;
+ if ((found = skin.get_joint_inv_bind_matrix(m, joint))) {
+ invert_m4(m);
+ break;
+ }
+ }
+
+ return found;
+ }
};
class MeshImporter : public MeshImporterBase
@@ -1077,6 +1116,9 @@ private:
}
break;
+ case COLLADAFW::MeshVertexData::DATA_TYPE_UNKNOWN:
+ default:
+ fprintf(stderr, "MeshImporter.getUV(): unknown data type\n");
}
}
};
@@ -1317,7 +1359,7 @@ private:
int count_new_tris(COLLADAFW::Mesh *mesh, Mesh *me)
{
COLLADAFW::MeshPrimitiveArray& prim_arr = mesh->getMeshPrimitives();
- int i, j, k;
+ int i, j;
int tottri = 0;
for (i = 0; i < prim_arr.getCount(); i++) {
@@ -1727,11 +1769,14 @@ private:
ArmatureImporter *armature_importer;
Scene *scene;
- std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map;
+ std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > curve_map;
std::map<COLLADAFW::UniqueId, TransformReader::Animation> uid_animated_map;
- std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map;
+ // std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map;
+ std::map<COLLADAFW::UniqueId, const COLLADAFW::AnimationList*> animlist_map;
+ std::vector<FCurve*> unused_curves;
+ std::map<COLLADAFW::UniqueId, Object*> joint_objects;
- FCurve *create_fcurve(int array_index, char *rna_path)
+ FCurve *create_fcurve(int array_index, const char *rna_path)
{
FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
@@ -1754,6 +1799,105 @@ private:
calchandles_fcurve(fcu);
}
+ // create one or several fcurves depending on the number of parameters being animated
+ void animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
+ {
+ COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
+ COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
+ // COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
+ // COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
+ float fps = (float)FPS;
+ size_t dim = curve->getOutDimension();
+ int i;
+
+ std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
+
+ if (dim == 1) {
+ FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+ // fcu->rna_path = BLI_strdupn(path, strlen(path));
+ fcu->array_index = 0;
+ //fcu->totvert = curve->getKeyCount();
+
+ // create beztriple for each key
+ for (i = 0; i < curve->getKeyCount(); i++) {
+ BezTriple bez;
+ memset(&bez, 0, sizeof(BezTriple));
+
+ // intangent
+ // bez.vec[0][0] = get_float_value(intan, i + i) * fps;
+ // bez.vec[0][1] = get_float_value(intan, i + i + 1);
+
+ // input, output
+ bez.vec[1][0] = get_float_value(input, i) * fps;
+ bez.vec[1][1] = get_float_value(output, i);
+
+ // outtangent
+ // bez.vec[2][0] = get_float_value(outtan, i + i) * fps;
+ // bez.vec[2][1] = get_float_value(outtan, i + i + 1);
+
+ bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ bez.f1 = bez.f2 = bez.f3 = SELECT;
+ bez.h1 = bez.h2 = HD_AUTO;
+ insert_bezt_fcurve(fcu, &bez, 0);
+ }
+
+ calchandles_fcurve(fcu);
+
+ fcurves.push_back(fcu);
+ }
+ else if(dim == 3) {
+ for (i = 0; i < dim; i++ ) {
+ FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve");
+
+ fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
+ // fcu->rna_path = BLI_strdupn(path, strlen(path));
+ fcu->array_index = 0;
+ //fcu->totvert = curve->getKeyCount();
+
+ // create beztriple for each key
+ for (int j = 0; j < curve->getKeyCount(); j++) {
+ BezTriple bez;
+ memset(&bez, 0, sizeof(BezTriple));
+
+ // intangent
+ // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps;
+ // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1);
+
+ // input, output
+ bez.vec[1][0] = get_float_value(input, j) * fps;
+ bez.vec[1][1] = get_float_value(output, j * 3 + i);
+
+ // outtangent
+ // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps;
+ // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1);
+
+ bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ bez.f1 = bez.f2 = bez.f3 = SELECT;
+ bez.h1 = bez.h2 = HD_AUTO;
+ insert_bezt_fcurve(fcu, &bez, 0);
+ }
+
+ calchandles_fcurve(fcu);
+
+ fcurves.push_back(fcu);
+ }
+ }
+
+ for (std::vector<FCurve*>::iterator it = fcurves.begin(); it != fcurves.end(); it++)
+ unused_curves.push_back(*it);
+ }
+
+ void fcurve_deg_to_rad(FCurve *cu)
+ {
+ for (int i = 0; i < cu->totvert; i++) {
+ // TODO convert handles too
+ cu->bezt[i].vec[1][1] *= M_PI / 180.0f;
+ }
+ }
+
+#if 0
void make_fcurves_from_animation(COLLADAFW::AnimationCurve *curve,
COLLADAFW::FloatOrDoubleArray& input,
COLLADAFW::FloatOrDoubleArray& output,
@@ -1762,7 +1906,7 @@ private:
{
int i;
// char *path = "location";
- std::vector<FCurve*>& fcurves = uid_fcurve_map[curve->getUniqueId()];
+ std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
if (dim == 1) {
// create fcurve
@@ -1831,49 +1975,36 @@ private:
}
}
}
+#endif
void add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated)
{
- ID *id = &ob->id;
bAction *act;
- bActionGroup *grp = NULL;
- if (!ob->adt || !ob->adt->action) act = verify_adt_action(id, 1);
- else act = verify_adt_action(id, 0);
-
- if (!ob->adt || !ob->adt->action) {
- fprintf(stderr, "Cannot create anim data or action for this object. \n");
- return;
- }
+ if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
+ else act = ob->adt->action;
- FCurve *fcu;
std::vector<FCurve*>::iterator it;
- int i = 0;
+ int i;
+#if 0
char *p = strstr(rna_path, "rotation_euler");
bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0';
+
+ // convert degrees to radians for rotation
+ if (is_rotation)
+ fcurve_deg_to_rad(fcu);
+#endif
- for (it = curves.begin(); it != curves.end(); it++) {
- fcu = *it;
+ for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) {
+ FCurve *fcu = *it;
fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
if (array_index == -1) fcu->array_index = i;
else fcu->array_index = array_index;
-
- // convert degrees to radians for rotation
- if (is_rotation) {
- for(int j = 0; j < fcu->totvert; j++) {
- float rot_intan = fcu->bezt[j].vec[0][1];
- float rot_output = fcu->bezt[j].vec[1][1];
- float rot_outtan = fcu->bezt[j].vec[2][1];
- fcu->bezt[j].vec[0][1] = rot_intan * M_PI / 180.0f;
- fcu->bezt[j].vec[1][1] = rot_output * M_PI / 180.0f;
- fcu->bezt[j].vec[2][1] = rot_outtan * M_PI / 180.0f;
- }
- }
-
+
if (ob->type == OB_ARMATURE) {
- bAction *act = ob->adt->action;
+ bActionGroup *grp = NULL;
const char *bone_name = get_joint_name(animated->node);
if (bone_name) {
@@ -1886,7 +2017,7 @@ private:
grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
grp->flag = AGRP_SELECTED;
- BLI_snprintf(grp->name, sizeof(grp->name), bone_name);
+ BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
BLI_addtail(&act->groups, grp);
BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
@@ -1896,15 +2027,18 @@ private:
action_groups_add_channel(act, grp, fcu);
}
+#if 0
if (is_rotation) {
fcurves_actionGroup_map[grp].push_back(fcu);
}
+#endif
}
else {
BLI_addtail(&act->curves, fcu);
}
- i++;
+ // curve is used, so remove it from unused_curves
+ unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
}
}
public:
@@ -1912,13 +2046,20 @@ public:
AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
TransformReader(conv), armature_importer(arm), scene(scene) { }
- bool write_animation( const COLLADAFW::Animation* anim )
+ ~AnimationImporter()
{
- float fps = (float)FPS;
+ // free unused FCurves
+ for (std::vector<FCurve*>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++)
+ free_fcurve(*it);
+
+ if (unused_curves.size())
+ fprintf(stderr, "removed %u unused curves\n", unused_curves.size());
+ }
+ bool write_animation(const COLLADAFW::Animation* anim)
+ {
if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve*)anim;
- size_t dim = curve->getOutDimension();
// XXX Don't know if it's necessary
// Should we check outPhysicalDimension?
@@ -1927,11 +2068,6 @@ public:
return true;
}
- COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
- COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
- COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
- COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
-
// a curve can have mixed interpolation type,
// in this case curve->getInterpolationTypes returns a list of interpolation types per key
COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
@@ -1939,17 +2075,11 @@ public:
if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
switch (interp) {
case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
- // support this
- make_fcurves_from_animation(curve, input, output, intan, outtan, dim, fps);
- break;
case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
- // and this
- make_fcurves_from_animation(curve, input, output, intan, outtan, dim, fps);
+ animation_to_fcurves(curve);
break;
- case COLLADAFW::AnimationCurve::INTERPOLATION_CARDINAL:
- case COLLADAFW::AnimationCurve::INTERPOLATION_HERMITE:
- case COLLADAFW::AnimationCurve::INTERPOLATION_BSPLINE:
- case COLLADAFW::AnimationCurve::INTERPOLATION_STEP:
+ default:
+ // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types
fprintf(stderr, "CARDINAL, HERMITE, BSPLINE and STEP anim interpolation types not supported yet.\n");
break;
}
@@ -1967,19 +2097,22 @@ public:
}
// called on post-process stage after writeVisualScenes
- bool write_animation_list( const COLLADAFW::AnimationList* animationList )
+ bool write_animation_list(const COLLADAFW::AnimationList* animlist)
{
- const COLLADAFW::UniqueId& anim_list_id = animationList->getUniqueId();
+ const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
+
+ animlist_map[animlist_id] = animlist;
- // possible in case we cannot interpret some transform
- if (uid_animated_map.find(anim_list_id) == uid_animated_map.end()) {
+#if 0
+ // should not happen
+ if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
return true;
}
// for bones rna_path is like: pose.bones["bone-name"].rotation
// what does this AnimationList animate?
- Animation& animated = uid_animated_map[anim_list_id];
+ Animation& animated = uid_animated_map[animlist_id];
Object *ob = animated.ob;
char rna_path[100];
@@ -2000,26 +2133,28 @@ public:
is_joint = true;
}
- const COLLADAFW::AnimationList::AnimationBindings& bindings = animationList->getAnimationBindings();
+ const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
switch (animated.tm->getTransformationType()) {
case COLLADAFW::Transformation::TRANSLATE:
+ case COLLADAFW::Transformation::SCALE:
{
+ bool loc = animated.tm->getTransformationType() == COLLADAFW::Transformation::TRANSLATE;
if (is_joint)
- BLI_snprintf(rna_path, sizeof(rna_path), "%s.location", joint_path);
+ BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
else
- BLI_strncpy(rna_path, "location", sizeof(rna_path));
+ BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
for (int i = 0; i < bindings.getCount(); i++) {
const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
COLLADAFW::UniqueId anim_uid = binding.animation;
- if (uid_fcurve_map.find(anim_uid) == uid_fcurve_map.end()) {
+ if (curve_map.find(anim_uid) == curve_map.end()) {
fprintf(stderr, "Cannot find FCurve by animation UID.\n");
continue;
}
- std::vector<FCurve*>& fcurves = uid_fcurve_map[anim_uid];
+ std::vector<FCurve*>& fcurves = curve_map[anim_uid];
switch (binding.animationClass) {
case COLLADAFW::AnimationList::POSITION_X:
@@ -2035,8 +2170,8 @@ public:
add_fcurves_to_object(ob, fcurves, rna_path, -1, &animated);
break;
default:
- fprintf(stderr, "AnimationClass %d is not supported for TRANSLATE transformation.\n",
- binding.animationClass);
+ fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
+ binding.animationClass, loc ? "TRANSLATE" : "SCALE");
}
}
}
@@ -2055,12 +2190,12 @@ public:
const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
COLLADAFW::UniqueId anim_uid = binding.animation;
- if (uid_fcurve_map.find(anim_uid) == uid_fcurve_map.end()) {
+ if (curve_map.find(anim_uid) == curve_map.end()) {
fprintf(stderr, "Cannot find FCurve by animation UID.\n");
continue;
}
- std::vector<FCurve*>& fcurves = uid_fcurve_map[anim_uid];
+ std::vector<FCurve*>& fcurves = curve_map[anim_uid];
switch (binding.animationClass) {
case COLLADAFW::AnimationList::ANGLE:
@@ -2083,51 +2218,13 @@ public:
}
}
break;
- case COLLADAFW::Transformation::SCALE:
- {
- if (is_joint)
- BLI_snprintf(rna_path, sizeof(rna_path), "%s.scale", joint_path);
- else
- BLI_strncpy(rna_path, "scale", sizeof(rna_path));
-
- // same as for TRANSLATE
- for (int i = 0; i < bindings.getCount(); i++) {
- const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i];
- COLLADAFW::UniqueId anim_uid = binding.animation;
-
- if (uid_fcurve_map.find(anim_uid) == uid_fcurve_map.end()) {
- fprintf(stderr, "Cannot find FCurve by animation UID.\n");
- continue;
- }
-
- std::vector<FCurve*>& fcurves = uid_fcurve_map[anim_uid];
-
- switch (binding.animationClass) {
- case COLLADAFW::AnimationList::POSITION_X:
- add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated);
- break;
- case COLLADAFW::AnimationList::POSITION_Y:
- add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated);
- break;
- case COLLADAFW::AnimationList::POSITION_Z:
- add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated);
- break;
- case COLLADAFW::AnimationList::POSITION_XYZ:
- add_fcurves_to_object(ob, fcurves, rna_path, -1, &animated);
- break;
- default:
- fprintf(stderr, "AnimationClass %d is not supported for SCALE transformation.\n",
- binding.animationClass);
- }
- }
- }
- break;
case COLLADAFW::Transformation::MATRIX:
case COLLADAFW::Transformation::SKEW:
case COLLADAFW::Transformation::LOOKAT:
fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
break;
}
+#endif
return true;
}
@@ -2137,9 +2234,10 @@ public:
float mat[4][4];
TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
if (ob)
- TransformReader::decompose(mat, ob->loc, ob->rot, ob->size);
+ TransformReader::decompose(mat, ob->loc, ob->rot, NULL, ob->size);
}
+#if 0
virtual void change_eul_to_quat(Object *ob, bAction *act)
{
bActionGroup *grp;
@@ -2163,7 +2261,7 @@ public:
char rna_path[100];
BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name);
- BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
+ BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path);
FCurve *quatcu[4] = {
create_fcurve(0, rna_path),
@@ -2172,6 +2270,12 @@ public:
create_fcurve(3, rna_path)
};
+ bPoseChannel *chan = get_pose_channel(ob->pose, grp->name);
+
+ float m4[4][4], irest[3][3];
+ invert_m4_m4(m4, chan->bone->arm_mat);
+ copy_m3_m4(irest, m4);
+
for (i = 0; i < 3; i++) {
FCurve *cu = eulcu[i];
@@ -2187,9 +2291,17 @@ public:
eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f
};
- float quat[4];
+ // make eul relative to bone rest pose
+ float rot[3][3], rel[3][3], quat[4];
+
+ /*eul_to_mat3(rot, eul);
+
+ mul_m3_m3m3(rel, irest, rot);
- eul_to_quat( quat,eul);
+ mat3_to_quat(quat, rel);
+ */
+
+ eul_to_quat(quat, eul);
for (int k = 0; k < 4; k++)
create_bezt(quatcu[k], frame, quat[k]);
@@ -2205,7 +2317,7 @@ public:
free_fcurve(eulcu[i]);
}
- get_pose_channel(ob->pose, grp->name)->rotmode = ROT_MODE_QUAT;
+ chan->rotmode = ROT_MODE_QUAT;
for (i = 0; i < 4; i++)
action_groups_add_channel(act, grp, quatcu[i]);
@@ -2215,7 +2327,581 @@ public:
for (pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
pchan->rotmode = ROT_MODE_QUAT;
}
- }
+ }
+#endif
+
+ // prerequisites:
+ // animlist_map - map animlist id -> animlist
+ // curve_map - map anim id -> curve(s)
+#ifdef ARMATURE_TEST
+ Object *translate_animation(COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Object*>& object_map,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
+ COLLADAFW::Transformation::TransformationType tm_type,
+ Object *par_job = NULL)
+#else
+ void translate_animation(COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Object*>& object_map,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
+ COLLADAFW::Transformation::TransformationType tm_type)
+#endif
+ {
+ bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
+ bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
+ COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
+ Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
+ const char *bone_name = is_joint ? get_joint_name(node) : NULL;
+
+ if (!ob) {
+ fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
+#ifdef ARMATURE_TEST
+ return NULL;
+#else
+ return;
+#endif
+ }
+
+ // frames at which to sample
+ std::vector<float> frames;
+
+ // for each <rotate>, <translate>, etc. there is a separate Transformation
+ const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
+
+ std::vector<FCurve*> old_curves;
+
+ int i;
+
+ // find frames at which to sample plus convert all keys to radians
+ for (i = 0; i < tms.getCount(); i++) {
+ COLLADAFW::Transformation *tm = tms[i];
+ COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
+
+ if (type == tm_type) {
+ const COLLADAFW::UniqueId& listid = tm->getAnimationList();
+
+ if (animlist_map.find(listid) != animlist_map.end()) {
+ const COLLADAFW::AnimationList *animlist = animlist_map[listid];
+ const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
+
+ if (bindings.getCount()) {
+ for (int j = 0; j < bindings.getCount(); j++) {
+ std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
+ bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
+
+ if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3)) {
+ std::vector<FCurve*>::iterator iter;
+
+ for (iter = curves.begin(); iter != curves.end(); iter++) {
+ FCurve *fcu = *iter;
+
+ if (is_rotation)
+ fcurve_deg_to_rad(fcu);
+
+ for (int k = 0; k < fcu->totvert; k++) {
+ float fra = fcu->bezt[k].vec[1][0];
+ if (std::find(frames.begin(), frames.end(), fra) == frames.end())
+ frames.push_back(fra);
+ }
+ }
+ }
+ else {
+ fprintf(stderr, "expected 1 or 3 curves, got %u\n", curves.size());
+ }
+
+ for (std::vector<FCurve*>::iterator it = curves.begin(); it != curves.end(); it++)
+ old_curves.push_back(*it);
+ }
+ }
+ }
+ }
+ }
+
+ sort(frames.begin(), frames.end());
+
+ float irest_dae[4][4];
+ float rest[4][4], irest[4][4];
+
+ if (is_joint) {
+ if (is_joint)
+ get_joint_rest_mat(irest_dae, root, node);
+ else
+ evaluate_transform_at_frame(irest_dae, node, 0.0f);
+ invert_m4(irest_dae);
+
+ Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
+ if (!bone) {
+ fprintf(stderr, "cannot find bone \"%s\"", bone_name);
+#ifdef ARMATURE_TEST
+ return NULL;
+#else
+ return;
+#endif
+ }
+
+ unit_m4(rest);
+ copy_m4_m4(rest, bone->arm_mat);
+ invert_m4_m4(irest, rest);
+ }
+
+ char rna_path[200];
+
+#ifdef ARMATURE_TEST
+ Object *job = get_joint_object(root, node, par_job);
+ FCurve *job_curves[4];
+#endif
+
+ if (frames.size() == 0) {
+#ifdef ARMATURE_TEST
+ return job;
+#else
+ return;
+#endif
+ }
+
+ const char *tm_str = NULL;
+ switch (tm_type) {
+ case COLLADAFW::Transformation::ROTATE:
+ tm_str = "rotation_quaternion";
+ break;
+ case COLLADAFW::Transformation::SCALE:
+ tm_str = "scale";
+ break;
+ case COLLADAFW::Transformation::TRANSLATE:
+ tm_str = "location";
+ break;
+ default:
+#ifdef ARMATURE_TEST
+ return job;
+#else
+ return;
+#endif
+ }
+
+ if (is_joint) {
+ char joint_path[200];
+ armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
+ BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
+ }
+ else {
+ strcpy(rna_path, tm_str);
+ }
+
+ // new curves
+ FCurve *newcu[4];
+ int totcu = is_rotation ? 4 : 3;
+
+ for (i = 0; i < totcu; i++) {
+ newcu[i] = create_fcurve(i, rna_path);
+#ifdef ARMATURE_TEST
+ job_curves[i] = create_fcurve(i, tm_str);
+#endif
+ }
+
+ std::vector<float>::iterator it;
+
+ // sample values at each frame
+ for (it = frames.begin(); it != frames.end(); it++) {
+ float fra = *it;
+
+ float mat[4][4];
+
+ unit_m4(mat);
+
+ // calc object-space mat
+ evaluate_transform_at_frame(mat, node, fra);
+
+ // for joints, we need a special matrix
+ if (is_joint) {
+ // special matrix: iR * M * iR_dae * R
+ // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
+ // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
+ float temp[4][4], par[4][4];
+
+ // calc M
+ calc_joint_parent_mat_rest(par, NULL, root, node);
+ mul_m4_m4m4(temp, mat, par);
+
+ // evaluate_joint_world_transform_at_frame(temp, NULL, , node, fra);
+
+ // calc special matrix
+ mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL);
+ }
+
+ float val[4];
+
+ switch (tm_type) {
+ case COLLADAFW::Transformation::ROTATE:
+ mat4_to_quat(val, mat);
+ break;
+ case COLLADAFW::Transformation::SCALE:
+ mat4_to_size(val, mat);
+ break;
+ case COLLADAFW::Transformation::TRANSLATE:
+ copy_v3_v3(val, mat[3]);
+ break;
+ default:
+ break;
+ }
+
+ // add 4 or 3 keys
+ for (i = 0; i < totcu; i++) {
+ add_bezt(newcu[i], fra, val[i]);
+ }
+
+#ifdef ARMATURE_TEST
+ if (is_joint) {
+ evaluate_transform_at_frame(mat, node, fra);
+
+ switch (tm_type) {
+ case COLLADAFW::Transformation::ROTATE:
+ mat4_to_quat(val, mat);
+ break;
+ case COLLADAFW::Transformation::SCALE:
+ mat4_to_size(val, mat);
+ break;
+ case COLLADAFW::Transformation::TRANSLATE:
+ copy_v3_v3(val, mat[3]);
+ break;
+ default:
+ break;
+ }
+
+ for (i = 0; i < totcu; i++)
+ add_bezt(job_curves[i], fra, val[i]);
+ }
+#endif
+ }
+
+ verify_adt_action((ID*)&ob->id, 1);
+
+ ListBase *curves = &ob->adt->action->curves;
+ // no longer needed
+#if 0
+ // remove old curves
+ for (std::vector<FCurve*>::iterator it = old_curves.begin(); it != old_curves.end(); it++) {
+ if (is_joint)
+ action_groups_remove_channel(ob->adt->action, *it);
+ else
+ BLI_remlink(curves, *it);
+
+ // std::remove(unused_curves.begin(), unused_curves.end(), *it);
+ // free_fcurve(*it);
+ }
+#endif
+
+ // add curves
+ for (i = 0; i < totcu; i++) {
+ if (is_joint)
+ add_bone_fcurve(ob, node, newcu[i]);
+ else
+ BLI_addtail(curves, newcu[i]);
+
+#ifdef ARMATURE_TEST
+ if (is_joint)
+ BLI_addtail(&job->adt->action->curves, job_curves[i]);
+#endif
+ }
+
+ if (is_rotation) {
+ if (is_joint) {
+ bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
+ chan->rotmode = ROT_MODE_QUAT;
+ }
+ else {
+ ob->rotmode = ROT_MODE_QUAT;
+ }
+ }
+
+#ifdef ARMATURE_TEST
+ return job;
+#endif
+ }
+
+ // internal, better make it private
+ // warning: evaluates only rotation
+ // prerequisites: animlist_map, curve_map
+ void evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra)
+ {
+ const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
+
+ unit_m4(mat);
+
+ for (int i = 0; i < tms.getCount(); i++) {
+ COLLADAFW::Transformation *tm = tms[i];
+ COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
+ float m[4][4];
+
+ unit_m4(m);
+
+ if (!evaluate_animation(tm, m, fra)) {
+ switch (type) {
+ case COLLADAFW::Transformation::ROTATE:
+ dae_rotate_to_mat4(tm, m);
+ break;
+ case COLLADAFW::Transformation::TRANSLATE:
+ dae_translate_to_mat4(tm, m);
+ break;
+ case COLLADAFW::Transformation::SCALE:
+ dae_scale_to_mat4(tm, m);
+ break;
+ case COLLADAFW::Transformation::MATRIX:
+ dae_matrix_to_mat4(tm, m);
+ break;
+ default:
+ fprintf(stderr, "unsupported transformation type %d\n", type);
+ }
+ }
+
+ float temp[4][4];
+ copy_m4_m4(temp, mat);
+
+ mul_m4_m4m4(mat, m, temp);
+ }
+ }
+
+ bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra)
+ {
+ const COLLADAFW::UniqueId& listid = tm->getAnimationList();
+
+ if (animlist_map.find(listid) != animlist_map.end()) {
+ const COLLADAFW::AnimationList *animlist = animlist_map[listid];
+ const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
+
+ if (bindings.getCount()) {
+ for (int j = 0; j < bindings.getCount(); j++) {
+ std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
+ COLLADAFW::AnimationList::AnimationClass animclass = bindings[j].animationClass;
+ COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
+ bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
+
+ if (type == COLLADAFW::Transformation::ROTATE) {
+ if (curves.size() != 1) {
+ fprintf(stderr, "expected 1 curve, got %u\n", curves.size());
+ }
+ else {
+ if (animclass == COLLADAFW::AnimationList::ANGLE) {
+ COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis();
+ float ax[3] = {axis[0], axis[1], axis[2]};
+ float angle = evaluate_fcurve(curves[0], fra);
+ axis_angle_to_mat4(mat, ax, angle);
+
+ return true;
+ }
+ else {
+ // TODO support other animclasses
+ fprintf(stderr, "<rotate> animclass %d is not supported yet\n", bindings[j].animationClass);
+ }
+ }
+ }
+ else if (type == COLLADAFW::Transformation::SCALE || type == COLLADAFW::Transformation::TRANSLATE) {
+ if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3)) {
+ bool animated = true;
+ bool scale = (type == COLLADAFW::Transformation::SCALE);
+
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+ if (scale)
+ vec[0] = vec[1] = vec[2] = 1.0f;
+
+ switch (animclass) {
+ case COLLADAFW::AnimationList::POSITION_X:
+ vec[0] = evaluate_fcurve(curves[0], fra);
+ break;
+ case COLLADAFW::AnimationList::POSITION_Y:
+ vec[1] = evaluate_fcurve(curves[0], fra);
+ break;
+ case COLLADAFW::AnimationList::POSITION_Z:
+ vec[2] = evaluate_fcurve(curves[0], fra);
+ break;
+ case COLLADAFW::AnimationList::POSITION_XYZ:
+ vec[0] = evaluate_fcurve(curves[0], fra);
+ vec[1] = evaluate_fcurve(curves[1], fra);
+ vec[2] = evaluate_fcurve(curves[2], fra);
+ break;
+ default:
+ fprintf(stderr, "<%s> animclass %d is not supported yet\n", scale ? "scale" : "translate", animclass);
+ animated = false;
+ break;
+ }
+
+ if (animated) {
+ if (scale)
+ size_to_mat4(mat, vec);
+ else
+ copy_v3_v3(mat[3], vec);
+ }
+
+ return animated;
+ }
+ else {
+ fprintf(stderr, "expected 1 or 3 curves, got %u, animclass is %d\n", curves.size(), animclass);
+ }
+ }
+ else {
+ // not very useful for user
+ fprintf(stderr, "animation of transformation %d is not supported yet\n", type);
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // gives a world-space mat of joint at rest position
+ void get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node)
+ {
+ // if bind mat is not available,
+ // use "current" node transform, i.e. all those tms listed inside <node>
+ if (!armature_importer->get_joint_bind_mat(mat, node)) {
+ float par[4][4], m[4][4];
+
+ calc_joint_parent_mat_rest(par, NULL, root, node);
+ get_node_mat(m, node, NULL, NULL);
+ mul_m4_m4m4(mat, m, par);
+ }
+ }
+
+ // gives a world-space mat, end's mat not included
+ bool calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end)
+ {
+ float m[4][4];
+
+ if (node == end) {
+ par ? copy_m4_m4(mat, par) : unit_m4(mat);
+ return true;
+ }
+
+ // use bind matrix if available or calc "current" world mat
+ if (!armature_importer->get_joint_bind_mat(m, node)) {
+ float temp[4][4];
+ get_node_mat(temp, node, NULL, NULL);
+ mul_m4_m4m4(m, temp, par);
+ }
+
+ COLLADAFW::NodePointerArray& children = node->getChildNodes();
+ for (int i = 0; i < children.getCount(); i++) {
+ if (calc_joint_parent_mat_rest(mat, m, children[i], end))
+ return true;
+ }
+
+ return false;
+ }
+
+#ifdef ARMATURE_TEST
+ Object *get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job)
+ {
+ if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) {
+ Object *job = add_object(scene, OB_EMPTY);
+
+ rename_id((ID*)&job->id, (char*)get_joint_name(node));
+
+ job->lay = object_in_scene(job, scene)->lay = 2;
+
+ mul_v3_fl(job->size, 0.5f);
+ job->recalc |= OB_RECALC_OB;
+
+ verify_adt_action((ID*)&job->id, 1);
+
+ job->rotmode = ROT_MODE_QUAT;
+
+ float mat[4][4];
+ get_joint_rest_mat(mat, root, node);
+
+ if (par_job) {
+ float temp[4][4], ipar[4][4];
+ invert_m4_m4(ipar, par_job->obmat);
+ copy_m4_m4(temp, mat);
+ mul_m4_m4m4(mat, temp, ipar);
+ }
+
+ TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size);
+
+ if (par_job) {
+ job->parent = par_job;
+
+ par_job->recalc |= OB_RECALC_OB;
+ job->parsubstr[0] = 0;
+ }
+
+ where_is_object(scene, job);
+
+ // after parenting and layer change
+ DAG_scene_sort(scene);
+
+ joint_objects[node->getUniqueId()] = job;
+ }
+
+ return joint_objects[node->getUniqueId()];
+ }
+#endif
+
+#if 0
+ // recursively evaluates joint tree until end is found, mat then is world-space matrix of end
+ // mat must be identity on enter, node must be root
+ bool evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra)
+ {
+ float m[4][4];
+ if (par) {
+ float temp[4][4];
+ evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f);
+ mul_m4_m4m4(m, temp, par);
+ }
+ else {
+ evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f);
+ }
+
+ if (node == end) {
+ copy_m4_m4(mat, m);
+ return true;
+ }
+ else {
+ COLLADAFW::NodePointerArray& children = node->getChildNodes();
+ for (int i = 0; i < children.getCount(); i++) {
+ if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra))
+ return true;
+ }
+ }
+
+ return false;
+ }
+#endif
+
+ void add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
+ {
+ const char *bone_name = get_joint_name(node);
+ bAction *act = ob->adt->action;
+
+ /* try to find group */
+ bActionGroup *grp = action_groups_find_named(act, bone_name);
+
+ /* no matching groups, so add one */
+ if (grp == NULL) {
+ /* Add a new group, and make it active */
+ grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
+
+ grp->flag = AGRP_SELECTED;
+ BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
+
+ BLI_addtail(&act->groups, grp);
+ BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64);
+ }
+
+ /* add F-Curve to group */
+ action_groups_add_channel(act, grp, fcu);
+ }
+
+ void add_bezt(FCurve *fcu, float fra, float value)
+ {
+ BezTriple bez;
+ memset(&bez, 0, sizeof(BezTriple));
+ bez.vec[1][0] = fra;
+ bez.vec[1][1] = value;
+ bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ bez.f1 = bez.f2 = bez.f3 = SELECT;
+ bez.h1 = bez.h2 = HD_AUTO;
+ insert_bezt_fcurve(fcu, &bez, 0);
+ calchandles_fcurve(fcu);
+ }
};
/*
@@ -2245,6 +2931,11 @@ private:
std::map<COLLADAFW::UniqueId, Camera*> uid_camera_map;
std::map<COLLADAFW::UniqueId, Lamp*> uid_lamp_map;
std::map<Material*, TexIndexTextureArrayMap> material_texture_mapping_map;
+ std::map<COLLADAFW::UniqueId, Object*> object_map;
+ std::vector<const COLLADAFW::VisualScene*> vscenes;
+
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> root_map; // find root joint by child joint uid, for bone tree evaluation during resampling
+
// animation
// std::map<COLLADAFW::UniqueId, std::vector<FCurve*> > uid_fcurve_map;
// Nodes don't share AnimationLists (Arystan)
@@ -2253,7 +2944,7 @@ private:
public:
/** Constructor. */
- Writer(bContext *C, const char *filename) : mContext(C), mFilename(filename),
+ Writer(bContext *C, const char *filename) : mFilename(filename), mContext(C),
armature_importer(&unit_converter, &mesh_importer, &anim_importer, CTX_data_scene(C)),
mesh_importer(&armature_importer, CTX_data_scene(C)),
anim_importer(&unit_converter, &armature_importer, CTX_data_scene(C)) {}
@@ -2295,8 +2986,51 @@ public:
/** This method is called after the last write* method. No other methods will be called after this.*/
virtual void finish()
{
+#if 0
armature_importer.fix_animation();
+#endif
+
+ for (std::vector<const COLLADAFW::VisualScene*>::iterator it = vscenes.begin(); it != vscenes.end(); it++) {
+ const COLLADAFW::NodePointerArray& roots = (*it)->getRootNodes();
+
+ for (int i = 0; i < roots.getCount(); i++)
+ translate_anim_recursive(roots[i]);
+ }
+
+ }
+
+
+#ifdef ARMATURE_TEST
+ void translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW::Node *par = NULL, Object *parob = NULL)
+ {
+ if (par && par->getType() == COLLADAFW::Node::JOINT) {
+ // par is root if there's no corresp. key in root_map
+ if (root_map.find(par->getUniqueId()) == root_map.end())
+ root_map[node->getUniqueId()] = par;
+ else
+ root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
+ }
+
+ COLLADAFW::Transformation::TransformationType types[] = {
+ COLLADAFW::Transformation::ROTATE,
+ COLLADAFW::Transformation::SCALE,
+ COLLADAFW::Transformation::TRANSLATE
+ };
+
+ int i;
+ Object *ob;
+
+ for (i = 0; i < 3; i++)
+ ob = anim_importer.translate_animation(node, object_map, root_map, types[i]);
+
+ COLLADAFW::NodePointerArray &children = node->getChildNodes();
+ for (int i = 0; i < children.getCount(); i++) {
+ translate_anim_recursive(children[i], node, ob);
+ }
}
+#else
+
+#endif
/** When this method is called, the writer must write the global document asset.
@return The writer should return true, if writing succeeded, false otherwise.*/
@@ -2396,11 +3130,11 @@ public:
// check if object is not NULL
if (!ob) return;
+
+ object_map[node->getUniqueId()] = ob;
// if par was given make this object child of the previous
if (par && ob) {
- Object workob;
-
ob->parent = par;
// doing what 'set parent' operator does
@@ -2424,7 +3158,7 @@ public:
@return The writer should return true, if writing succeeded, false otherwise.*/
virtual bool writeVisualScene ( const COLLADAFW::VisualScene* visualScene )
{
- // This method is guaranteed to be called _after_ writeGeometry, writeMaterial, etc.
+ // this method called on post process after writeGeometry, writeMaterial, etc.
// for each <node> in <visual_scene>:
// create an Object
@@ -2434,15 +3168,15 @@ public:
// writeGeometry because <geometry> does not reference <node>,
// we link Objects with Meshes here
+ vscenes.push_back(visualScene);
+
// TODO: create a new scene except the selected <visual_scene> - use current blender
// scene for it
Scene *sce = CTX_data_scene(mContext);
+ const COLLADAFW::NodePointerArray& roots = visualScene->getRootNodes();
- for (int i = 0; i < visualScene->getRootNodes().getCount(); i++) {
- COLLADAFW::Node *node = visualScene->getRootNodes()[i];
- const COLLADAFW::Node::NodeType& type = node->getType();
-
- write_node(node, NULL, sce, NULL);
+ for (int i = 0; i < roots.getCount(); i++) {
+ write_node(roots[i], NULL, sce, NULL);
}
armature_importer.make_armatures(mContext);
@@ -2494,7 +3228,7 @@ public:
ma->mtex[i] = add_mtex();
ma->mtex[i]->texco = TEXCO_UV;
- ma->mtex[i]->tex = add_texture("texture");
+ ma->mtex[i]->tex = add_texture("Texture");
ma->mtex[i]->tex->type = TEX_IMAGE;
ma->mtex[i]->tex->imaflag &= ~TEX_USEALPHA;
ma->mtex[i]->tex->ima = uid_image_map[ima_uid];
@@ -2799,12 +3533,14 @@ public:
// this function is called only for animations that pass COLLADAFW::validate
virtual bool writeAnimation( const COLLADAFW::Animation* anim )
{
+ // return true;
return anim_importer.write_animation(anim);
}
// called on post-process stage after writeVisualScenes
virtual bool writeAnimationList( const COLLADAFW::AnimationList* animationList )
{
+ // return true;
return anim_importer.write_animation_list(animationList);
}
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 32c3e7af874..278cd37ac66 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -26,7 +26,7 @@ public:
// TODO need also for angle conversion, time conversion...
- void mat4_from_dae(float out[][4], const COLLADABU::Math::Matrix4& in)
+ void dae_matrix_to_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 swap columns and rows
@@ -58,10 +58,13 @@ public:
class TransformBase
{
public:
- void decompose(float mat[][4], float *loc, float *rot, float *size)
+ void decompose(float mat[][4], float *loc, float eul[3], float quat[4], float *size)
{
- mat4_to_size( size,mat);
- mat4_to_eul( rot,mat);
+ 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]);
}
};