9#include "COLLADASWBaseInputElement.h"
10#include "COLLADASWInstanceController.h"
11#include "COLLADASWPrimitves.h"
12#include "COLLADASWSource.h"
39void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins,
43 if (
bc_is_root_bone(bone, this->export_settings.get_deform_bones_only())) {
45 ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, node_id));
49 write_bone_URLs(ins, ob_arm, child);
59 const std::string &controller_id = get_controller_id(ob_arm, ob);
61 COLLADASW::InstanceController ins(mSW);
62 ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
65 if (mesh->deform_verts().is_empty()) {
71 write_bone_URLs(ins, ob_arm, bone);
75 ins.getBindMaterial(), ob,
this->export_settings.get_active_uv_only());
83 Scene *sce = blender_context.get_scene();
88 sce, *
this, this->export_settings.get_export_set());
99 export_skin_controller(ob, ob_arm);
101 if (key && this->export_settings.get_include_shapekeys()) {
102 export_morph_controller(ob, key);
107bool ArmatureExporter::already_written(
Object *ob_arm)
109 return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) !=
110 written_armatures.end();
113void ArmatureExporter::wrote(
Object *ob_arm)
115 written_armatures.push_back(ob_arm);
118void ArmatureExporter::find_objects_using_armature(
Object *ob_arm,
119 std::vector<Object *> &objects,
124 Base *base = (
Base *)sce->base.first;
126 Object *ob = base->object;
128 if (ob->
type ==
OB_MESH && get_assigned_armature(ob) == ob_arm) {
129 objects.push_back(ob);
137std::string ControllerExporter::get_controller_id(
Object *ob_arm,
Object *ob)
140 SKIN_CONTROLLER_ID_SUFFIX;
143std::string ControllerExporter::get_controller_id(
Key *key,
Object *ob)
148void ControllerExporter::export_skin_controller(
Object *ob,
Object *ob_arm)
158 bool use_instantiation = this->export_settings.get_use_object_instantiation();
161 if (((
Mesh *)ob->
data)->deform_verts().is_empty()) {
167 this->export_settings.get_export_mesh_type(),
168 this->export_settings.get_apply_modifiers(),
169 this->export_settings.get_triangulate());
171 std::string controller_name =
id_name(ob_arm);
172 std::string controller_id = get_controller_id(ob_arm, ob);
174 openSkin(controller_id,
176 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING,
get_geometry_id(ob, use_instantiation)));
178 add_bind_shape_mat(ob);
181 std::string joints_source_id = add_joints_source(ob_arm, defbase, controller_id);
182 std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, defbase, controller_id);
184 std::list<int> vcounts;
185 std::list<int> joints;
186 std::list<float> weights;
192 std::vector<int> joint_index_by_def_index;
196 if (is_bone_defgroup(ob_arm, def)) {
197 joint_index_by_def_index.push_back(j++);
200 joint_index_by_def_index.push_back(-1);
204 const MDeformVert *dvert = mesh->deform_verts().data();
208 std::map<int, float> jw;
215 if (idx >= joint_index_by_def_index.size()) {
221 int joint_index = joint_index_by_def_index[idx];
222 if (joint_index != -1 && vert->
dw[j].
weight > 0.0f) {
223 jw[joint_index] += vert->
dw[j].
weight;
230 float invsumw = 1.0f / sumw;
231 vcounts.push_back(jw.size());
232 for (
auto &index_and_weight : jw) {
233 joints.push_back(index_and_weight.first);
234 weights.push_back(invsumw * index_and_weight.second);
238 vcounts.push_back(0);
240 vcounts.push_back(1);
241 joints.push_back(-1);
242 weights.push_back(1.0f);
247 if (oob_counter > 0) {
249 "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
251 joint_index_by_def_index.size());
255 std::string weights_source_id = add_weights_source(mesh, controller_id, weights);
256 add_joints_element(defbase, joints_source_id, inv_bind_mat_source_id);
257 add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
265void ControllerExporter::export_morph_controller(
Object *ob,
Key *key)
267 bool use_instantiation = this->export_settings.get_use_object_instantiation();
272 this->export_settings.get_export_mesh_type(),
273 this->export_settings.get_apply_modifiers(),
274 this->export_settings.get_triangulate());
276 std::string controller_name =
id_name(ob) +
"-morph";
277 std::string controller_id = get_controller_id(key, ob);
282 COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING,
get_geometry_id(ob, use_instantiation)));
284 std::string targets_id = add_morph_targets(key, ob);
285 std::string morph_weights_id = add_morph_weights(key, ob);
287 COLLADASW::TargetsElement targets(mSW);
289 COLLADASW::InputList &
input = targets.getInputList();
291 input.push_back(COLLADASW::Input(
292 COLLADASW::InputSemantic::MORPH_TARGET,
293 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id)));
295 COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT,
296 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
303 add_weight_extras(key);
308std::string ControllerExporter::add_morph_targets(
Key *key,
Object *ob)
312 COLLADASW::IdRefSource source(mSW);
313 source.setId(source_id);
314 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
315 source.setAccessorCount(key->
totkey - 1);
316 source.setAccessorStride(1);
318 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
319 param.emplace_back(
"IDREF");
321 source.prepareToAppendValues();
326 for (; kb; kb = kb->next) {
328 source.appendValues(geom_id);
336std::string ControllerExporter::add_morph_weights(
Key *key,
Object *ob)
340 COLLADASW::FloatSourceF source(mSW);
341 source.setId(source_id);
342 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
343 source.setAccessorCount(key->
totkey - 1);
344 source.setAccessorStride(1);
346 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
347 param.emplace_back(
"MORPH_WEIGHT");
349 source.prepareToAppendValues();
354 for (; kb; kb = kb->next) {
355 float weight = kb->curval;
356 source.appendValues(weight);
363void ControllerExporter::add_weight_extras(
Key *key)
366 COLLADASW::BaseExtraTechnique extra;
371 for (; kb; kb = kb->next) {
374 extra.addExtraTechniqueParameter(
"KHR",
"morph_weights", 0.000,
"MORPH_WEIGHT_TO_TARGET");
378void ControllerExporter::add_joints_element(
const ListBase *defbase,
379 const std::string &joints_source_id,
380 const std::string &inv_bind_mat_source_id)
382 COLLADASW::JointsElement joints(mSW);
383 COLLADASW::InputList &
input = joints.getInputList();
385 input.push_back(COLLADASW::Input(
386 COLLADASW::InputSemantic::JOINT,
387 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
389 COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
390 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
394void ControllerExporter::add_bind_shape_mat(
Object *ob)
396 double bind_mat[4][4];
400 if (export_settings.get_apply_global_orientation()) {
409 if (this->export_settings.get_limit_precision()) {
413 addBindShapeTransform(bind_mat);
416std::string ControllerExporter::add_joints_source(
Object *ob_arm,
418 const std::string &controller_id)
420 std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
424 if (is_bone_defgroup(ob_arm, def)) {
429 COLLADASW::NameSource source(mSW);
430 source.setId(source_id);
431 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
432 source.setAccessorCount(totjoint);
433 source.setAccessorStride(1);
435 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
436 param.emplace_back(
"JOINT");
438 source.prepareToAppendValues();
441 Bone *bone = get_bone_from_defgroup(ob_arm, def);
452std::string ControllerExporter::add_inv_bind_mats_source(
Object *ob_arm,
454 const std::string &controller_id)
456 std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
460 if (is_bone_defgroup(ob_arm, def)) {
465 COLLADASW::FloatSourceF source(mSW);
466 source.setId(source_id);
467 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
468 source.setAccessorCount(totjoint);
469 source.setAccessorStride(16);
471 source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
472 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
473 param.emplace_back(
"TRANSFORM");
475 source.prepareToAppendValues();
480 int flag = arm->flag;
484 Depsgraph *
depsgraph = blender_context.get_depsgraph();
485 Scene *scene = blender_context.get_scene();
492 if (is_bone_defgroup(ob_arm, def)) {
497 float inv_bind_mat[4][4];
499 float bind_mat[4][4];
508 this->export_settings, pchan->
bone, bind_mat, pchan->
bone->
arm_mat,
true);
511 if (export_settings.get_open_sim()) {
513 float rot[3] = {0, 0, 0};
523 mul_m4_m4m4(world, ob_arm->object_to_world().ptr(), bind_mat);
526 if (export_settings.get_apply_global_orientation()) {
533 if (this->export_settings.get_limit_precision()) {
536 source.appendValues(inv_bind_mat);
542 Depsgraph *
depsgraph = blender_context.get_depsgraph();
543 Scene *scene = blender_context.get_scene();
556 return pchan ? pchan->
bone :
nullptr;
561 return get_bone_from_defgroup(ob_arm, def) !=
nullptr;
564std::string ControllerExporter::add_weights_source(
Mesh *mesh,
565 const std::string &controller_id,
566 const std::list<float> &weights)
568 std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
570 COLLADASW::FloatSourceF source(mSW);
571 source.setId(source_id);
572 source.setArrayId(source_id + ARRAY_ID_SUFFIX);
573 source.setAccessorCount(weights.size());
574 source.setAccessorStride(1);
576 COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
577 param.emplace_back(
"WEIGHT");
579 source.prepareToAppendValues();
581 for (
float weight : weights) {
582 source.appendValues(weight);
590void ControllerExporter::add_vertex_weights_element(
const std::string &weights_source_id,
591 const std::string &joints_source_id,
592 const std::list<int> &vcounts,
593 const std::list<int> &joints)
595 COLLADASW::VertexWeightsElement weightselem(mSW);
596 COLLADASW::InputList &
input = weightselem.getInputList();
599 input.push_back(COLLADASW::Input(
600 COLLADASW::InputSemantic::JOINT,
601 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id),
604 COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
605 COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id),
608 weightselem.setCount(vcounts.size());
611 COLLADASW::PrimitivesBase::VCountList vcountlist;
613 vcountlist.resize(vcounts.size());
614 std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
616 weightselem.prepareToAppendVCountValues();
617 weightselem.appendVertexCount(vcountlist);
619 weightselem.CloseVCountAndOpenVElement();
622 int weight_index = 0;
623 for (
int joint_index : joints) {
624 weightselem.appendValues(joint_index, weight_index++);
627 weightselem.finish();
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
Key * BKE_key_from_object(Object *ob)
void BKE_id_free(Main *bmain, void *idv)
void BKE_object_matrix_local_get(Object *ob, float r_mat[4][4])
#define LISTBASE_FOREACH(type, var, list)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void loc_eulO_size_to_mat4(float R[4][4], const float loc[3], const float eul[3], const float size[3], short order)
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
struct bPoseChannel bPoseChannel
struct bArmature bArmature
struct MDeformVert MDeformVert
struct bDeformGroup bDeformGroup
BPy_StructRNA * depsgraph
static void sanitize(Matrix &matrix, int precision)
ControllerExporter(BlenderContext &blender_context, COLLADASW::StreamWriter *sw, BCExportSettings &export_settings)
bool add_instance_controller(Object *ob)
void operator()(Object *ob)
bool is_skinned_mesh(Object *ob)
void export_controllers()
void add_material_bindings(COLLADASW::BindMaterial &bind_material, Object *ob, bool active_uv_only)
static void mat4_to_dae(float out[4][4], float in[4][4])
static void mat4_to_dae_double(double out[4][4], float in[4][4])
std::string get_joint_sid(Bone *bone)
std::string translate_id(const char *idString)
std::string get_geometry_id(Object *ob)
std::string id_name(void *id)
bool bc_is_root_bone(Bone *aBone, bool deform_bones_only)
void bc_add_global_transform(Matrix &to_mat, const Matrix &from_mat, const BCMatrix &global_transform, const bool invert)
void bc_apply_global_transform(Matrix &to_mat, const BCMatrix &global_transform, const bool invert)
Object * bc_get_assigned_armature(Object *ob)
void bc_create_restpose_mat(BCExportSettings &export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
Mesh * bc_get_mesh_copy(BlenderContext &blender_context, Object *ob, BC_export_mesh_type export_mesh_type, bool apply_modifiers, bool triangulate)
void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
bool bc_get_property_matrix(Bone *bone, const std::string &key, float mat[4][4])
constexpr int LIMITTED_PRECISION
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)