There were at least three copies of those: - OB_RECALC* family of flags, which are rudiment of an old dependency graph system. - PSYS_RECALC* which were used by old dependency graph system as a separate set since the graph itself did not handle particle systems. - DEG_TAG_* which was used to tag IDs. Now there is a single set, which defines what can be tagged and queried for an update. It also has some aggregate flags to make queries simpler. Lets once and for all solve the madness of those flags, stick to a single set, which will not overlap with anything or require any extra conversion. Technically, shouldn't be measurable user difference, but some of the agregate flags for few dependency graph components did change. Fixes T58632: Particle don't update rotation settings
352 lines
10 KiB
C++
352 lines
10 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file blender/collada/SkinInfo.cpp
|
|
* \ingroup collada
|
|
*/
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#if !defined(WIN32)
|
|
#include <stdint.h>
|
|
#endif
|
|
|
|
/* COLLADABU_ASSERT, may be able to remove later */
|
|
#include "COLLADABUPlatform.h"
|
|
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_math.h"
|
|
#include "BLI_compiler_attrs.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
#include "DNA_modifier_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "BKE_action.h"
|
|
#include "BKE_object.h"
|
|
#include "BKE_object_deform.h"
|
|
|
|
#include "ED_mesh.h"
|
|
#include "ED_object.h"
|
|
|
|
#include "SkinInfo.h"
|
|
#include "collada_utils.h"
|
|
|
|
// use name, or fall back to original id if name not present (name is optional)
|
|
template<class T>
|
|
static const char *bc_get_joint_name(T *node)
|
|
{
|
|
const std::string& id = node->getName();
|
|
return id.size() ? id.c_str() : node->getOriginalId().c_str();
|
|
}
|
|
|
|
// This is used to store data passed in write_controller_data.
|
|
// Arrays from COLLADAFW::SkinControllerData lose ownership, so do this class members
|
|
// so that arrays don't get freed until we free them explicitly.
|
|
SkinInfo::SkinInfo()
|
|
{
|
|
/* pass */
|
|
}
|
|
|
|
SkinInfo::SkinInfo(const SkinInfo& skin) : weights(skin.weights),
|
|
joint_data(skin.joint_data),
|
|
unit_converter(skin.unit_converter),
|
|
ob_arm(skin.ob_arm),
|
|
controller_uid(skin.controller_uid),
|
|
parent(skin.parent)
|
|
{
|
|
copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix);
|
|
|
|
transfer_uint_array_data_const(skin.joints_per_vertex, joints_per_vertex);
|
|
transfer_uint_array_data_const(skin.weight_indices, weight_indices);
|
|
transfer_int_array_data_const(skin.joint_indices, joint_indices);
|
|
}
|
|
|
|
SkinInfo::SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) {
|
|
}
|
|
|
|
// nobody owns the data after this, so it should be freed manually with releaseMemory
|
|
template <class T>
|
|
void SkinInfo::transfer_array_data(T& src, T& dest)
|
|
{
|
|
dest.setData(src.getData(), src.getCount());
|
|
src.yieldOwnerShip();
|
|
dest.yieldOwnerShip();
|
|
}
|
|
|
|
// when src is const we cannot src.yieldOwnerShip, this is used by copy constructor
|
|
void SkinInfo::transfer_int_array_data_const(const COLLADAFW::IntValuesArray& src, COLLADAFW::IntValuesArray& dest)
|
|
{
|
|
dest.setData((int *)src.getData(), src.getCount());
|
|
dest.yieldOwnerShip();
|
|
}
|
|
|
|
void SkinInfo::transfer_uint_array_data_const(const COLLADAFW::UIntValuesArray& src, COLLADAFW::UIntValuesArray& dest)
|
|
{
|
|
dest.setData((unsigned int *)src.getData(), src.getCount());
|
|
dest.yieldOwnerShip();
|
|
}
|
|
|
|
void SkinInfo::borrow_skin_controller_data(const COLLADAFW::SkinControllerData *skin)
|
|
{
|
|
transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getJointsPerVertex(), joints_per_vertex);
|
|
transfer_array_data((COLLADAFW::UIntValuesArray &)skin->getWeightIndices(), weight_indices);
|
|
transfer_array_data((COLLADAFW::IntValuesArray &)skin->getJointIndices(), joint_indices);
|
|
// transfer_array_data(skin->getWeights(), weights);
|
|
|
|
// cannot transfer data for FloatOrDoubleArray, copy values manually
|
|
const COLLADAFW::FloatOrDoubleArray& weight = skin->getWeights();
|
|
for (unsigned int i = 0; i < weight.getValuesCount(); i++)
|
|
weights.push_back(bc_get_float_value(weight, i));
|
|
|
|
unit_converter->dae_matrix_to_mat4_(bind_shape_matrix, skin->getBindShapeMatrix());
|
|
}
|
|
|
|
void SkinInfo::free()
|
|
{
|
|
joints_per_vertex.releaseMemory();
|
|
weight_indices.releaseMemory();
|
|
joint_indices.releaseMemory();
|
|
// weights.releaseMemory();
|
|
}
|
|
|
|
// using inverse bind matrices to construct armature
|
|
// it is safe to invert them to get the original matrices
|
|
// because if they are inverse matrices, they can be inverted
|
|
void SkinInfo::add_joint(const COLLADABU::Math::Matrix4& matrix)
|
|
{
|
|
JointData jd;
|
|
unit_converter->dae_matrix_to_mat4_(jd.inv_bind_mat, matrix);
|
|
joint_data.push_back(jd);
|
|
}
|
|
|
|
void SkinInfo::set_controller(const COLLADAFW::SkinController *co)
|
|
{
|
|
controller_uid = co->getUniqueId();
|
|
|
|
// fill in joint UIDs
|
|
const COLLADAFW::UniqueIdArray& joint_uids = co->getJoints();
|
|
for (unsigned int i = 0; i < joint_uids.getCount(); i++) {
|
|
joint_data[i].joint_uid = joint_uids[i];
|
|
|
|
// // store armature pointer
|
|
// JointData& jd = joint_index_to_joint_info_map[i];
|
|
// jd.ob_arm = ob_arm;
|
|
|
|
// now we'll be able to get inv bind matrix from joint id
|
|
// joint_id_to_joint_index_map[joint_ids[i]] = i;
|
|
}
|
|
}
|
|
|
|
// called from write_controller
|
|
Object *SkinInfo::create_armature(Main *bmain, Scene *scene, ViewLayer *view_layer)
|
|
{
|
|
ob_arm = bc_add_object(bmain, scene, view_layer, OB_ARMATURE, NULL);
|
|
return ob_arm;
|
|
}
|
|
|
|
Object *SkinInfo::set_armature(Object *ob_arm)
|
|
{
|
|
if (this->ob_arm)
|
|
return this->ob_arm;
|
|
|
|
this->ob_arm = ob_arm;
|
|
return ob_arm;
|
|
}
|
|
|
|
bool SkinInfo::get_joint_inv_bind_matrix(float inv_bind_mat[4][4], COLLADAFW::Node *node)
|
|
{
|
|
const COLLADAFW::UniqueId& uid = node->getUniqueId();
|
|
std::vector<JointData>::iterator it;
|
|
for (it = joint_data.begin(); it != joint_data.end(); it++) {
|
|
if ((*it).joint_uid == uid) {
|
|
copy_m4_m4(inv_bind_mat, (*it).inv_bind_mat);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Object *SkinInfo::BKE_armature_from_object()
|
|
{
|
|
return ob_arm;
|
|
}
|
|
|
|
const COLLADAFW::UniqueId& SkinInfo::get_controller_uid()
|
|
{
|
|
return controller_uid;
|
|
}
|
|
|
|
// check if this skin controller references a joint or any descendant of it
|
|
//
|
|
// some nodes may not be referenced by SkinController,
|
|
// in this case to determine if the node belongs to this armature,
|
|
// we need to search down the tree
|
|
bool SkinInfo::uses_joint_or_descendant(COLLADAFW::Node *node)
|
|
{
|
|
const COLLADAFW::UniqueId& uid = node->getUniqueId();
|
|
std::vector<JointData>::iterator it;
|
|
for (it = joint_data.begin(); it != joint_data.end(); it++) {
|
|
if ((*it).joint_uid == uid)
|
|
return true;
|
|
}
|
|
|
|
COLLADAFW::NodePointerArray& children = node->getChildNodes();
|
|
for (unsigned int i = 0; i < children.getCount(); i++) {
|
|
if (uses_joint_or_descendant(children[i]))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid,
|
|
TransformReader *tm)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
Scene *scene = CTX_data_scene(C);
|
|
|
|
ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
|
|
ArmatureModifierData *amd = (ArmatureModifierData *)md;
|
|
amd->object = ob_arm;
|
|
|
|
#if 1
|
|
/* XXX Why do we enforce objects to be children of Armatures if they weren't so before ?*/
|
|
if (!BKE_object_is_child_recursive(ob_arm, ob)) {
|
|
bc_set_parent(ob, ob_arm, C);
|
|
}
|
|
#else
|
|
Object workob;
|
|
ob->parent = ob_arm;
|
|
ob->partype = PAROBJECT;
|
|
|
|
BKE_object_workob_calc_parent(scene, ob, &workob);
|
|
invert_m4_m4(ob->parentinv, workob.obmat);
|
|
|
|
DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
|
|
#endif
|
|
copy_m4_m4(ob->obmat, bind_shape_matrix);
|
|
BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
|
|
|
|
amd->deformflag = ARM_DEF_VGROUP;
|
|
|
|
// create all vertex groups
|
|
std::vector<JointData>::iterator it;
|
|
int joint_index;
|
|
for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) {
|
|
const char *name = "Group";
|
|
|
|
// skip joints that have invalid UID
|
|
if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue;
|
|
|
|
// name group by joint node name
|
|
|
|
if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) {
|
|
name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]);
|
|
}
|
|
|
|
BKE_object_defgroup_add_name(ob, name);
|
|
}
|
|
|
|
// <vcount> - number of joints per vertex - joints_per_vertex
|
|
// <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices
|
|
// ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender?
|
|
|
|
// for each vertex in weight indices
|
|
// for each bone index in vertex
|
|
// add vertex to group at group index
|
|
// treat group index -1 specially
|
|
|
|
// get def group by index with BLI_findlink
|
|
|
|
for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) {
|
|
|
|
unsigned int limit = weight + joints_per_vertex[vertex];
|
|
for (; weight < limit; weight++) {
|
|
int joint = joint_indices[weight], joint_weight = weight_indices[weight];
|
|
|
|
// -1 means "weight towards the bind shape", we just don't assign it to any group
|
|
if (joint != -1) {
|
|
bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint);
|
|
|
|
ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bPoseChannel *SkinInfo::get_pose_channel_from_node(COLLADAFW::Node *node)
|
|
{
|
|
return BKE_pose_channel_find_name(ob_arm->pose, bc_get_joint_name(node));
|
|
}
|
|
|
|
void SkinInfo::set_parent(Object *_parent)
|
|
{
|
|
parent = _parent;
|
|
}
|
|
|
|
Object *SkinInfo::get_parent()
|
|
{
|
|
return parent;
|
|
}
|
|
|
|
void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node *> &root_joints,
|
|
std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid,
|
|
std::vector<COLLADAFW::Node *>& result)
|
|
{
|
|
std::vector<COLLADAFW::Node *>::const_iterator it;
|
|
// for each root_joint
|
|
for (it = root_joints.begin(); it != root_joints.end(); it++) {
|
|
COLLADAFW::Node *root = *it;
|
|
std::vector<JointData>::iterator ji;
|
|
//for each joint_data in this skin
|
|
for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
|
|
if (joint_by_uid.find((*ji).joint_uid) != joint_by_uid.end()) {
|
|
//get joint node from joint map
|
|
COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
|
|
|
|
//find if joint node is in the tree belonging to the root_joint
|
|
if (find_node_in_tree(joint, root)) {
|
|
if (std::find(result.begin(), result.end(), root) == result.end())
|
|
result.push_back(root);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool SkinInfo::find_node_in_tree(COLLADAFW::Node *node, COLLADAFW::Node *tree_root)
|
|
{
|
|
if (node == tree_root)
|
|
return true;
|
|
|
|
COLLADAFW::NodePointerArray& children = tree_root->getChildNodes();
|
|
for (unsigned int i = 0; i < children.getCount(); i++) {
|
|
if (find_node_in_tree(node, children[i]))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|