message: Changed NNLS blendshapes fitting to use SparseMatrix
  P * V_hat_h was a small performance bottleneck - using SparseMatrix is faster by quite a bit (10+%) with both the BFM2017 as well as the SFM3448.
diff: @@ -146,11 +146,19 @@ inline std::vector<float> fit_blendshapes_to_landmarks_nnls(const std::vector<mo
  V_hat_h.block(row_index, 0, 3, V_hat_h.cols()) = blendshapes_as_basis.block(vertex_ids[i] * 3, 0, 3, blendshapes_as_basis.cols());
  row_index += 4; // replace 3 rows and skip the 4th one, it has all zeros
  }
  +
  // Form a block diagonal matrix $P \in R^{3N\times 4N}$ in which the camera matrix C (P_Affine, affine_camera_matrix) is placed on the diagonal:
  - MatrixXf P = MatrixXf::Zero(3 * num_landmarks, 4 * num_landmarks);
  - for (int i = 0; i < num_landmarks; ++i) {
  - P.block<3, 4>(3 * i, 4 * i) = affine_camera_matrix;
  + Eigen::SparseMatrix<float> P(3 * num_landmarks, 4 * num_landmarks);
  + std::vector<Eigen::Triplet<float>> P_coefficients; // list of non-zeros coefficients
  + for (int i = 0; i < num_landmarks; ++i) { // Note: could make this the inner-most loop.
  + for (int x = 0; x < affine_camera_matrix.rows(); ++x) {
  + for (int y = 0; y < affine_camera_matrix.cols(); ++y) {
  + P_coefficients.push_back(Eigen::Triplet<float>(3 * i + x, 4 * i + y, affine_camera_matrix(x, y)));
  }
  + }
  + }
  + P.setFromTriplets(P_coefficients.begin(), P_coefficients.end());
  +
  // The landmarks in matrix notation (in homogeneous coordinates), $3N\times 1$
  VectorXf y = VectorXf::Ones(3 * num_landmarks);
  for (int i = 0; i < num_landmarks; ++i) {
  @@ -158,6 +166,7 @@ inline std::vector<float> fit_blendshapes_to_landmarks_nnls(const std::vector<mo
  y((3 * i) + 1) = landmarks[i][1];
  //y_((3 * i) + 2) = 1; // already 1, stays (homogeneous coordinate)
  }
  +
  // The mean, with an added homogeneous coordinate (x_1, y_1, z_1, 1, x_2, ...)^t
  VectorXf v_bar = VectorXf::Ones(4 * num_landmarks);
  for (int i = 0; i < num_landmarks; ++i) {
  