This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/collada/SkinInfo.cpp
Sergey Sharybin 79312c1912 Depsgraph: Remove duplicated sets of recalc/update flags
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
2018-12-07 11:37:38 +01:00

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;
}