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:
Diffstat (limited to 'source/blender/collada')
-rw-r--r--source/blender/collada/AnimationExporter.cpp26
-rw-r--r--source/blender/collada/AnimationImporter.cpp4
-rw-r--r--source/blender/collada/ArmatureExporter.cpp94
-rw-r--r--source/blender/collada/ArmatureExporter.h2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp66
-rw-r--r--source/blender/collada/ControllerExporter.cpp125
-rw-r--r--source/blender/collada/ControllerExporter.h2
-rw-r--r--source/blender/collada/DocumentExporter.cpp17
-rw-r--r--source/blender/collada/DocumentImporter.cpp14
-rw-r--r--source/blender/collada/EffectExporter.cpp134
-rw-r--r--source/blender/collada/EffectExporter.h1
-rw-r--r--source/blender/collada/ErrorHandler.cpp9
-rw-r--r--source/blender/collada/ExportSettings.h7
-rw-r--r--source/blender/collada/GeometryExporter.cpp311
-rw-r--r--source/blender/collada/GeometryExporter.h34
-rw-r--r--source/blender/collada/ImageExporter.cpp28
-rw-r--r--source/blender/collada/ImportSettings.h1
-rw-r--r--source/blender/collada/InstanceWriter.cpp63
-rw-r--r--source/blender/collada/InstanceWriter.h3
-rw-r--r--source/blender/collada/MaterialExporter.cpp35
-rw-r--r--source/blender/collada/MeshImporter.cpp7
-rw-r--r--source/blender/collada/SceneExporter.cpp5
-rw-r--r--source/blender/collada/SkinInfo.cpp3
-rw-r--r--source/blender/collada/TransformReader.cpp23
-rw-r--r--source/blender/collada/TransformReader.h5
-rw-r--r--source/blender/collada/TransformWriter.cpp7
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp17
-rw-r--r--source/blender/collada/collada.h17
-rw-r--r--source/blender/collada/collada_internal.cpp34
-rw-r--r--source/blender/collada/collada_internal.h8
-rw-r--r--source/blender/collada/collada_utils.cpp380
-rw-r--r--source/blender/collada/collada_utils.h25
33 files changed, 1087 insertions, 423 deletions
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index 3bff20e846b..d4f434d56fd 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -312,12 +312,12 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
if (ob->type == OB_ARMATURE) {
ob_name = getObjectBoneName(ob, fcu);
BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s.%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)translate_id(transformName).c_str(),
- axis_name);
+ anim_id,
+ sizeof(anim_id),
+ "%s_%s.%s",
+ (char *)translate_id(ob_name).c_str(),
+ (char *)translate_id(transformName).c_str(),
+ axis_name);
}
else {
if (ma)
@@ -326,12 +326,12 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
ob_name = id_name(ob);
BLI_snprintf(
- anim_id,
- sizeof(anim_id),
- "%s_%s_%s",
- (char *)translate_id(ob_name).c_str(),
- (char *)getAnimationPathId(fcu).c_str(),
- axis_name);
+ anim_id,
+ sizeof(anim_id),
+ "%s_%s_%s",
+ (char *)translate_id(ob_name).c_str(),
+ (char *)getAnimationPathId(fcu).c_str(),
+ axis_name);
}
openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
@@ -530,7 +530,7 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
addSampler(sampler);
- std::string target = translate_id(bone_name) + "/transform";
+ std::string target = get_joint_id(bone, ob_arm) + "/transform";
addChannel(COLLADABU::URI(empty, sampler_id), target);
closeAnimation();
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 5cd01eff263..bd47ee0214d 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -35,8 +35,8 @@
#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_string_utils.h"
#include "BLT_translation.h"
@@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
mul_m4_m4m4(mat, ipar, temp);
}
- TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size);
+ bc_decompose(mat, job->loc, NULL, job->quat, job->size);
if (par_job) {
job->parent = par_job;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 4f5cf83f5ca..d2495a8cb9f 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -69,17 +69,21 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
// write bone nodes
bArmature * armature = (bArmature *)ob_arm->data;
- ED_armature_to_edit(armature);
+ bool is_edited = armature->edbo != NULL;
- bArmature *arm = (bArmature *)ob_arm->data;
- for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
+ if (!is_edited)
+ ED_armature_to_edit(armature);
+
+ for (Bone *bone = (Bone *)armature->bonebase.first; bone; bone = bone->next) {
// start from root bones
if (!bone->parent)
add_bone_node(bone, ob_arm, sce, se, child_objects);
}
- ED_armature_from_edit(armature);
- ED_armature_edit_free(armature);
+ if (!is_edited) {
+ ED_armature_from_edit(armature);
+ ED_armature_edit_free(armature);
+ }
}
void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
@@ -112,7 +116,10 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
@@ -152,11 +159,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
// parent_mat is armature-space
void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
SceneExporter *se,
@@ -257,47 +259,59 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
//bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
float mat[4][4];
+ float bone_rest_mat[4][4]; /* derived from bone->arm_mat */
+ float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */
- if (bone->parent) {
- // get bone-space matrix from parent pose
- /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
- float invpar[4][4];
- invert_m4_m4(invpar, parchan->pose_mat);
- mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
-
- float invpar[4][4];
- invert_m4_m4(invpar, bone->parent->arm_mat);
- mul_m4_m4m4(mat, invpar, bone->arm_mat);
+ bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat);
- }
- else {
+ if (!has_restmat) {
+
+ /* Have no restpose matrix stored, try old style <= Blender 2.78 */
- //copy_m4_m4(mat, pchan->pose_mat);
- //pose mat is object space
- //New change: export bone->arm_mat
- copy_m4_m4(mat, bone->arm_mat);
- }
+ bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true);
- // OPEN_SIM_COMPATIBILITY
- if (export_settings->open_sim) {
- // Remove rotations vs armature from transform
- // parent_rest_rot * mat * irest_rot
- float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
+ if (bone->parent) {
+ // get bone-space matrix from parent pose
+ /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
+ float invpar[4][4];
+ invert_m4_m4(invpar, parchan->pose_mat);
+ mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
+ float invpar[4][4];
+ bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true);
- mul_m4_m4m4(mat, mat, temp);
+ invert_m4_m4(invpar, parent_rest_mat);
+ mul_m4_m4m4(mat, invpar, bone_rest_mat);
- if (bone->parent) {
- copy_m4_m4(temp, bone->parent->arm_mat);
+ }
+ else {
+ copy_m4_m4(mat, bone_rest_mat);
+ }
+
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
+ // Remove rotations vs armature from transform
+ // parent_rest_rot * mat * irest_rot
+ float temp[4][4];
+ copy_m4_m4(temp, bone_rest_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
- mul_m4_m4m4(mat, temp, mat);
+ if (bone->parent) {
+ copy_m4_m4(temp, parent_rest_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
}
}
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(mat, 6);
+
TransformWriter::add_node_transform(node, mat, NULL);
+
}
std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 883a6aca847..d271b505aa9 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -83,8 +83,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
// Scene, SceneExporter and the list of child_objects
// are required for writing bone parented objects
void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index ae43c0a69d2..0ea8324ed7c 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -32,6 +32,7 @@
#include "COLLADAFWUniqueId.h"
+extern "C" {
#include "BKE_action.h"
#include "BKE_depsgraph.h"
#include "BKE_object.h"
@@ -39,7 +40,9 @@
#include "BLI_string.h"
#include "BLI_listbase.h"
#include "ED_armature.h"
+}
+#include "collada_utils.h"
#include "ArmatureImporter.h"
// use node name, or fall back to original id if not present (name is optional)
@@ -91,6 +94,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
+ float joint_bind_mat[4][4];
int chain_length = 0;
//Checking if bone is already made.
@@ -106,7 +110,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
*/
std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it;
- bool bone_is_not_skinned = true;
+ bool bone_is_skinned = false;
for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) {
SkinInfo *b = &skin_it->second;
@@ -114,7 +118,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
// get original world-space matrix
invert_m4_m4(mat, joint_inv_bind_mat);
-
+ copy_m4_m4(joint_bind_mat, mat);
// And make local to armature
Object *ob_arm = skin->BKE_armature_from_object();
if (ob_arm) {
@@ -123,24 +127,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
mul_m4_m4m4(mat, invmat, mat);
}
- bone_is_not_skinned = false;
+ bone_is_skinned = true;
break;
}
}
// create a bone even if there's no joint data for it (i.e. it has no influence)
- if (bone_is_not_skinned) {
- float obmat[4][4];
- // bone-space
- get_node_mat(obmat, node, NULL, NULL);
-
- // get world-space
- if (parent) {
- mul_m4_m4m4(mat, parent_mat, obmat);
- }
- else {
- copy_m4_m4(mat, obmat);
- }
+ if (!bone_is_skinned) {
+ get_node_mat(mat, node, NULL, NULL, parent_mat);
}
if (parent) bone->parent = parent;
@@ -156,10 +150,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
int use_connect = be.get_use_connect();
switch (use_connect) {
- case 1: bone->flag |= BONE_CONNECTED;
- break;
- case 0: bone->flag &= ~BONE_CONNECTED;
- case -1: break; // not defined
+ case 1: bone->flag |= BONE_CONNECTED;
+ break;
+ case -1:/* Connect type not specified */
+ case 0: bone->flag &= ~BONE_CONNECTED;
+ break;
}
if (be.has_roll()) {
@@ -169,8 +164,18 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
float angle;
mat4_to_loc_rot_size(loc, rot, size, mat);
mat3_to_vec_roll(rot, NULL, &angle);
+ bone->roll = angle;
}
copy_v3_v3(bone->head, mat[3]);
+
+ if (bone_is_skinned)
+ {
+ float rest_mat[4][4];
+ get_node_mat(rest_mat, node, NULL, NULL, NULL);
+ bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat);
+ bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat);
+ }
+
add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
/* find smallest bone length in armature (used later for leaf bone length) */
@@ -272,7 +277,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone)
}
-
void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip)
{
BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature);
@@ -288,12 +292,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
for (; child; child = child->next) {
BoneExtended *be = extended_bones[child->name];
if (be != NULL) {
- if (be->get_chain_length() <= clip) {
- if (be->get_chain_length() > maxlen) {
+ int chain_len = be->get_chain_length();
+ if (chain_len <= clip) {
+ if (chain_len > maxlen) {
dominant_child = be;
- maxlen = be->get_chain_length();
+ maxlen = chain_len;
}
- else if (be->get_chain_length() == maxlen) {
+ else if (chain_len == maxlen) {
dominant_child = NULL;
}
}
@@ -307,7 +312,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
EditBone *pebone = bc_get_edit_bone(armature, parentbone->name);
EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name());
if (pebone && !(cebone->flag & BONE_CONNECTED)) {
-
float vec[3];
sub_v3_v3v3(vec, cebone->head, pebone->head);
@@ -320,14 +324,16 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH)
{
- pebone->tail[0] = cebone->head[0];
- pebone->tail[1] = cebone->head[1];
- pebone->tail[2] = cebone->head[2];
-
+ copy_v3_v3(pebone->tail, cebone->head);
+ pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/
if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) {
+
+ BoneExtended *cbe = extended_bones[cebone->name];
+ cbe->set_use_connect(true);
+
cebone->flag |= BONE_CONNECTED;
- printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name);
pbe->set_leaf_bone(false);
+ printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name);
}
}
}
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 06e151c363b..5cd5e6d271a 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -98,7 +98,10 @@ bool ControllerExporter::add_instance_controller(Object *ob)
write_bone_URLs(ins, ob_arm, bone);
}
- InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(ins.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
ins.add();
return true;
@@ -157,11 +160,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
{
return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
@@ -468,81 +466,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb
return source_id;
}
-static float get_property(Bone *bone, const char *key, float def)
-{
- float result = def;
- if (bone->prop) {
- IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key);
- if (property) {
- switch (property->type) {
- case IDP_INT:
- result = (float)(IDP_Int(property));
- break;
- case IDP_FLOAT:
- result = (float)(IDP_Float(property));
- break;
- case IDP_DOUBLE:
- result = (float)(IDP_Double(property));
- break;
- default:
- result = def;
- }
- }
- }
- return result;
-}
-
-/**
- * This function creates an arbitrary rest pose matrix from
- * data provided as custom properties. This is a workaround
- * for support of maya's restpose matrix which can be arbitrary
- * in opposition to Blender where the Rest pose Matrix is always
- * the Identity matrix.
- *
- * The custom properties are:
- *
- * restpose_scale_x
- * restpose_scale_y
- * restpose_scale_z
- *
- * restpose_rot_x
- * restpose_rot_y
- * restpose_rot_z
- *
- * restpose_loc_x
- * restpose_loc_y
- * restpose_loc_z
- *
- * The matrix is only setup if the scale AND the rot properties are defined.
- * The presence of the loc properties is optional.
- *
- * This feature has been implemented to support Second Life "Fitted Mesh"
- * TODO: Check if an arbitrary rest pose matrix makes sense within Blender.
- * Eventually leverage the custom property data into an "official"
- * Edit_bone Property
- */
-static void create_restpose_mat(Bone *bone, float mat[4][4])
-{
- float loc[3] = {
- get_property(bone, "restpose_loc_x", 0.0),
- get_property(bone, "restpose_loc_y", 0.0),
- get_property(bone, "restpose_loc_z", 0.0)
- };
-
- float rot[3] = {
- DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_z", 0.0))
- };
-
- float scale[3] = {
- get_property(bone, "restpose_scale_x", 1.0),
- get_property(bone, "restpose_scale_y", 1.0),
- get_property(bone, "restpose_scale_z", 1.0)
- };
-
- loc_eulO_size_to_mat4(mat, loc, rot, scale, 6);
-}
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
{
@@ -585,30 +508,36 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
float world[4][4];
float inv_bind_mat[4][4];
+ float bind_mat[4][4]; /* derived from bone->arm_mat */
+
+ bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat);
- // SL/OPEN_SIM COMPATIBILITY
- if (export_settings->open_sim) {
- // Only translations, no rotation vs armature
- float temp[4][4];
- unit_m4(temp);
- copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
- mul_m4_m4m4(world, ob_arm->obmat, temp);
-
- // Add Maya restpose matrix (if defined as properties)
- float restpose_mat[4][4];
- create_restpose_mat(pchan->bone, restpose_mat);
- mul_m4_m4m4(world, world, restpose_mat);
+ if (!has_bindmat) {
- }
- else {
- // make world-space matrix, arm_mat is armature-space
- mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
+ /* Have no bind matrix stored, try old style <= Blender 2.78 */
+
+ bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
+
+ // SL/OPEN_SIM COMPATIBILITY
+ if (export_settings->open_sim) {
+
+ float loc[3];
+ float rot[3] = { 0, 0, 0 };
+ float scale[3];
+ bc_decompose(bind_mat, loc, NULL, NULL, scale);
+
+ // Only translations, no rotation vs armature
+ loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6);
+ }
}
+ // make world-space matrix (bind_mat is armature-space)
+ mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
invert_m4_m4(mat, world);
converter.mat4_to_dae(inv_bind_mat, mat);
-
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(inv_bind_mat, 6);
source.appendValues(inv_bind_mat);
}
}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 0be51187f6f..80b858ca6dd 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -84,8 +84,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
std::string get_controller_id(Object *ob_arm, Object *ob);
std::string get_controller_id(Key *key, Object *ob);
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index bd32e989ae3..dcfd062470c 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -138,7 +138,8 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
char *bc_CustomData_get_layer_name(const struct CustomData *data, int type, int n)
{
int layer_index = CustomData_get_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 0)
+ return NULL;
return data->layers[layer_index + n].name;
}
@@ -147,9 +148,10 @@ char *bc_CustomData_get_active_layer_name(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
- if (layer_index < 0) return NULL;
+ if (layer_index < 1)
+ return NULL;
- return data->layers[layer_index].name;
+ return bc_CustomData_get_layer_name(data, type, layer_index-1);
}
DocumentExporter::DocumentExporter(const ExportSettings *export_settings) : export_settings(export_settings) {
@@ -303,7 +305,10 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
// <library_visual_scenes>
SceneExporter se(writer, &arm_exporter, this->export_settings);
-
+#if 0
+ /* The following code seems to be an obsolete workaround
+ Comment out until it proofs correct that we no longer need it.
+ */
if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
// channels adressing <matrix> objects is not (yet) supported
// So we force usage of <location>, <translation> and <scale>
@@ -315,7 +320,9 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
else {
se.setExportTransformationType(this->export_settings->export_transformation_type);
}
-
+#else
+ se.setExportTransformationType(this->export_settings->export_transformation_type);
+#endif
se.exportScene(sce);
// <scene>
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 226f319cefd..f7fdfb06a40 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -388,9 +388,7 @@ Object *DocumentImporter::create_camera_object(COLLADAFW::InstanceCamera *camera
Camera *cam = uid_camera_map[cam_uid];
Camera *old_cam = (Camera *)ob->data;
ob->data = cam;
- id_us_min(&old_cam->id);
- if (old_cam->id.us == 0)
- BKE_libblock_free(G.main, old_cam);
+ BKE_libblock_free_us(G.main, old_cam);
return ob;
}
@@ -406,9 +404,7 @@ Object *DocumentImporter::create_lamp_object(COLLADAFW::InstanceLight *lamp, Sce
Lamp *la = uid_lamp_map[lamp_uid];
Lamp *old_lamp = (Lamp *)ob->data;
ob->data = la;
- id_us_min(&old_lamp->id);
- if (old_lamp->id.us == 0)
- BKE_libblock_free(G.main, old_lamp);
+ BKE_libblock_free_us(G.main, old_lamp);
return ob;
}
@@ -512,9 +508,9 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
std::vector<Object *> *root_objects = new std::vector<Object *>();
fprintf(stderr,
- "Writing node id='%s', name='%s'\n",
- id.c_str(),
- name.c_str());
+ "Writing node id='%s', name='%s'\n",
+ id.c_str(),
+ name.c_str());
if (is_joint) {
if (parent_node == NULL && !is_library_node) {
diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp
index 76b51148509..2bf0859b0f0 100644
--- a/source/blender/collada/EffectExporter.cpp
+++ b/source/blender/collada/EffectExporter.cpp
@@ -27,7 +27,6 @@
#include <map>
-#include <set>
#include "COLLADASWEffectProfile.h"
#include "COLLADAFWColorOrTexture.h"
@@ -49,21 +48,10 @@ extern "C" {
#include "BKE_material.h"
}
-// OB_MESH is assumed
-static std::string getActiveUVLayerName(Object *ob)
-{
- Mesh *me = (Mesh *)ob->data;
-
- int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
- if (num_layers)
- return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
-
- return "";
-}
-
EffectsExporter::EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryEffects(sw), export_settings(export_settings) {
}
+
bool EffectsExporter::hasEffects(Scene *sce)
{
Base *base = (Base *)sce->base.first;
@@ -86,13 +74,49 @@ bool EffectsExporter::hasEffects(Scene *sce)
void EffectsExporter::exportEffects(Scene *sce)
{
- if (hasEffects(sce)) {
- this->scene = sce;
- openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
-
- closeLibrary();
+ this->scene = sce;
+
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
+ if (hasEffects(sce)) {
+ MaterialFunctor mf;
+ openLibrary();
+ mf.forEachMaterialInExportSet<EffectsExporter>(sce, *this, this->export_settings->export_set);
+ closeLibrary();
+ }
+ }
+ else {
+ std::set<Object *> uv_textured_obs = bc_getUVTexturedObjects(sce, !this->export_settings->active_uv_only);
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string key(id_name(ima));
+ key = translate_id(key);
+ COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
+ key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
+ key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
+ sampler.setImageId(key);
+
+ openEffect(key + "-effect");
+ COLLADASW::EffectProfile ep(mSW);
+ ep.setProfileType(COLLADASW::EffectProfile::COMMON);
+ ep.setShaderType(COLLADASW::EffectProfile::PHONG);
+ ep.setDiffuse(createTexture(ima, key, &sampler), false, "diffuse");
+ COLLADASW::ColorOrTexture cot = getcol(0, 0, 0, 1.0f);
+ ep.setSpecular(cot, false, "specular");
+ ep.openProfile();
+ ep.addProfileElements();
+ ep.addExtraTechniques(mSW);
+ ep.closeProfile();
+ closeEffect();
+ }
+ closeLibrary();
+ }
}
}
@@ -176,8 +200,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
{
// create a list of indices to textures of type TEX_IMAGE
std::vector<int> tex_indices;
- if (this->export_settings->include_material_textures)
- createTextureIndices(ma, tex_indices);
+ createTextureIndices(ma, tex_indices);
openEffect(translate_id(id_name(ma)) + "-effect");
@@ -311,61 +334,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
}
}
- int active_uv_layer = -1;
- std::set<Image *> uv_textures;
- if (ob->type == OB_MESH && ob->totcol && this->export_settings->include_uv_textures) {
- bool active_uv_only = this->export_settings->active_uv_only;
- Mesh *me = (Mesh *) ob->data;
- active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
-
- BKE_mesh_tessface_ensure(me);
- for (int i = 0; i < me->pdata.totlayer; i++) {
- if (!active_uv_only || active_uv_layer == i)
- {
- if (me->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
- MPoly *mpoly = me->mpoly;
- for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
-
- Material *mat = give_current_material(ob, mpoly->mat_nr + 1);
- if (mat != ma)
- continue;
-
- Image *ima = txface->tpage;
- if (ima == NULL)
- continue;
-
-
- bool not_in_list = uv_textures.find(ima)==uv_textures.end();
- if (not_in_list) {
- std::string name = id_name(ima);
- std::string key(name);
- key = translate_id(key);
-
- // create only one <sampler>/<surface> pair for each unique image
- if (im_samp_map.find(key) == im_samp_map.end()) {
- //<newparam> <sampler> <source>
- COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D,
- key + COLLADASW::Sampler::SAMPLER_SID_SUFFIX,
- key + COLLADASW::Sampler::SURFACE_SID_SUFFIX);
- sampler.setImageId(key);
- samplers[a] = sampler;
- samp_surf[b] = &samplers[a];
- im_samp_map[key] = b;
- b++;
- a++;
- uv_textures.insert(ima);
- }
- }
- }
- }
- }
- }
- }
-
// used as fallback when MTex->uvname is "" (this is pretty common)
// it is indeed the correct value to use in that case
- std::string active_uv(getActiveUVLayerName(ob));
+ std::string active_uv(bc_get_active_uvlayer_name(ob));
// write textures
// XXX very slow
@@ -385,19 +356,6 @@ void EffectsExporter::operator()(Material *ma, Object *ob)
writeTextures(ep, key, sampler, t, ima, uvname);
}
- std::set<Image *>::iterator uv_t_iter;
- int idx;
- for (idx = 0, uv_t_iter = uv_textures.begin(); uv_t_iter != uv_textures.end(); uv_t_iter++, idx++ ) {
- if (active_uv_layer>-1 && idx==active_uv_layer) {
- Image *ima = *uv_t_iter;
- std::string key(id_name(ima));
- key = translate_id(key);
- int i = im_samp_map[key];
- COLLADASW::Sampler *sampler = (COLLADASW::Sampler *)samp_surf[i];
- ep.setDiffuse(createTexture(ima, active_uv, sampler), false, "diffuse");
- }
- }
-
// performs the actual writing
ep.addProfileElements();
bool twoSided = false;
diff --git a/source/blender/collada/EffectExporter.h b/source/blender/collada/EffectExporter.h
index d20cbfdfe0b..7d45a085777 100644
--- a/source/blender/collada/EffectExporter.h
+++ b/source/blender/collada/EffectExporter.h
@@ -48,7 +48,6 @@ class EffectsExporter: COLLADASW::LibraryEffects
public:
EffectsExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
void exportEffects(Scene *sce);
-
void operator()(Material *ma, Object *ob);
COLLADASW::ColorOrTexture createTexture(Image *ima,
diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp
index 98aa85f8a9b..32aa5636e08 100644
--- a/source/blender/collada/ErrorHandler.cpp
+++ b/source/blender/collada/ErrorHandler.cpp
@@ -49,7 +49,7 @@ ErrorHandler::~ErrorHandler()
//--------------------------------------------------------------------
bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
{
- bool isError = true;
+ bool isError = false;
if (error->getErrorClass() == COLLADASaxFWL::IError::ERROR_SAXPARSER) {
COLLADASaxFWL::SaxParserError *saxParserError = (COLLADASaxFWL::SaxParserError *) error;
@@ -81,10 +81,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
* Accept non critical errors as warnings (i.e. texture not found)
* This makes the importer more graceful, so it now imports what makes sense.
*/
- if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) {
- isError = false;
- }
-
+ isError = (saxFWLError->getSeverity() != COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL);
std::cout << "Sax FWL Error: " << saxFWLError->getErrorMessage() << std::endl;
}
else {
@@ -93,5 +90,5 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error)
mError |= isError;
- return false; // let OpenCollada decide when to abort
+ return isError; // let OpenCollada decide when to abort
}
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 9451cac9dae..6d90edd2f67 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -28,7 +28,6 @@
#define __EXPORTSETTINGS_H__
#include "collada.h"
-#include "collada.h"
struct ExportSettings {
public:
@@ -42,8 +41,7 @@ public:
bool deform_bones_only;
bool active_uv_only;
- bool include_uv_textures;
- bool include_material_textures;
+ BC_export_texture_type export_texture_type;
bool use_texture_copies;
bool triangulate;
@@ -51,7 +49,10 @@ public:
bool use_blender_profile;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
+
bool open_sim;
+ bool limit_precision;
+ bool keep_bind_info;
char *filepath;
LinkNode *export_set;
diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp
index 7c7c57f3305..8a9ccbbed51 100644
--- a/source/blender/collada/GeometryExporter.cpp
+++ b/source/blender/collada/GeometryExporter.cpp
@@ -52,6 +52,7 @@ extern "C" {
#include "collada_internal.h"
#include "collada_utils.h"
+
// TODO: optimize UV sets by making indexed list with duplicates removed
GeometryExporter::GeometryExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryGeometries(sw), export_settings(export_settings)
{
@@ -134,13 +135,22 @@ void GeometryExporter::operator()(Object *ob)
// Only create Polylists if number of faces > 0
if (me->totface > 0) {
// XXX slow
- if (ob->totcol) {
- for (int a = 0; a < ob->totcol; a++) {
- createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ std::set<Image *> uv_images = bc_getUVImages(ob, !this->export_settings->active_uv_only);
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT || uv_images.size() == 0) {
+ if (ob->totcol) {
+ for (int a = 0; a < ob->totcol; a++) {
+ createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+ }
+ }
+ else {
+ int i = 0;
+ createPolylist(i, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
}
@@ -220,13 +230,15 @@ void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb)
//createLooseEdgeList(ob, me, geom_id, norind);
// XXX slow
- if (ob->totcol) {
+ if (ob->totcol && this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
for (int a = 0; a < ob->totcol; a++) {
createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
}
}
else {
- createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+ bool all_uv_layers = !this->export_settings->active_uv_only;
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ createPolylists(uv_images, has_uvs, has_color, ob, me, geom_id, norind);
}
closeMesh();
@@ -295,7 +307,44 @@ std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char
return result;
}
-// powerful because it handles both cases when there is material and when there's not
+static void prepareToAppendValues(bool is_triangulated, COLLADASW::PrimitivesBase *facelist, std::vector<unsigned long> &vcount_list)
+{
+ // performs the actual writing
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->prepareToAppendValues();
+ }
+ else {
+ // sets <vcount>
+ facelist->setVCountList(vcount_list);
+ ((COLLADASW::Polylist *)facelist)-> prepareToAppendValues();
+ }
+}
+
+static void finishList(bool is_triangulated, COLLADASW::PrimitivesBase *facelist)
+{
+ if (is_triangulated) {
+ ((COLLADASW::Triangles *)facelist)->finish();
+ }
+ else {
+ ((COLLADASW::Polylist *)facelist)->finish();
+ }
+}
+
+COLLADASW::PrimitivesBase *getFacelist(bool is_triangulated, COLLADASW::StreamWriter *mSW)
+{
+ COLLADASW::PrimitivesBase *facelist;
+
+ if (is_triangulated)
+ {
+ facelist = new COLLADASW::Triangles(mSW);
+ }
+ else {
+ facelist = new COLLADASW::Polylist(mSW);
+ }
+ return facelist;
+}
+
+// Export meshes with Materials
void GeometryExporter::createPolylist(short material_index,
bool has_uvs,
bool has_color,
@@ -313,7 +362,7 @@ void GeometryExporter::createPolylist(short material_index,
int i;
int faces_in_polylist = 0;
std::vector<unsigned long> vcount_list;
-
+ bool is_triangulated = true;
// count faces with this material
for (i = 0; i < totpolys; i++) {
MPoly *p = &mpolys[i];
@@ -321,6 +370,9 @@ void GeometryExporter::createPolylist(short material_index,
if (p->mat_nr == material_index) {
faces_in_polylist++;
vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
}
}
@@ -331,20 +383,21 @@ void GeometryExporter::createPolylist(short material_index,
}
Material *ma = ob->totcol ? give_current_material(ob, material_index + 1) : NULL;
- COLLADASW::Polylist polylist(mSW);
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
// sets count attribute in <polylist>
- polylist.setCount(faces_in_polylist);
+ facelist->setCount(faces_in_polylist);
// sets material name
if (ma) {
std::string material_id = get_material_id(ma);
std::ostringstream ostr;
ostr << translate_id(material_id);
- polylist.setMaterial(ostr.str());
+ facelist->setMaterial(ostr.str());
}
-
- COLLADASW::InputList &til = polylist.getInputList();
+
+ COLLADASW::InputList &til = facelist->getInputList();
// creates <input> in <polylist> for vertices
COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
@@ -360,13 +413,21 @@ void GeometryExporter::createPolylist(short material_index,
int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE)-1;
for (i = 0; i < num_layers; i++) {
if (!this->export_settings->active_uv_only || i == active_uv_index) {
-
- // char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i);
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
- makeUrl(makeTexcoordSourceId(geom_id, i, this->export_settings->active_uv_only)),
- 2, // this is only until we have optimized UV sets
- (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
- );
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
til.push_back(input3);
}
}
@@ -387,12 +448,10 @@ void GeometryExporter::createPolylist(short material_index,
}
}
- // sets <vcount>
- polylist.setVCountList(vcount_list);
// performs the actual writing
- polylist.prepareToAppendValues();
-
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
// <p>
int texindex = 0;
for (i = 0; i < totpolys; i++) {
@@ -404,22 +463,202 @@ void GeometryExporter::createPolylist(short material_index,
BCPolygonNormalsIndices normal_indices = norind[i];
for (int j = 0; j < loop_count; j++) {
- polylist.appendValues(l[j].v);
- polylist.appendValues(normal_indices[j]);
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
if (has_uvs)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
if (has_color)
- polylist.appendValues(texindex + j);
+ facelist->appendValues(texindex + j);
}
}
texindex += loop_count;
}
-
- polylist.finish();
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
}
+void GeometryExporter::createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string imageid(id_name(ima));
+ createPolylist(imageid, has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+ }
+
+ /* We msut add an additional collector for the case when
+ * some parts of the object are not textured at all.
+ * The next call creates a polylist for all untextured polygons
+ */
+
+ createPolylist("", has_uvs,
+ has_color,
+ ob,
+ me,
+ geom_id,
+ norind);
+
+}
+
+/* ===========================================================================
+ * Export Meshes with UV Textures (export as materials, see also in
+ * effectExporter and MaterialExporter)
+ *
+ * If imageid is the empty string, then collect only untextured polygons
+ * =========================================================================== */
+void GeometryExporter::createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind)
+{
+
+ MPoly *mpolys = me->mpoly;
+ MLoop *mloops = me->mloop;
+ MTexPoly *mtpolys = me->mtpoly;
+
+ int totpolys = me->totpoly;
+
+ // <vcount>
+ int i;
+ int faces_in_polylist = 0;
+ std::vector<unsigned long> vcount_list;
+ bool is_triangulated = true;
+ // count faces with this material
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage):"";
+ if (tpageid == imageid) {
+ faces_in_polylist++;
+ vcount_list.push_back(p->totloop);
+ if (p->totloop != 3) {
+ is_triangulated = false;
+ }
+ }
+ }
+
+ // no faces using this imageid
+ if (faces_in_polylist == 0) {
+ if (imageid != "")
+ fprintf(stderr, "%s: Image %s is not used.\n", id_name(ob).c_str(), imageid.c_str());
+ return;
+ }
+
+ COLLADASW::PrimitivesBase *facelist = getFacelist(is_triangulated, mSW);
+
+ // sets count attribute in <polylist>
+ facelist->setCount(faces_in_polylist);
+
+ if (imageid != "") {
+ // sets material name
+ std::string material_id = get_material_id_from_id(imageid);
+ std::ostringstream ostr;
+ ostr << translate_id(material_id);
+ facelist->setMaterial(ostr.str());
+ }
+ COLLADASW::InputList &til = facelist->getInputList();
+
+ // creates <input> in <polylist> for vertices
+ COLLADASW::Input input1(COLLADASW::InputSemantic::VERTEX, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX), 0);
+
+ // creates <input> in <polylist> for normals
+ COLLADASW::Input input2(COLLADASW::InputSemantic::NORMAL, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::NORMAL), 1);
+
+ til.push_back(input1);
+ til.push_back(input2);
+
+ // if mesh has uv coords writes <input> for TEXCOORD
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (i = 0; i < num_layers; i++) {
+ if (!this->export_settings->active_uv_only || i == active_uv_index) {
+
+ std::string uv_name(bc_get_uvlayer_name(me, i));
+ std::string effective_id = geom_id; // (uv_name == "") ? geom_id : uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ i, this->export_settings->active_uv_only);
+
+ /* Note: the third parameter denotes the offset of TEXCOORD in polylist elements
+ For now this is always 2 (This may change sometime/maybe)
+ */
+ COLLADASW::Input input3(COLLADASW::InputSemantic::TEXCOORD,
+ makeUrl(layer_id),
+ 2, // this is only until we have optimized UV sets
+ (this->export_settings->active_uv_only) ? 0 : i // only_active_uv exported -> we have only one set
+ );
+ til.push_back(input3);
+ }
+ }
+
+ int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
+ if (totlayer_mcol > 0) {
+ int map_index = 0;
+
+ for (int a = 0; a < totlayer_mcol; a++) {
+ char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
+ COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
+ makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
+ (has_uvs) ? 3 : 2, // all color layers have same index order
+ map_index // set number equals color map index
+ );
+ til.push_back(input4);
+ map_index++;
+ }
+ }
+
+ // performs the actual writing
+ prepareToAppendValues(is_triangulated, facelist, vcount_list);
+
+ // <p>
+ int texindex = 0;
+ for (i = 0; i < totpolys; i++) {
+ MTexPoly *tp = &mtpolys[i];
+ MPoly *p = &mpolys[i];
+ int loop_count = p->totloop;
+ std::string tpageid = (tp->tpage) ? id_name(tp->tpage) : "";
+ if (tpageid == imageid) {
+ MLoop *l = &mloops[p->loopstart];
+ BCPolygonNormalsIndices normal_indices = norind[i];
+
+ for (int j = 0; j < loop_count; j++) {
+ facelist->appendValues(l[j].v);
+ facelist->appendValues(normal_indices[j]);
+ if (has_uvs)
+ facelist->appendValues(texindex + j);
+
+ if (has_color)
+ facelist->appendValues(texindex + j);
+ }
+ }
+
+ texindex += loop_count;
+ }
+
+ finishList(is_triangulated, facelist);
+ delete facelist;
+}
// creates <source> for positions
void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
@@ -479,12 +718,13 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
source.setAccessorCount(me->totloop);
- source.setAccessorStride(3);
+ source.setAccessorStride(4);
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
param.push_back("R");
param.push_back("G");
param.push_back("B");
+ param.push_back("A");
source.prepareToAppendValues();
@@ -496,7 +736,8 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
source.appendValues(
mlc->r / 255.0f,
mlc->g / 255.0f,
- mlc->b / 255.0f
+ mlc->b / 255.0f,
+ mlc->a / 255.0f
);
}
}
@@ -537,7 +778,13 @@ void GeometryExporter::createTexcoordsSource(std::string geom_id, Mesh *me)
MLoopUV *mloops = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a);
COLLADASW::FloatSourceF source(mSW);
- std::string layer_id = makeTexcoordSourceId(geom_id, a, this->export_settings->active_uv_only);
+ std::string active_uv_name(bc_get_active_uvlayer_name(me));
+ std::string effective_id = geom_id; // (active_uv_name == "") ? geom_id : active_uv_name;
+ std::string layer_id = makeTexcoordSourceId(
+ effective_id,
+ a,
+ this->export_settings->active_uv_only );
+
source.setId(layer_id);
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 69d1067e6f4..890304f4568 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -85,15 +85,33 @@ public:
Mesh *me,
std::string& geom_id);
- // powerful because it handles both cases when there is material and when there's not
+ // Create polylists for meshes with Materials
void createPolylist(short material_index,
- bool has_uvs,
- bool has_color,
- Object *ob,
- Mesh *me,
- std::string& geom_id,
- std::vector<BCPolygonNormalsIndices>& norind);
-
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylists(std::set<Image *> uv_images,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
+ // Create polylists for meshes with UV Textures
+ void createPolylist(std::string imageid,
+ bool has_uvs,
+ bool has_color,
+ Object *ob,
+ Mesh *me,
+ std::string& geom_id,
+ std::vector<BCPolygonNormalsIndices>& norind);
+
// creates <source> for positions
void createVertsSource(std::string geom_id, Mesh *me);
diff --git a/source/blender/collada/ImageExporter.cpp b/source/blender/collada/ImageExporter.cpp
index aac41e2e93c..93be7de6236 100644
--- a/source/blender/collada/ImageExporter.cpp
+++ b/source/blender/collada/ImageExporter.cpp
@@ -55,9 +55,9 @@ ImagesExporter::ImagesExporter(COLLADASW::StreamWriter *sw, const ExportSettings
void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
{
- std::string name(id_name(image));
- std::string translated_name(translate_id(name));
- bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_name) == mImages.end();
+ std::string id(id_name(image));
+ std::string translated_id(translate_id(id));
+ bool not_yet_exported = find(mImages.begin(), mImages.end(), translated_id) == mImages.end();
if (not_yet_exported) {
@@ -88,7 +88,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
// make absolute destination path
- BLI_strncpy(export_file, name.c_str(), sizeof(export_file));
+ BLI_strncpy(export_file, id.c_str(), sizeof(export_file));
BKE_image_path_ensure_ext_from_imformat(export_file, &imageFormat);
BLI_join_dirfile(export_path, sizeof(export_path), export_dir, export_file);
@@ -143,10 +143,11 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
}
}
- COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_name, translated_name); /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ /* set name also to mNameNC. This helps other viewers import files exported from Blender better */
+ COLLADASW::Image img(COLLADABU::URI(COLLADABU::URI::nativePathToUri(export_path)), translated_id, translated_id);
img.add(mSW);
fprintf(stdout, "Collada export: Added image: %s\n", export_file);
- mImages.push_back(translated_name);
+ mImages.push_back(translated_id);
BKE_image_release_ibuf(image, imbuf, NULL);
}
@@ -161,7 +162,7 @@ void ImagesExporter::export_UV_Images()
for (node = this->export_settings->export_set; node; node = node->next) {
Object *ob = (Object *)node->link;
- if (ob->type == OB_MESH && ob->totcol) {
+ if (ob->type == OB_MESH) {
Mesh *me = (Mesh *) ob->data;
BKE_mesh_tessface_ensure(me);
int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
@@ -189,7 +190,13 @@ void ImagesExporter::export_UV_Images()
}
}
-
+/* ============================================================
+ * Check if there are any images to be exported
+ * Returns true as soon as an object is detected that
+ * either has an UV Texture assigned, or has a material
+ * assigned that uses an Image Texture.
+ * ============================================================
+ */
bool ImagesExporter::hasImages(Scene *sce)
{
LinkNode *node;
@@ -232,11 +239,10 @@ void ImagesExporter::exportImages(Scene *sce)
openLibrary();
MaterialFunctor mf;
- if (this->export_settings->include_material_textures) {
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT) {
mf.forEachMaterialInExportSet<ImagesExporter>(sce, *this, this->export_settings->export_set);
}
-
- if (this->export_settings->include_uv_textures) {
+ else {
export_UV_Images();
}
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 2c52d73e756..4a2d4e8046a 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -37,6 +37,7 @@ public:
bool fix_orientation;
int min_chain_length;
char *filepath;
+ bool keep_bind_info;
};
#endif
diff --git a/source/blender/collada/InstanceWriter.cpp b/source/blender/collada/InstanceWriter.cpp
index 71371d280df..de1a4075462 100644
--- a/source/blender/collada/InstanceWriter.cpp
+++ b/source/blender/collada/InstanceWriter.cpp
@@ -32,43 +32,76 @@
#include "COLLADASWInstanceMaterial.h"
extern "C" {
- #include "BKE_customdata.h"
- #include "BKE_material.h"
- #include "DNA_mesh_types.h"
+#include "BKE_customdata.h"
+#include "BKE_material.h"
+#include "DNA_mesh_types.h"
}
#include "InstanceWriter.h"
#include "collada_internal.h"
#include "collada_utils.h"
-void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only)
+void InstanceWriter::add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type)
{
- for (int a = 0; a < ob->totcol; a++) {
- Material *ma = give_current_material(ob, a + 1);
-
- COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
+ bool all_uv_layers = !active_uv_only;
+ COLLADASW::InstanceMaterialList& iml = bind_material.getInstanceMaterialList();
- if (ma) {
- std::string matid(get_material_id(ma));
- matid = translate_id(matid);
+ if (export_texture_type == BC_TEXTURE_TYPE_UV)
+ {
+ std::set<Image *> uv_images = bc_getUVImages(ob, all_uv_layers);
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+ matid = get_material_id_from_id(matid);
std::ostringstream ostr;
ostr << matid;
COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
-
+
// create <bind_vertex_input> for each uv map
Mesh *me = (Mesh *)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
-
+
int map_index = 0;
- int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) -1;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
for (int b = 0; b < totlayer; b++) {
if (!active_uv_only || b == active_uv_index) {
char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
}
}
-
+
iml.push_back(im);
}
}
+
+ else {
+ for (int a = 0; a < ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a + 1);
+ if (ma) {
+ std::string matid(get_material_id(ma));
+ matid = translate_id(matid);
+ std::ostringstream ostr;
+ ostr << matid;
+ COLLADASW::InstanceMaterial im(ostr.str(), COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, matid));
+
+ // create <bind_vertex_input> for each uv map
+ Mesh *me = (Mesh *)ob->data;
+ int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+
+ int map_index = 0;
+ int active_uv_index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE) - 1;
+ for (int b = 0; b < totlayer; b++) {
+ if (!active_uv_only || b == active_uv_index) {
+ char *name = bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
+ im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", map_index++));
+ }
+ }
+
+ iml.push_back(im);
+ }
+ }
+ }
}
diff --git a/source/blender/collada/InstanceWriter.h b/source/blender/collada/InstanceWriter.h
index 49ddf091b1c..a46027325a2 100644
--- a/source/blender/collada/InstanceWriter.h
+++ b/source/blender/collada/InstanceWriter.h
@@ -31,11 +31,12 @@
#include "COLLADASWBindMaterial.h"
#include "DNA_object_types.h"
+#include "collada.h"
class InstanceWriter
{
protected:
- void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only);
+ void add_material_bindings(COLLADASW::BindMaterial& bind_material, Object *ob, bool active_uv_only, BC_export_texture_type export_texture_type);
};
#endif
diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp
index 4aece997f72..6e6cc24be20 100644
--- a/source/blender/collada/MaterialExporter.cpp
+++ b/source/blender/collada/MaterialExporter.cpp
@@ -38,14 +38,39 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw, const ExportSe
void MaterialsExporter::exportMaterials(Scene *sce)
{
- if (hasMaterials(sce)) {
- openLibrary();
+ if (this->export_settings->export_texture_type == BC_TEXTURE_TYPE_MAT)
+ {
+ if (hasMaterials(sce)) {
+ openLibrary();
- MaterialFunctor mf;
- mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
+ MaterialFunctor mf;
+ mf.forEachMaterialInExportSet<MaterialsExporter>(sce, *this, this->export_settings->export_set);
- closeLibrary();
+ closeLibrary();
+ }
}
+
+ else {
+ std::set<Image *> uv_images = bc_getUVImages(sce, !this->export_settings->active_uv_only);
+ if (uv_images.size() > 0) {
+ openLibrary();
+ std::set<Image *>::iterator uv_images_iter;
+ for (uv_images_iter = uv_images.begin();
+ uv_images_iter != uv_images.end();
+ uv_images_iter++) {
+
+ Image *ima = *uv_images_iter;
+ std::string matid(id_name(ima));
+
+ openMaterial(get_material_id_from_id(matid), translate_id(matid));
+ std::string efid = translate_id(matid) + "-effect";
+ addInstanceEffect(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, efid));
+ closeMaterial();
+ }
+ closeLibrary();
+ }
+ }
+
}
bool MaterialsExporter::hasMaterials(Scene *sce)
diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp
index 8f3bf88af65..6ca53c64299 100644
--- a/source/blender/collada/MeshImporter.cpp
+++ b/source/blender/collada/MeshImporter.cpp
@@ -27,7 +27,7 @@
#include <algorithm>
-#if !defined(WIN32) || defined(FREE_WINDOWS)
+#if !defined(WIN32)
#include <iostream>
#endif
@@ -1173,8 +1173,9 @@ Object *MeshImporter::create_mesh_object(COLLADAFW::Node *node, COLLADAFW::Insta
BKE_mesh_assign_object(ob, new_mesh);
BKE_mesh_calc_normals(new_mesh);
- if (old_mesh->id.us == 0) BKE_libblock_free(G.main, old_mesh);
-
+ id_us_plus(&old_mesh->id); /* Because BKE_mesh_assign_object would have already decreased it... */
+ BKE_libblock_free_us(G.main, old_mesh);
+
char layername[100];
layername[0] = '\0';
MTFace *texture_face = NULL;
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 30cd6ddf197..73945539931 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -151,7 +151,10 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, this->export_settings->use_object_instantiation)));
instGeom.setName(translate_id(id_name(ob)));
- InstanceWriter::add_material_bindings(instGeom.getBindMaterial(), ob, this->export_settings->active_uv_only);
+ InstanceWriter::add_material_bindings(instGeom.getBindMaterial(),
+ ob,
+ this->export_settings->active_uv_only,
+ this->export_settings->export_texture_type);
instGeom.add();
}
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 7242a24523c..c48c060dc95 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -27,7 +27,7 @@
#include <algorithm>
-#if !defined(WIN32) || defined(FREE_WINDOWS)
+#if !defined(WIN32)
#include <stdint.h>
#endif
@@ -230,7 +230,6 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
ArmatureModifierData *amd = (ArmatureModifierData *)md;
amd->object = ob_arm;
- struct bArmature *armature = (bArmature *)ob_arm->data;
#if 1
bc_set_parent(ob, ob_arm, C);
diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp
index f8f31304d28..7f742be7e30 100644
--- a/source/blender/collada/TransformReader.cpp
+++ b/source/blender/collada/TransformReader.cpp
@@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv)
/* pass */
}
-void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob)
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob)
+{
+ get_node_mat(mat, node, animation_map, ob, NULL);
+}
+
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob,
+ float parent_mat[4][4])
{
float cur[4][4];
float copy[4][4];
@@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
// then this is considered as redundant information.
// So if we find a Matrix we use that and return.
dae_matrix_to_mat4(tm, mat);
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
return;
case COLLADAFW::Transformation::TRANSLATE:
dae_translate_to_mat4(tm, cur);
@@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
(*animation_map)[anim_list_id] = anim;
}
}
+
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
}
void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h
index ab974b9ba85..08bb17ccac1 100644
--- a/source/blender/collada/TransformReader.h
+++ b/source/blender/collada/TransformReader.h
@@ -43,7 +43,7 @@
//struct Object;
-class TransformReader : public TransformBase
+class TransformReader
{
protected:
@@ -59,7 +59,8 @@ public:
TransformReader(UnitConverter *conv);
void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob);
-
+ void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]);
+
void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 908111ebae6..b7eeff3b074 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -27,11 +27,10 @@
#include "BKE_object.h"
+#include "BLI_math.h"
#include "TransformWriter.h"
-#include "BLI_math.h"
-
void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4])
{
float loc[3], rot[3], scale[3];
@@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
converter->mat4_to_dae_double(dmat, local);
delete converter;
- TransformBase::decompose(local, loc, rot, NULL, scale);
+ bc_decompose(local, loc, rot, NULL, scale);
if (node.getType() == COLLADASW::Node::JOINT) {
// XXX Why are joints handled differently ?
@@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
case BC_TRANSFORMATION_TYPE_TRANSROTLOC:
{
float loc[3], rot[3], scale[3];
- TransformBase::decompose(f_obmat, loc, rot, NULL, scale);
+ bc_decompose(f_obmat, loc, rot, NULL, scale);
add_transform(node, loc, rot, scale);
break;
}
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 7f69a4b9c95..5bb13d4aac9 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -33,9 +33,10 @@
#include "DNA_object_types.h"
#include "collada_internal.h"
+#include "collada_utils.h"
#include "collada.h"
-class TransformWriter : protected TransformBase
+class TransformWriter
{
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index fe8b1d2320a..024bc4a4a5c 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -48,7 +48,8 @@ int collada_import(bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length)
+ int min_chain_length,
+ int keep_bind_info)
{
ImportSettings import_settings;
@@ -58,6 +59,7 @@ int collada_import(bContext *C,
import_settings.find_chains = find_chains != 0;
import_settings.fix_orientation = fix_orientation != 0;
import_settings.min_chain_length = min_chain_length;
+ import_settings.keep_bind_info = keep_bind_info !=0;
DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
@@ -78,8 +80,7 @@ int collada_export(Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -87,7 +88,9 @@ int collada_export(Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim)
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info)
{
ExportSettings export_settings;
@@ -102,8 +105,7 @@ int collada_export(Scene *sce,
export_settings.deform_bones_only = deform_bones_only != 0;
export_settings.active_uv_only = active_uv_only != 0;
- export_settings.include_uv_textures = include_uv_textures != 0;
- export_settings.include_material_textures= include_material_textures != 0;
+ export_settings.export_texture_type = export_texture_type;
export_settings.use_texture_copies = use_texture_copies != 0;
export_settings.triangulate = triangulate != 0;
@@ -112,7 +114,8 @@ int collada_export(Scene *sce,
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
export_settings.open_sim = open_sim != 0;
-
+ export_settings.limit_precision = limit_precision != 0;
+ export_settings.keep_bind_info = keep_bind_info !=0;
int includeFilter = OB_REL_NONE;
if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index a4416608584..d31f5a8ba62 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -46,6 +46,11 @@ typedef enum BC_export_transformation_type {
BC_TRANSFORMATION_TYPE_TRANSROTLOC
} BC_export_transformation_type;
+typedef enum BC_export_texture_type {
+ BC_TEXTURE_TYPE_MAT,
+ BC_TEXTURE_TYPE_UV
+} BC_export_texture_type;
+
struct bContext;
struct Scene;
@@ -58,7 +63,9 @@ int collada_import(struct bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length);
+ int min_chain_length,
+
+ int keep_bind_info);
int collada_export(struct Scene *sce,
const char *filepath,
@@ -72,8 +79,7 @@ int collada_export(struct Scene *sce,
int deform_bones_only,
int active_uv_only,
- int include_uv_textures,
- int include_material_textures,
+ BC_export_texture_type export_texture_type,
int use_texture_copies,
int triangulate,
@@ -81,9 +87,10 @@ int collada_export(struct Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim);
-
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 38855013ee1..8974acb3460 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -33,11 +33,8 @@
UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
{
- unit_m4(x_up_mat4);
- rotate_m4(x_up_mat4, 'Y', -0.5 * M_PI);
-
- unit_m4(y_up_mat4);
- rotate_m4(y_up_mat4, 'X', 0.5 * M_PI);
+ axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI);
+ axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI);
unit_m4(z_up_mat4);
unit_m4(scale_mat4);
@@ -165,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce)
size_to_mat4(scale_mat4, rescale);
}
-void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
-{
- 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]);
-}
-
/**
* Translation map.
* Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
@@ -344,7 +329,12 @@ std::string get_light_id(Object *ob)
std::string get_joint_id(Bone *bone, Object *ob_arm)
{
- return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name);
+ return translate_id(id_name(ob_arm) + "_" + bone->name);
+}
+
+std::string get_joint_sid(Bone *bone, Object *ob_arm)
+{
+ return translate_id(bone->name);
}
std::string get_camera_id(Object *ob)
@@ -354,7 +344,13 @@ std::string get_camera_id(Object *ob)
std::string get_material_id(Material *mat)
{
- return translate_id(id_name(mat)) + "-material";
+ std::string id = id_name(mat);
+ return get_material_id_from_id(id);
+}
+
+std::string get_material_id_from_id(std::string id)
+{
+ return translate_id(id) + "-material";
}
std::string get_morph_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 4aa637a6876..5f3fa34edc1 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -85,12 +85,6 @@ public:
};
-class TransformBase
-{
-public:
- void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
-};
-
extern void clear_global_id_map();
/** Look at documentation of translate_map */
extern std::string translate_id(const std::string &id);
@@ -104,10 +98,12 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation);
extern std::string get_light_id(Object *ob);
extern std::string get_joint_id(Bone *bone, Object *ob_arm);
+extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
extern std::string get_material_id(Material *mat);
+extern std::string get_material_id_from_id(std::string id);
extern std::string get_morph_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 2efa8b21d81..b09732f9102 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,7 +32,7 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
-#include "collada_utils.h"
+#include <set>
extern "C" {
#include "DNA_modifier_types.h"
@@ -63,6 +63,9 @@ extern "C" {
#include "bmesh_tools.h"
}
+#include "collada_utils.h"
+#include "ExportSettings.h"
+
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
{
if (index >= array.getValuesCount())
@@ -352,6 +355,28 @@ void bc_match_scale(std::vector<Object *> *objects_done,
}
}
+/*
+ Convenience function to get only the needed components of a matrix
+*/
+void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
+{
+ if (size) {
+ mat4_to_size(size, mat);
+ }
+
+ if (eul) {
+ mat4_to_eul(eul, mat);
+ }
+
+ if (quat) {
+ mat4_to_quat(quat, mat);
+ }
+
+ if (loc) {
+ copy_v3_v3(loc, mat[3]);
+ }
+}
+
void bc_triangulate_mesh(Mesh *me)
{
bool use_beauty = false;
@@ -612,3 +637,356 @@ int BoneExtended::get_use_connect()
{
return this->use_connect;
}
+
+/**
+* Stores a 4*4 matrix as a custom bone property array of size 16
+*/
+void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
+{
+ IDProperty *idgroup = (IDProperty *)ebone->prop;
+ if (idgroup == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ ebone->prop = idgroup;
+ }
+
+ IDPropertyTemplate val = { 0 };
+ val.array.len = 16;
+ val.array.type = IDP_FLOAT;
+
+ IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
+ float *array = (float *)IDP_Array(data);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ array[4 * i + j] = mat[i][j];
+
+ IDP_AddToGroup(idgroup, data);
+}
+
+#if 0
+/**
+* Stores a Float value as a custom bone property
+*
+* Note: This function is currently not needed. Keep for future usage
+*/
+static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
+{
+ if (ebone->prop == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ }
+
+ IDProperty *pgroup = (IDProperty *)ebone->prop;
+ IDPropertyTemplate val = { 0 };
+ IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
+ IDP_Float(prop) = value;
+ IDP_AddToGroup(pgroup, prop);
+
+}
+#endif
+
+/*
+* Get a custom property when it exists.
+* This function is also used to check if a property exists.
+*/
+IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
+{
+ return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
+}
+
+/**
+* Read a custom bone property and convert to float
+* Return def if the property does not exist.
+*/
+float bc_get_property(Bone *bone, std::string key, float def)
+{
+ float result = def;
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property) {
+ switch (property->type) {
+ case IDP_INT:
+ result = (float)(IDP_Int(property));
+ break;
+ case IDP_FLOAT:
+ result = (float)(IDP_Float(property));
+ break;
+ case IDP_DOUBLE:
+ result = (float)(IDP_Double(property));
+ break;
+ default:
+ result = def;
+ }
+ }
+ return result;
+}
+
+/**
+* Read a custom bone property and convert to matrix
+* Return true if conversion was succesfull
+*
+* Return false if:
+* - the property does not exist
+* - is not an array of size 16
+*/
+bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
+{
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property && property->type == IDP_ARRAY && property->len == 16) {
+ float *array = (float *)IDP_Array(property);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = array[4 * i + j];
+ return true;
+ }
+ return false;
+}
+
+/**
+* get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
+*/
+void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
+{
+ val[0] = bc_get_property(bone, key + "_x", def[0]);
+ val[1] = bc_get_property(bone, key + "_y", def[1]);
+ val[2] = bc_get_property(bone, key + "_z", def[2]);
+}
+
+/**
+* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
+*/
+static bool has_custom_props(Bone *bone, bool enabled, std::string key)
+{
+ if (!enabled)
+ return false;
+
+ return (bc_get_IDProperty(bone, key + "_x")
+ || bc_get_IDProperty(bone, key + "_y")
+ || bc_get_IDProperty(bone, key + "_z"));
+
+}
+
+/**
+* Check if custom information about bind matrix exists and modify the from_mat
+* accordingly.
+*
+* Note: This is old style for Blender <= 2.78 only kept for compatibility
+*/
+void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
+{
+ float loc[3];
+ float rot[3];
+ float scale[3];
+ static const float V0[3] = { 0, 0, 0 };
+
+ if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
+ {
+ /* No need */
+ copy_m4_m4(to_mat, from_mat);
+ return;
+ }
+
+ bc_decompose(from_mat, loc, rot, NULL, scale);
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_loc", loc, loc);
+
+ if (use_local_space && bone->parent) {
+ Bone *b = bone;
+ while (b->parent) {
+ b = b->parent;
+ float ploc[3];
+ bc_get_property_vector(b, "restpose_loc", ploc, V0);
+ loc[0] += ploc[0];
+ loc[1] += ploc[1];
+ loc[2] += ploc[2];
+ }
+ }
+ }
+
+ if (export_settings->keep_bind_info) {
+ if (bc_get_IDProperty(bone, "restpose_rot_x"))
+ rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_y"))
+ rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_z"))
+ rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
+ }
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_scale", scale, scale);
+ }
+
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+}
+
+/*
+ Make 4*4 matrices better readable
+*/
+void bc_sanitize_mat(float mat[4][4], int precision)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = double_round(mat[i][j], precision);
+}
+
+/*
+* Returns name of Active UV Layer or empty String if no active UV Layer defined.
+* Assuming the Object is of type MESH
+*/
+std::string bc_get_active_uvlayer_name(Object *ob)
+{
+ Mesh *me = (Mesh *)ob->data;
+ return bc_get_active_uvlayer_name(me);
+}
+
+/*
+ * Returns name of Active UV Layer or empty String if no active UV Layer defined
+ */
+std::string bc_get_active_uvlayer_name(Mesh *me)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers) {
+ return std::string(bc_CustomData_get_active_layer_name(&me->fdata, CD_MTFACE));
+ }
+ return "";
+}
+
+/*
+ * Returns UV Layer name or empty string if layer index is out of range
+ */
+std::string bc_get_uvlayer_name(Mesh *me, int layer)
+{
+ int num_layers = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
+ if (num_layers && layer < num_layers) {
+ return std::string(bc_CustomData_get_layer_name(&me->fdata, CD_MTFACE, layer));
+ }
+ return "";
+}
+
+/**********************************************************************
+*
+* Return the list of Mesh objects with assigned UVtextures and Images
+* Note: We need to create artificaial materials for each of them
+*
+***********************************************************************/
+std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers)
+{
+ std::set <Object *> UVObjects;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ has_uvimage = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (has_uvimage) {
+ UVObjects.insert(ob);
+ }
+ }
+ base = base->next;
+ }
+ return UVObjects;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images from all exported Mesh Items
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+ Base *base = (Base *)sce->base.first;
+
+ while (base) {
+ Object *ob = base->object;
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ base = base->next;
+ }
+ return UVImages;
+}
+
+/**********************************************************************
+*
+* Return the list of UV Texture images for the given Object
+* Note: We need to create one artificial material for each Image.
+*
+***********************************************************************/
+std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers)
+{
+ std::set <Image *> UVImages;
+
+ bool has_uvimage = false;
+ if (ob->type == OB_MESH) {
+ Mesh *me = (Mesh *)ob->data;
+ int active_uv_layer = CustomData_get_active_layer_index(&me->pdata, CD_MTEXPOLY);
+
+ for (int i = 0; i < me->pdata.totlayer && !has_uvimage; i++) {
+ if (all_uv_layers || active_uv_layer == i)
+ {
+ if (me->pdata.layers[i].type == CD_MTEXPOLY) {
+ MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data;
+ MPoly *mpoly = me->mpoly;
+ for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) {
+
+ Image *ima = txface->tpage;
+ if (ima != NULL) {
+ if (UVImages.find(ima) == UVImages.end())
+ UVImages.insert(ima);
+ }
+ }
+ }
+ }
+ }
+ }
+ return UVImages;
+} \ No newline at end of file
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 7fdbef3b6cb..5447c39e902 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -34,6 +34,7 @@
#include <vector>
#include <map>
+#include <set>
#include <algorithm>
extern "C" {
@@ -53,8 +54,10 @@ extern "C" {
#include "BKE_object.h"
#include "BKE_DerivedMesh.h"
#include "BKE_scene.h"
+#include "BKE_idprop.h"
}
+#include "ImportSettings.h"
#include "ExportSettings.h"
#include "collada_internal.h"
@@ -78,6 +81,7 @@ extern void bc_set_mark(Object *ob);
extern char *bc_CustomData_get_layer_name(const CustomData *data, int type, int n);
extern char *bc_CustomData_get_active_layer_name(const CustomData *data, int type);
+extern char *bc_CustomData_get_layer_name(const CustomData *data, int layer_index, int type);
extern void bc_bubble_sort_by_Object_name(LinkNode *export_set);
extern bool bc_is_root_bone(Bone *aBone, bool deform_bones_only);
@@ -88,11 +92,32 @@ extern std::string bc_url_encode(std::string data);
extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene);
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
+extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
+
extern void bc_triangulate_mesh(Mesh *me);
extern bool bc_is_leaf_bone(Bone *bone);
extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
extern int bc_set_layer(int bitfield, int layer, bool enable);
extern int bc_set_layer(int bitfield, int layer);
+extern void bc_sanitize_mat(float mat[4][4], int precision);
+
+extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key);
+extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value);
+extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]);
+
+extern float bc_get_property(Bone *bone, std::string key, float def);
+extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]);
+extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]);
+
+extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
+
+extern std::string bc_get_active_uvlayer_name(Object *ob);
+extern std::string bc_get_active_uvlayer_name(Mesh *me);
+extern std::string bc_get_uvlayer_name(Mesh *me, int layer);
+
+extern std::set<Image *> bc_getUVImages(Scene *sce, bool all_uv_layers);
+extern std::set<Image *> bc_getUVImages(Object *ob, bool all_uv_layers);
+extern std::set<Object *> bc_getUVTexturedObjects(Scene *sce, bool all_uv_layers);
class BCPolygonNormalsIndices
{