Loading [MathJax]/extensions/tex2jax.js
Radium Engine  1.5.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
HandleWeightOperation.cpp
1 #include <Core/Animation/HandleWeightOperation.hpp>
2 #include <Core/Math/LinearAlgebra.hpp> // Math::checkInvalidNumbers
3 #include <Core/Utils/Log.hpp>
4 #include <utility>
5 
6 namespace Ra {
7 namespace Core {
8 namespace Animation {
9 
10 using namespace Utils; // log
11 
12 WeightMatrix extractWeightMatrix( const MeshWeight& weight, const uint weight_size ) {
13  WeightMatrix W( weight.size(), weight_size );
14  W.setZero();
15  for ( uint i = 0; i < weight.size(); ++i ) {
16  for ( const auto& w : weight[i] ) {
17  W.coeffRef( i, w.first ) = w.second;
18  }
19  }
20  return W;
21 }
22 
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 ) );
29  W[i].push_back( w );
30  }
31  }
32  }
33  return W;
34 }
35 
36 WeightMatrix partitionOfUnity( Eigen::Ref<const WeightMatrix> weights ) {
37  WeightMatrix W = weights;
38  normalizeWeights( W );
39  return W;
40 }
41 
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 );
46  return maxId;
47 }
48 
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 );
53  }
54 }
55 
56 bool checkWeightMatrix( Eigen::Ref<const WeightMatrix> matrix,
57  const bool FAIL_ON_ASSERT,
58  const bool MT ) {
59  bool ok = Math::checkInvalidNumbers( matrix, FAIL_ON_ASSERT ) &&
60  checkNoWeightVertex( matrix, FAIL_ON_ASSERT, MT );
61 
62  if ( !ok ) { LOG( logDEBUG ) << "Matrix is not good."; }
63 
64  return ok;
65 }
66 
67 bool checkNoWeightVertex( Eigen::Ref<const WeightMatrix> matrix,
68  const bool FAIL_ON_ASSERT,
69  const bool MT ) {
70  int status = 1;
71  LOG( logDEBUG ) << "Searching for empty rows in the matrix...";
72  if ( MT ) {
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;
77 #pragma omp atomic
78  status &= check;
79  }
80  if ( status == 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"; }
83  }
84  }
85  else {
86  for ( int i = 0; i < matrix.rows(); ++i ) {
87  Sparse row = matrix.row( i );
88  if ( row.nonZeros() == 0 ) {
89  status = 0;
90 
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; }
94  }
95  }
96  }
97  return status != 0;
98 }
99 
100 bool normalizeWeights( Eigen::Ref<WeightMatrix> matrix, const bool MT ) {
101  CORE_UNUSED( MT );
102 
103  bool skinningWeightOk = true;
104 
105 #pragma omp parallel for if ( MT )
106  for ( int k = 0; k < matrix.innerSize(); ++k ) {
107  const Scalar sum = matrix.row( k ).sum();
108  if ( !Ra::Core::Math::areApproxEqual( sum, 0_ra ) ) {
109  if ( !Ra::Core::Math::areApproxEqual( sum, 1_ra ) ) {
110  skinningWeightOk = false;
111  matrix.row( k ) /= sum;
112  }
113  }
114  }
115  return !skinningWeightOk;
116 }
117 
118 } // namespace Animation
119 } // Namespace Core
120 } // Namespace Ra
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.
Definition: Math.hpp:42
bool checkInvalidNumbers(Eigen::Ref< Eigen::Quaternion< S >> q, const bool FAIL_ON_ASSERT=false)
Call std::isfinite on quaternion entries.
Definition: Cage.cpp:3