1#include <Core/Animation/HandleWeightOperation.hpp>
2#include <Core/Math/LinearAlgebra.hpp>
3#include <Core/Math/Math.hpp>
5#include <Core/Utils/Log.hpp>
19WeightMatrix extractWeightMatrix(
const MeshWeight& weight,
const uint weight_size ) {
20 WeightMatrix W( weight.size(), weight_size );
22 for ( uint i = 0; i < weight.size(); ++i ) {
23 for (
const auto& w : weight[i] ) {
24 W.coeffRef( i, w.first ) = w.second;
30MeshWeight extractMeshWeight( Eigen::Ref<const WeightMatrix> matrix ) {
31 MeshWeight W( matrix.rows() );
32 for (
int i = 0; i < matrix.rows(); ++i ) {
33 for (
int j = 0; j < matrix.cols(); ++j ) {
34 if ( matrix.coeff( i, j ) != 0.0 ) {
43WeightMatrix partitionOfUnity( Eigen::Ref<const WeightMatrix> weights ) {
44 WeightMatrix W = weights;
45 normalizeWeights( W );
49uint getMaxWeightIndex( Eigen::Ref<const WeightMatrix> weights,
const uint vertexID ) {
50 uint maxId = uint( -1 );
51 VectorN row = weights.row( vertexID );
52 row.maxCoeff( &maxId );
56void getMaxWeightIndex( Eigen::Ref<const WeightMatrix> weights,
std::vector<uint>& handleID ) {
57 handleID.
resize( weights.rows() );
58 for (
int i = 0; i < weights.rows(); ++i ) {
59 handleID[i] = getMaxWeightIndex( weights, i );
63bool checkWeightMatrix( Eigen::Ref<const WeightMatrix> matrix,
64 const bool FAIL_ON_ASSERT,
67 checkNoWeightVertex( matrix, FAIL_ON_ASSERT, MT );
69 if ( !ok ) { LOG( logDEBUG ) <<
"Matrix is not good."; }
74bool checkNoWeightVertex( Eigen::Ref<const WeightMatrix> matrix,
75 const bool FAIL_ON_ASSERT,
78 LOG( logDEBUG ) <<
"Searching for empty rows in the matrix...";
80#pragma omp parallel for
81 for (
int i = 0; i < matrix.rows(); ++i ) {
82 Sparse row = matrix.row( i );
83 const int check = ( row.nonZeros() > 0 ) ? 1 : 0;
88 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false,
"At least a vertex as no weights" ); }
89 else { LOG( logDEBUG ) <<
"At least a vertex as no weights"; }
93 for (
int i = 0; i < matrix.rows(); ++i ) {
94 Sparse row = matrix.row( i );
95 if ( row.nonZeros() == 0 ) {
99 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false, text.
c_str() ); }
100 else { LOG( logDEBUG ) << text; }
107bool normalizeWeights( Eigen::Ref<WeightMatrix> matrix,
const bool MT ) {
110 bool skinningWeightOk =
true;
112#pragma omp parallel for if ( MT )
113 for (
int k = 0; k < matrix.innerSize(); ++k ) {
114 const Scalar sum = matrix.row( k ).sum();
117 skinningWeightOk =
false;
118 matrix.row( k ) /= sum;
122 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.
hepler function to manage enum as underlying types in VariableSet