feature collada: Allow export/import of skeletal animations as curves
This commit is contained in:
@@ -27,8 +27,9 @@
|
||||
|
||||
std::string EMPTY_STRING;
|
||||
|
||||
std::string AnimationExporter::get_axis_name(std::string channel, int id)
|
||||
std::string AnimationExporter::get_axis_name(std::string channel_type, int id)
|
||||
{
|
||||
|
||||
static std::map<std::string, std::vector<std::string>> BC_COLLADA_AXIS_FROM_TYPE = {
|
||||
{"color", {"R", "G", "B"}},
|
||||
{"specular_color", {"R", "G", "B"}},
|
||||
@@ -39,7 +40,8 @@ std::string AnimationExporter::get_axis_name(std::string channel, int id)
|
||||
{"rotation_euler", {"X", "Y", "Z"}}};
|
||||
|
||||
std::map<std::string, std::vector<std::string>>::const_iterator it;
|
||||
it = BC_COLLADA_AXIS_FROM_TYPE.find(channel);
|
||||
|
||||
it = BC_COLLADA_AXIS_FROM_TYPE.find(channel_type);
|
||||
if (it == BC_COLLADA_AXIS_FROM_TYPE.end()) {
|
||||
return "";
|
||||
}
|
||||
@@ -146,7 +148,7 @@ void AnimationExporter::exportAnimation(Object *ob, BCAnimationSampler &sampler)
|
||||
|
||||
export_curve_animation_set(ob, sampler, export_as_matrix);
|
||||
|
||||
if (ob->type == OB_ARMATURE) {
|
||||
if (ob->type == OB_ARMATURE && export_as_matrix) {
|
||||
|
||||
#ifdef WITH_MORPH_ANIMATION
|
||||
/* TODO: This needs to be handled by extra profiles, postponed for now */
|
||||
@@ -183,7 +185,8 @@ void AnimationExporter::export_curve_animation_set(Object *ob,
|
||||
BCAnimationCurveMap::iterator it;
|
||||
for (it = curves->begin(); it != curves->end(); ++it) {
|
||||
BCAnimationCurve &curve = *it->second;
|
||||
if (curve.get_channel_target() == "rotation_quaternion") {
|
||||
std::string channel_type = curve.get_channel_type();
|
||||
if (channel_type == "rotation_quaternion") {
|
||||
/* Can not export Quaternion animation in Collada as far as i know)
|
||||
* Maybe automatically convert to euler rotation?
|
||||
* Discard for now. */
|
||||
@@ -286,9 +289,9 @@ BCAnimationCurve *AnimationExporter::get_modified_export_curve(Object *ob,
|
||||
BCAnimationCurve &curve,
|
||||
BCAnimationCurveMap &curves)
|
||||
{
|
||||
std::string channel_target = curve.get_channel_target();
|
||||
std::string channel_type = curve.get_channel_type();
|
||||
BCAnimationCurve *mcurve = NULL;
|
||||
if (channel_target == "lens") {
|
||||
if (channel_type == "lens") {
|
||||
|
||||
/* Create an xfov curve */
|
||||
|
||||
@@ -339,7 +342,8 @@ void AnimationExporter::export_curve_animation(Object *ob, BCAnimationCurve &cur
|
||||
|
||||
int channel_index = curve.get_channel_index();
|
||||
/* RGB or XYZ or "" */
|
||||
std::string axis = get_axis_name(channel_target, channel_index);
|
||||
std::string channel_type = curve.get_channel_type();
|
||||
std::string axis = get_axis_name(channel_type, channel_index);
|
||||
|
||||
std::string action_name;
|
||||
bAction *action = bc_getSceneObjectAction(ob);
|
||||
@@ -767,7 +771,7 @@ std::string AnimationExporter::collada_linear_interpolation_source(int tot,
|
||||
return source_id;
|
||||
}
|
||||
|
||||
const std::string AnimationExporter::get_collada_name(std::string channel_target) const
|
||||
const std::string AnimationExporter::get_collada_name(std::string channel_type) const
|
||||
{
|
||||
/*
|
||||
* Translation table to map FCurve animation types to Collada animation.
|
||||
@@ -811,11 +815,10 @@ const std::string AnimationExporter::get_collada_name(std::string channel_target
|
||||
{"clip_start", "znear"}};
|
||||
|
||||
std::map<std::string, std::string>::iterator name_it = BC_CHANNEL_BLENDER_TO_COLLADA.find(
|
||||
channel_target);
|
||||
channel_type);
|
||||
if (name_it == BC_CHANNEL_BLENDER_TO_COLLADA.end()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string tm_name = name_it->second;
|
||||
return tm_name;
|
||||
}
|
||||
@@ -828,7 +831,8 @@ std::string AnimationExporter::get_collada_sid(const BCAnimationCurve &curve,
|
||||
const std::string axis_name)
|
||||
{
|
||||
std::string channel_target = curve.get_channel_target();
|
||||
std::string tm_name = get_collada_name(channel_target);
|
||||
std::string channel_type = curve.get_channel_type();
|
||||
std::string tm_name = get_collada_name(channel_type);
|
||||
|
||||
bool is_angle = curve.is_rotation_curve();
|
||||
|
||||
|
||||
@@ -170,6 +170,16 @@ void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationImporter::fcurve_scale(FCurve *cu, int scale)
|
||||
{
|
||||
for (unsigned int i = 0; i < cu->totvert; i++) {
|
||||
/* TODO convert handles too */
|
||||
cu->bezt[i].vec[1][1] *= scale;
|
||||
cu->bezt[i].vec[0][1] *= scale;
|
||||
cu->bezt[i].vec[2][1] *= scale;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationImporter::fcurve_is_used(FCurve *fcu)
|
||||
{
|
||||
unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu),
|
||||
@@ -451,7 +461,8 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
|
||||
/* sets the rna_path and array index to curve */
|
||||
void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves,
|
||||
const char *rna_path,
|
||||
int array_index)
|
||||
int array_index,
|
||||
int scale)
|
||||
{
|
||||
std::vector<FCurve *>::iterator it;
|
||||
int i;
|
||||
@@ -466,6 +477,10 @@ void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves,
|
||||
fcu->array_index = array_index;
|
||||
}
|
||||
|
||||
if (scale != 1) {
|
||||
fcurve_scale(fcu, scale);
|
||||
}
|
||||
|
||||
fcurve_is_used(fcu);
|
||||
}
|
||||
}
|
||||
@@ -581,10 +596,20 @@ void AnimationImporter::Assign_transform_animations(
|
||||
modify_fcurve(curves, rna_path, 0);
|
||||
}
|
||||
else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
|
||||
modify_fcurve(curves, rna_path, 1);
|
||||
if (is_joint) {
|
||||
modify_fcurve(curves, rna_path, 2, -1); // Bone animation from dae to blender
|
||||
}
|
||||
else {
|
||||
modify_fcurve(curves, rna_path, 1);
|
||||
}
|
||||
}
|
||||
else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
|
||||
modify_fcurve(curves, rna_path, 2);
|
||||
if (is_joint) {
|
||||
modify_fcurve(curves, rna_path, 1); // Bone animation from dae to blender
|
||||
}
|
||||
else {
|
||||
modify_fcurve(curves, rna_path, 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
unused_fcurve(curves);
|
||||
@@ -1061,28 +1086,23 @@ void AnimationImporter::translate_Animations(
|
||||
apply_matrix_curves(ob, animcurves, root, node, transform);
|
||||
}
|
||||
else {
|
||||
if (is_joint) {
|
||||
add_bone_animation_sampled(ob, animcurves, root, node, transform);
|
||||
}
|
||||
else {
|
||||
/* calculate rnapaths and array index of fcurves according to transformation and
|
||||
* animation class */
|
||||
Assign_transform_animations(
|
||||
transform, &bindings[j], &animcurves, is_joint, joint_path);
|
||||
/* calculate rnapaths and array index of fcurves according to transformation and
|
||||
* animation class */
|
||||
Assign_transform_animations(
|
||||
transform, &bindings[j], &animcurves, is_joint, joint_path);
|
||||
|
||||
std::vector<FCurve *>::iterator iter;
|
||||
/* Add the curves of the current animation to the object */
|
||||
for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
|
||||
FCurve *fcu = *iter;
|
||||
std::vector<FCurve *>::iterator iter;
|
||||
/* Add the curves of the current animation to the object */
|
||||
for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
|
||||
FCurve *fcu = *iter;
|
||||
|
||||
BLI_addtail(AnimCurves, fcu);
|
||||
fcurve_is_used(fcu);
|
||||
}
|
||||
BLI_addtail(AnimCurves, fcu);
|
||||
fcurve_is_used(fcu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_rotation && !is_joint) {
|
||||
if (is_rotation && !(is_joint || is_matrix)) {
|
||||
ob->rotmode = ROT_MODE_EUL;
|
||||
}
|
||||
}
|
||||
@@ -1822,10 +1842,10 @@ Object *AnimationImporter::translate_animation_OLD(
|
||||
if (is_rotation || is_matrix) {
|
||||
if (is_joint) {
|
||||
bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
|
||||
chan->rotmode = ROT_MODE_QUAT;
|
||||
chan->rotmode = (is_matrix)? ROT_MODE_QUAT : ROT_MODE_EUL;
|
||||
}
|
||||
else {
|
||||
ob->rotmode = ROT_MODE_QUAT;
|
||||
ob->rotmode = (is_matrix) ? ROT_MODE_QUAT : ROT_MODE_EUL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ class AnimationImporter : private TransformReader, public AnimationImporterBase
|
||||
void animation_to_fcurves(COLLADAFW::AnimationCurve *curve);
|
||||
|
||||
void fcurve_deg_to_rad(FCurve *cu);
|
||||
void fcurve_scale(FCurve *cu, int scale);
|
||||
|
||||
void fcurve_is_used(FCurve *fcu);
|
||||
|
||||
@@ -194,7 +195,7 @@ class AnimationImporter : private TransformReader, public AnimationImporterBase
|
||||
|
||||
int setAnimType(const COLLADAFW::Animatable *prop, int type, int addition);
|
||||
|
||||
void modify_fcurve(std::vector<FCurve *> *curves, const char *rna_path, int array_index);
|
||||
void modify_fcurve(std::vector<FCurve *> *curves, const char *rna_path, int array_index, int scale=1);
|
||||
void unused_fcurve(std::vector<FCurve *> *curves);
|
||||
// prerequisites:
|
||||
// animlist_map - map animlist id -> animlist
|
||||
|
||||
@@ -659,6 +659,11 @@ Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo &skin)
|
||||
ED_armature_from_edit(bmain, armature);
|
||||
ED_armature_edit_free(armature);
|
||||
|
||||
for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
|
||||
COLLADAFW::Node *node = *ri;
|
||||
set_bone_transformation_type(node, ob_arm);
|
||||
}
|
||||
|
||||
ED_armature_to_edit(armature);
|
||||
if (this->import_settings->find_chains) {
|
||||
connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
|
||||
@@ -673,6 +678,20 @@ Object *ArmatureImporter::create_armature_bones(Main *bmain, SkinInfo &skin)
|
||||
return ob_arm;
|
||||
}
|
||||
|
||||
void ArmatureImporter::set_bone_transformation_type(const COLLADAFW::Node *node, Object *ob_arm)
|
||||
{
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bc_get_joint_name(node));
|
||||
if (pchan) {
|
||||
pchan->rotmode = (node_is_decomposed(node)) ? ROT_MODE_EUL : ROT_MODE_QUAT;
|
||||
}
|
||||
|
||||
COLLADAFW::NodePointerArray childnodes = node->getChildNodes();
|
||||
for (int index = 0; index < childnodes.getCount(); index++) {
|
||||
node = childnodes[index];
|
||||
set_bone_transformation_type(node, ob_arm);
|
||||
}
|
||||
}
|
||||
|
||||
void ArmatureImporter::set_pose(Object *ob_arm,
|
||||
COLLADAFW::Node *root_node,
|
||||
const char *parentname,
|
||||
@@ -684,9 +703,12 @@ void ArmatureImporter::set_pose(Object *ob_arm,
|
||||
|
||||
/* object-space */
|
||||
get_node_mat(obmat, root_node, NULL, NULL);
|
||||
bool is_decomposed = node_is_decomposed(root_node);
|
||||
|
||||
// if (*edbone)
|
||||
bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone_name);
|
||||
pchan->rotmode = (is_decomposed) ? ROT_MODE_EUL : ROT_MODE_QUAT;
|
||||
|
||||
// else fprintf ( "",
|
||||
|
||||
/* get world-space */
|
||||
@@ -716,6 +738,19 @@ void ArmatureImporter::set_pose(Object *ob_arm,
|
||||
}
|
||||
}
|
||||
|
||||
bool ArmatureImporter::node_is_decomposed(const COLLADAFW::Node *node)
|
||||
{
|
||||
const COLLADAFW::TransformationPointerArray &nodeTransforms = node->getTransformations();
|
||||
for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
|
||||
COLLADAFW::Transformation *transform = nodeTransforms[i];
|
||||
COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
|
||||
if (tm_type == COLLADAFW::Transformation::MATRIX) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* root - if this joint is the top joint in hierarchy, if a joint
|
||||
* is a child of a node (not joint), root should be true since
|
||||
|
||||
@@ -123,6 +123,8 @@ class ArmatureImporter : private TransformReader {
|
||||
const char *parentname,
|
||||
float parent_mat[4][4]);
|
||||
|
||||
void set_bone_transformation_type(const COLLADAFW::Node *node, Object *ob_arm);
|
||||
bool node_is_decomposed(const COLLADAFW::Node *node);
|
||||
#if 0
|
||||
void set_leaf_bone_shapes(Object *ob_arm);
|
||||
void set_euler_rotmode();
|
||||
|
||||
@@ -174,7 +174,7 @@ const std::string BCAnimationCurve::get_animation_name(Object *ob) const
|
||||
}
|
||||
else {
|
||||
const char *boneName = BLI_str_quoted_substrN(fcurve->rna_path, "pose.bones[");
|
||||
name = (boneName) ? std::string(boneName) : "";
|
||||
name = (boneName) ? id_name(ob)+"_"+std::string(boneName) : "";
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -331,15 +331,17 @@ void BCAnimationCurve::clean_handles()
|
||||
|
||||
const bool BCAnimationCurve::is_transform_curve() const
|
||||
{
|
||||
std::string channel_target = this->get_channel_target();
|
||||
return (is_rotation_curve() || channel_target == "scale" || channel_target == "location");
|
||||
std::string channel_type = this->get_channel_type();
|
||||
return (is_rotation_curve() || channel_type == "scale" || channel_type == "location");
|
||||
}
|
||||
|
||||
const bool BCAnimationCurve::is_rotation_curve() const
|
||||
{
|
||||
std::string channel_target = this->get_channel_target();
|
||||
return (channel_target == "rotation" || channel_target == "rotation_euler" ||
|
||||
channel_target == "rotation_quaternion");
|
||||
std::string channel_type = this->get_channel_type();
|
||||
return (channel_type == "rotation"
|
||||
|| channel_type == "rotation_euler"
|
||||
|| channel_type == "rotation_quaternion"
|
||||
);
|
||||
}
|
||||
|
||||
const float BCAnimationCurve::get_value(const float frame)
|
||||
|
||||
@@ -119,6 +119,9 @@ class BCAnimationCurve {
|
||||
|
||||
const std::string get_animation_name(Object *ob) const; /* xxx: this is collada specific */
|
||||
const std::string get_channel_target() const;
|
||||
const std::string get_channel_type() const;
|
||||
const std::string get_channel_posebone() const; // returns "" if channel is not a bone channel
|
||||
|
||||
const int get_channel_index() const;
|
||||
const int get_subindex() const;
|
||||
const std::string get_rna_path() const;
|
||||
|
||||
@@ -42,17 +42,37 @@ void BCSample::add_bone_matrix(Bone *bone, Matrix &mat)
|
||||
/* Get channel value */
|
||||
const bool BCSample::get_value(std::string channel_target, const int array_index, float *val) const
|
||||
{
|
||||
if (channel_target == "location") {
|
||||
*val = obmat.location()[array_index];
|
||||
std::string bname = bc_string_before(channel_target, ".");
|
||||
std::string channel_type = bc_string_after(channel_target, ".");
|
||||
|
||||
const BCMatrix *matrix = &obmat;
|
||||
if (bname != channel_target) {
|
||||
bname = bname.substr(2);
|
||||
bname = bc_string_before(bname, "\"");
|
||||
BCBoneMatrixMap::const_iterator it;
|
||||
for (it = bonemats.begin(); it != bonemats.end(); ++it) {
|
||||
Bone *bone = it->first;
|
||||
if (bname == bone->name) {
|
||||
matrix = it->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (channel_target == "scale") {
|
||||
*val = obmat.scale()[array_index];
|
||||
else {
|
||||
matrix = &obmat;
|
||||
}
|
||||
else if (channel_target == "rotation" || channel_target == "rotation_euler") {
|
||||
*val = obmat.rotation()[array_index];
|
||||
|
||||
if (channel_type == "location") {
|
||||
*val = matrix->location()[array_index];
|
||||
}
|
||||
else if (channel_target == "rotation_quat") {
|
||||
*val = obmat.quat()[array_index];
|
||||
else if (channel_type == "scale") {
|
||||
*val = matrix->scale()[array_index];
|
||||
}
|
||||
else if (channel_type == "rotation" || channel_type == "rotation_euler") {
|
||||
*val = matrix->rotation()[array_index];
|
||||
}
|
||||
else if (channel_type == "rotation_quaternion") {
|
||||
*val = matrix->quat()[array_index];
|
||||
}
|
||||
else {
|
||||
*val = 0;
|
||||
|
||||
@@ -25,23 +25,6 @@
|
||||
|
||||
#include "TransformWriter.h"
|
||||
|
||||
static BC_export_transformation_type get_transformation_type(BCExportSettings &export_settings)
|
||||
{
|
||||
bool enforce_matrix_export = export_settings.get_include_animations();
|
||||
|
||||
return (enforce_matrix_export) ? BC_TRANSFORMATION_TYPE_MATRIX :
|
||||
export_settings.get_object_transformation_type();
|
||||
}
|
||||
|
||||
static BC_export_transformation_type get_transformation_type(Object *ob,
|
||||
BCExportSettings &export_settings)
|
||||
{
|
||||
bool enforce_matrix_export = ob->type == OB_ARMATURE && export_settings.get_include_animations();
|
||||
|
||||
return (enforce_matrix_export) ? BC_TRANSFORMATION_TYPE_MATRIX :
|
||||
export_settings.get_object_transformation_type();
|
||||
}
|
||||
|
||||
void TransformWriter::add_joint_transform(COLLADASW::Node &node,
|
||||
float mat[4][4],
|
||||
float parent_mat[4][4],
|
||||
@@ -68,7 +51,7 @@ void TransformWriter::add_joint_transform(COLLADASW::Node &node,
|
||||
converter->mat4_to_dae_double(dmat, local);
|
||||
delete converter;
|
||||
|
||||
if (get_transformation_type(export_settings) == BC_TRANSFORMATION_TYPE_MATRIX) {
|
||||
if (export_settings.get_object_transformation_type() == BC_TRANSFORMATION_TYPE_MATRIX) {
|
||||
node.addMatrix("transform", dmat);
|
||||
}
|
||||
else {
|
||||
@@ -96,7 +79,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node &node,
|
||||
bc_add_global_transform(f_obmat, export_settings.get_global_transform());
|
||||
}
|
||||
|
||||
switch (get_transformation_type(ob, export_settings)) {
|
||||
switch (export_settings.get_object_transformation_type()) {
|
||||
case BC_TRANSFORMATION_TYPE_MATRIX: {
|
||||
UnitConverter converter;
|
||||
double d_obmat[4][4];
|
||||
|
||||
Reference in New Issue
Block a user