1 #include <Core/Animation/HandleWeightOperation.hpp>
2 #include <Core/Math/LinearAlgebra.hpp>
3 #include <Core/Utils/Log.hpp>
10 using namespace Utils;
12 WeightMatrix extractWeightMatrix(
const MeshWeight& weight,
const uint weight_size ) {
13 WeightMatrix W( weight.size(), weight_size );
15 for ( uint i = 0; i < weight.size(); ++i ) {
16 for (
const auto& w : weight[i] ) {
17 W.coeffRef( i, w.first ) = w.second;
23 MeshWeight extractMeshWeight( Eigen::Ref<const WeightMatrix> matrix ) {
24 MeshWeight W( matrix.rows() );
25 for (
int i = 0; i < matrix.rows(); ++i ) {
26 for (
int j = 0; j < matrix.cols(); ++j ) {
27 if ( matrix.coeff( i, j ) != 0.0 ) {
28 std::pair<uint, Scalar> w( uint( j ), matrix.coeff( i, j ) );
36 WeightMatrix partitionOfUnity( Eigen::Ref<const WeightMatrix> weights ) {
37 WeightMatrix W = weights;
38 normalizeWeights( W );
42 uint getMaxWeightIndex( Eigen::Ref<const WeightMatrix> weights,
const uint vertexID ) {
43 uint maxId = uint( -1 );
44 VectorN row = weights.row( vertexID );
45 row.maxCoeff( &maxId );
49 void getMaxWeightIndex( Eigen::Ref<const WeightMatrix> weights, std::vector<uint>& handleID ) {
50 handleID.resize( weights.rows() );
51 for (
int i = 0; i < weights.rows(); ++i ) {
52 handleID[i] = getMaxWeightIndex( weights, i );
56 bool checkWeightMatrix( Eigen::Ref<const WeightMatrix> matrix,
57 const bool FAIL_ON_ASSERT,
60 checkNoWeightVertex( matrix, FAIL_ON_ASSERT, MT );
62 if ( !ok ) { LOG( logDEBUG ) <<
"Matrix is not good."; }
67 bool checkNoWeightVertex( Eigen::Ref<const WeightMatrix> matrix,
68 const bool FAIL_ON_ASSERT,
71 LOG( logDEBUG ) <<
"Searching for empty rows in the matrix...";
73 #pragma omp parallel for
74 for (
int i = 0; i < matrix.rows(); ++i ) {
75 Sparse row = matrix.row( i );
76 const int check = ( row.nonZeros() > 0 ) ? 1 : 0;
81 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false,
"At least a vertex as no weights" ); }
82 else { LOG( logDEBUG ) <<
"At least a vertex as no weights"; }
86 for (
int i = 0; i < matrix.rows(); ++i ) {
87 Sparse row = matrix.row( i );
88 if ( row.nonZeros() == 0 ) {
91 const std::string text =
"Vertex " + std::to_string( i ) +
" has no weights.";
92 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false, text.c_str() ); }
93 else { LOG( logDEBUG ) << text; }
100 bool normalizeWeights( Eigen::Ref<WeightMatrix> matrix,
const bool MT ) {
103 bool skinningWeightOk =
true;
105 #pragma omp parallel for if ( MT )
106 for (
int k = 0; k < matrix.innerSize(); ++k ) {
107 const Scalar sum = matrix.row( k ).sum();
110 skinningWeightOk =
false;
111 matrix.row( k ) /= sum;
115 return !skinningWeightOk;
std::enable_if<!std::numeric_limits< T >::is_integer, bool >::type areApproxEqual(T x, T y, T espilonBoostFactor=T(10))
Compare two numbers such that |x-y| < espilon*epsilonBoostFactor.
bool checkInvalidNumbers(Eigen::Ref< Eigen::Quaternion< S >> q, const bool FAIL_ON_ASSERT=false)
Call std::isfinite on quaternion entries.