Эх сурвалжийг харах

move bbw with active set to main lib, rm bbw extra, create mosek::bbw

Former-commit-id: 723d5cd6ebe241c6765e29a677dd38992e699f3f
Alec Jacobson 8 жил өмнө
parent
commit
c76993c791

+ 141 - 0
include/igl/bbw.cpp

@@ -0,0 +1,141 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "bbw.h"
+#include "min_quad_with_fixed.h"
+#include "harmonic.h"
+#include <Eigen/Sparse>
+#include <iostream>
+#include <cstdio>
+
+igl::BBWData::BBWData():
+  partition_unity(false),
+  W0(),
+  active_set_params(),
+  verbosity(0)
+{
+  // We know that the Bilaplacian is positive semi-definite
+  active_set_params.Auu_pd = true;
+}
+
+void igl::BBWData::print()
+{
+  using namespace std;
+  cout<<"partition_unity: "<<partition_unity<<endl;
+  cout<<"W0=["<<endl<<W0<<endl<<"];"<<endl;
+}
+
+
+template <
+  typename DerivedV,
+  typename DerivedEle,
+  typename Derivedb,
+  typename Derivedbc,
+  typename DerivedW>
+IGL_INLINE bool igl::bbw(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedEle> & Ele,
+  const Eigen::PlainObjectBase<Derivedb> & b,
+  const Eigen::PlainObjectBase<Derivedbc> & bc,
+  igl::BBWData & data,
+  Eigen::PlainObjectBase<DerivedW> & W
+  )
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(!data.partition_unity && "partition_unity not implemented yet");
+  // number of domain vertices
+  int n = V.rows();
+  // number of handles
+  int m = bc.cols();
+  // Build biharmonic operator
+  Eigen::SparseMatrix<typename DerivedV::Scalar> Q;
+  harmonic(V,Ele,2,Q);
+  W.derived().resize(n,m);
+  // No linear terms
+  VectorXd c = VectorXd::Zero(n);
+  // No linear constraints
+  SparseMatrix<typename DerivedW::Scalar> A(0,n),Aeq(0,n),Aieq(0,n);
+  VectorXd Beq(0,1),Bieq(0,1);
+  // Upper and lower box constraints (Constant bounds)
+  VectorXd ux = VectorXd::Ones(n);
+  VectorXd lx = VectorXd::Zero(n);
+  active_set_params eff_params = data.active_set_params;
+  if(data.verbosity >= 1)
+  {
+    cout<<"BBW: max_iter: "<<data.active_set_params.max_iter<<endl;
+    cout<<"BBW: eff_max_iter: "<<eff_params.max_iter<<endl;
+  }
+  if(data.verbosity >= 1)
+  {
+    cout<<"BBW: Computing initial weights for "<<m<<" handle"<<
+      (m!=1?"s":"")<<"."<<endl;
+  }
+  min_quad_with_fixed_data<typename DerivedW::Scalar > mqwf;
+  min_quad_with_fixed_precompute(Q,b,Aeq,true,mqwf);
+  min_quad_with_fixed_solve(mqwf,c,bc,Beq,W);
+  // decrement
+  eff_params.max_iter--;
+  bool error = false;
+  // Loop over handles
+  std::mutex critical;
+  const auto & optimize_weight = [&](const int i)
+  {
+    // Quicker exit for paralle_for
+    if(error)
+    {
+      return;
+    }
+    if(data.verbosity >= 1)
+    {
+      std::lock_guard<std::mutex> lock(critical);
+      cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<<
+        "."<<endl;
+    }
+    VectorXd bci = bc.col(i);
+    VectorXd Wi;
+    // use initial guess
+    Wi = W.col(i);
+    SolverStatus ret = active_set(
+        Q,c,b,bci,Aeq,Beq,Aieq,Bieq,lx,ux,eff_params,Wi);
+    switch(ret)
+    {
+      case SOLVER_STATUS_CONVERGED:
+        break;
+      case SOLVER_STATUS_MAX_ITER:
+        cerr<<"active_set: max iter without convergence."<<endl;
+        break;
+      case SOLVER_STATUS_ERROR:
+      default:
+        cerr<<"active_set error."<<endl;
+        error = true;
+    }
+    W.col(i) = Wi;
+  };
+  parallel_for(m,optimize_weight,2);
+  if(error)
+  {
+    return false;
+  }
+
+#ifndef NDEBUG
+  const double min_rowsum = W.rowwise().sum().array().abs().minCoeff();
+  if(min_rowsum < 0.1)
+  {
+    cerr<<"bbw.cpp: Warning, minimum row sum is very low. Consider more "
+      "active set iterations or enforcing partition of unity."<<endl;
+  }
+#endif
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template bool igl::bbw<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::BBWData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+#endif
+

+ 77 - 0
include/igl/bbw.h

@@ -0,0 +1,77 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_BBW_H
+#define IGL_BBW_H
+#include "igl_inline.h"
+
+#include <Eigen/Dense>
+#include <igl/active_set.h>
+
+namespace igl
+{
+  // Container for BBW computation related data and flags
+  class BBWData
+  {
+    public:
+      // Enforce partition of unity during optimization (optimize all weight
+      // simultaneously)
+      bool partition_unity;
+      // Initial guess
+      Eigen::MatrixXd W0;
+      igl::active_set_params active_set_params;
+      // Verbosity level
+      // 0: quiet
+      // 1: loud
+      // 2: louder
+      int verbosity;
+    public:
+      IGL_INLINE BBWData();
+      // Print current state of object
+      IGL_INLINE void print();
+  };
+
+  // Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
+  // set of boundary conditions
+  //
+  // Templates
+  //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
+  //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
+  //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
+  //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
+  //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
+  // Inputs:
+  //   V  #V by dim vertex positions
+  //   Ele  #Elements by simplex-size list of element indices
+  //   b  #b boundary indices into V
+  //   bc #b by #W list of boundary values
+  //   data  object containing options, intial guess --> solution and results
+  // Outputs:
+  //   W  #V by #W list of *unnormalized* weights to normalize use
+  //    igl::normalize_row_sums(W,W);
+  // Returns true on success, false on failure
+  template <
+    typename DerivedV,
+    typename DerivedEle,
+    typename Derivedb,
+    typename Derivedbc,
+    typename DerivedW>
+  IGL_INLINE bool bbw(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedEle> & Ele,
+    const Eigen::PlainObjectBase<Derivedb> & b,
+    const Eigen::PlainObjectBase<Derivedbc> & bc,
+    BBWData & data,
+    Eigen::PlainObjectBase<DerivedW> & W);
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "bbw.cpp"
+#endif
+
+#endif
+

+ 40 - 17
include/igl/harmonic.cpp

@@ -35,16 +35,7 @@ IGL_INLINE bool igl::harmonic(
   typedef typename DerivedV::Scalar Scalar;
   SparseMatrix<Scalar> L,M;
   cotmatrix(V,F,L);
-  switch(F.cols())
-  {
-    case 3:
-      massmatrix(V,F,MASSMATRIX_TYPE_VORONOI,M);
-      break;
-    case 4:
-    default:
-      massmatrix(V,F,MASSMATRIX_TYPE_BARYCENTRIC,M);
-    break;
-  }
+  massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
   return harmonic(L,M,b,bc,k,W);
 }
 
@@ -96,14 +87,9 @@ IGL_INLINE bool igl::harmonic(
   assert(n == M.rows() && "M must be square");
   assert(igl::isdiag(M) && "Mass matrix should be diagonal");
 
-  Eigen::SparseMatrix<DerivedM> Mi;
-  invert_diag(M,Mi);
   Eigen::SparseMatrix<DerivedL> Q;
-  Q = -L;
-  for(int p = 1;p<k;p++)
-  {
-    Q = (Q*Mi*-L).eval();
-  }
+  igl::harmonic(L,M,k,Q);
+
   typedef DerivedL Scalar;
   min_quad_with_fixed_data<Scalar> data;
   min_quad_with_fixed_precompute(Q,b,Eigen::SparseMatrix<Scalar>(),true,data);
@@ -123,6 +109,43 @@ IGL_INLINE bool igl::harmonic(
   return true;
 }
 
+template <
+  typename DerivedL,
+  typename DerivedM,
+  typename DerivedQ>
+IGL_INLINE void igl::harmonic(
+  const Eigen::SparseMatrix<DerivedL> & L,
+  const Eigen::SparseMatrix<DerivedM> & M,
+  const int k,
+  Eigen::SparseMatrix<DerivedQ> & Q)
+{
+  assert(L.rows() == L.cols()&&"L should be square");
+  assert(M.rows() == M.cols()&&"M should be square");
+  assert(L.rows() == M.rows()&&"L should match M's dimensions");
+  Eigen::SparseMatrix<DerivedM> Mi;
+  invert_diag(M,Mi);
+  Q = -L;
+  for(int p = 1;p<k;p++)
+  {
+    Q = (Q*Mi*-L).eval();
+  }
+}
+
+template <
+  typename DerivedV,
+  typename DerivedF,
+  typename DerivedQ>
+IGL_INLINE void igl::harmonic(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedF> & F,
+  const int k,
+  Eigen::SparseMatrix<DerivedQ> & Q)
+{
+  Eigen::SparseMatrix<DerivedQ> L,M;
+  cotmatrix(V,F,L);
+  massmatrix(V,F,MASSMATRIX_TYPE_DEFAULT,M);
+  return harmonic(L,M,k,Q);
+}
 
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization

+ 33 - 0
include/igl/harmonic.h

@@ -81,6 +81,39 @@ namespace igl
     const Eigen::PlainObjectBase<Derivedbc> & bc,
     const int k,
     Eigen::PlainObjectBase<DerivedW> & W);
+  // Build the discrete k-harmonic operator (computing integrated quantities).
+  // That is, if the k-harmonic PDE is Q x = 0, then this minimizes x' Q x
+  //
+  // Inputs:
+  //   L  #V by #V discrete (integrated) Laplacian  
+  //   M  #V by #V mass matrix
+  //   k  power of harmonic operation (1: harmonic, 2: biharmonic, etc)
+  // Outputs:
+  //   Q  #V by #V discrete (integrated) k-Laplacian  
+  template <
+    typename DerivedL,
+    typename DerivedM,
+    typename DerivedQ>
+  IGL_INLINE void harmonic(
+    const Eigen::SparseMatrix<DerivedL> & L,
+    const Eigen::SparseMatrix<DerivedM> & M,
+    const int k,
+    Eigen::SparseMatrix<DerivedQ> & Q);
+  // Inputs:
+  //   V  #V by dim vertex positions
+  //   F  #F by simplex-size list of element indices
+  //   k  power of harmonic operation (1: harmonic, 2: biharmonic, etc)
+  // Outputs:
+  //   Q  #V by #V discrete (integrated) k-Laplacian  
+  template <
+    typename DerivedV,
+    typename DerivedF,
+    typename DerivedQ>
+  IGL_INLINE void harmonic(
+    const Eigen::PlainObjectBase<DerivedV> & V,
+    const Eigen::PlainObjectBase<DerivedF> & F,
+    const int k,
+    Eigen::SparseMatrix<DerivedQ> & Q);
 };
 
 #ifndef IGL_STATIC_LIBRARY

+ 88 - 0
include/igl/mosek/bbw.cpp

@@ -0,0 +1,88 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2016 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#include "bbw.h"
+#include "mosek_quadprog.h"
+#include "../harmonic.h"
+#include "../slice_into.h"
+#include <Eigen/Sparse>
+#include <iostream>
+#include <cstdio>
+
+
+template <
+  typename DerivedV,
+  typename DerivedEle,
+  typename Derivedb,
+  typename Derivedbc,
+  typename DerivedW>
+IGL_INLINE bool igl::mosek::bbw(
+  const Eigen::PlainObjectBase<DerivedV> & V,
+  const Eigen::PlainObjectBase<DerivedEle> & Ele,
+  const Eigen::PlainObjectBase<Derivedb> & b,
+  const Eigen::PlainObjectBase<Derivedbc> & bc,
+  igl::BBWData & data,
+  igl::mosek::MosekData & mosek_data,
+  Eigen::PlainObjectBase<DerivedW> & W
+  )
+{
+  using namespace std;
+  using namespace Eigen;
+  assert(!data.partition_unity && "partition_unity not implemented yet");
+  // number of domain vertices
+  int n = V.rows();
+  // number of handles
+  int m = bc.cols();
+  // Build biharmonic operator
+  Eigen::SparseMatrix<typename DerivedV::Scalar> Q;
+  harmonic(V,Ele,2,Q);
+  W.derived().resize(n,m);
+  // No linear terms
+  VectorXd c = VectorXd::Zero(n);
+  // No linear constraints
+  SparseMatrix<typename DerivedW::Scalar> A(0,n);
+  VectorXd uc(0,1),lc(0,1);
+  // Upper and lower box constraints (Constant bounds)
+  VectorXd ux = VectorXd::Ones(n);
+  VectorXd lx = VectorXd::Zero(n);
+  // Loop over handles
+  for(int i = 0;i<m;i++)
+  {
+    if(data.verbosity >= 1)
+    {
+      cout<<"BBW: Computing weight for handle "<<i+1<<" out of "<<m<<
+        "."<<endl;
+    }
+    VectorXd bci = bc.col(i);
+    VectorXd Wi;
+    // impose boundary conditions via bounds
+    slice_into(bci,b,ux);
+    slice_into(bci,b,lx);
+    bool r = mosek_quadprog(Q,c,0,A,lc,uc,lx,ux,mosek_data,Wi);
+    if(!r)
+    {
+      return false;
+    }
+    W.col(i) = Wi;
+  }
+#ifndef NDEBUG
+    const double min_rowsum = W.rowwise().sum().array().abs().minCoeff();
+    if(min_rowsum < 0.1)
+    {
+      cerr<<"bbw.cpp: Warning, minimum row sum is very low. Consider more "
+        "active set iterations or enforcing partition of unity."<<endl;
+    }
+#endif
+
+  return true;
+}
+
+#ifdef IGL_STATIC_LIBRARY
+// Explicit template specialization
+template bool igl::mosek::bbw<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::BBWData&, igl::mosek::MosekData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
+#endif
+

+ 60 - 0
include/igl/mosek/bbw.h

@@ -0,0 +1,60 @@
+// This file is part of libigl, a simple c++ geometry processing library.
+//
+// Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License
+// v. 2.0. If a copy of the MPL was not distributed with this file, You can
+// obtain one at http://mozilla.org/MPL/2.0/.
+#ifndef IGL_MOSEK_BBW_H
+#define IGL_MOSEK_BBW_H
+#include "../igl_inline.h"
+#include "mosek_quadprog.h"
+#include "../bbw.h"
+#include <Eigen/Dense>
+
+namespace igl
+{
+  namespace mosek
+  {
+    // Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given
+    // set of boundary conditions
+    //
+    // Templates
+    //   DerivedV  derived type of eigen matrix for V (e.g. MatrixXd)
+    //   DerivedF  derived type of eigen matrix for F (e.g. MatrixXi)
+    //   Derivedb  derived type of eigen matrix for b (e.g. VectorXi)
+    //   Derivedbc  derived type of eigen matrix for bc (e.g. MatrixXd)
+    //   DerivedW  derived type of eigen matrix for W (e.g. MatrixXd)
+    // Inputs:
+    //   V  #V by dim vertex positions
+    //   Ele  #Elements by simplex-size list of element indices
+    //   b  #b boundary indices into V
+    //   bc #b by #W list of boundary values
+    //   data  object containing options, intial guess --> solution and results
+    //   mosek_data  object containing mosek options
+    // Outputs:
+    //   W  #V by #W list of *unnormalized* weights to normalize use
+    //    igl::normalize_row_sums(W,W);
+    // Returns true on success, false on failure
+    template <
+      typename DerivedV,
+      typename DerivedEle,
+      typename Derivedb,
+      typename Derivedbc,
+      typename DerivedW>
+    IGL_INLINE bool bbw(
+      const Eigen::PlainObjectBase<DerivedV> & V,
+      const Eigen::PlainObjectBase<DerivedEle> & Ele,
+      const Eigen::PlainObjectBase<Derivedb> & b,
+      const Eigen::PlainObjectBase<Derivedbc> & bc,
+      igl::BBWData & data,
+      igl::mosek::MosekData & mosek_data,
+      Eigen::PlainObjectBase<DerivedW> & W);
+  }
+}
+
+#ifndef IGL_STATIC_LIBRARY
+#  include "bbw.cpp"
+#endif
+
+#endif

+ 0 - 1
optional/CMakeLists.txt

@@ -22,7 +22,6 @@ option(LIBIGL_USE_STATIC_LIBRARY "Use LibIGL as static library" ON)
 
 
 option(LIBIGL_WITH_ANTTWEAKBAR      "Use AntTweakBar"    ON)
-option(LIBIGL_WITH_BBW              "Use BBW"            ON)
 find_package(CGAL QUIET)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           "${CGAL_FOUND}")
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         ON)

+ 0 - 16
shared/cmake/CMakeLists.txt

@@ -4,7 +4,6 @@ project(libigl)
 ### Available options ###
 option(LIBIGL_USE_STATIC_LIBRARY    "Use libigl as static library" OFF)
 option(LIBIGL_WITH_ANTTWEAKBAR      "Use AntTweakBar"    OFF)
-option(LIBIGL_WITH_BBW              "Use BBW"            OFF)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           OFF)
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         OFF)
 option(LIBIGL_WITH_CORK             "Use Cork"           OFF)
@@ -154,20 +153,6 @@ if(LIBIGL_WITH_ANTTWEAKBAR)
   endif()
 endif()
 
-### Compile the BBW part ###
-if(LIBIGL_WITH_BBW)
-  if(LIBIGL_USE_STATIC_LIBRARY)
-    CompileIGL_Module("bbw")
-    if(LIBIGL_WITH_MOSEK)
-      find_package(MOSEK REQUIRED)
-      list(APPEND LIBIGL_INCLUDE_DIRS ${MOSEK_INCLUDE_DIR})
-      target_include_directories(iglbbw PRIVATE ${MOSEK_INCLUDE_DIR})
-    else()
-      target_compile_definitions(iglbbw PRIVATE -DIGL_NO_MOSEK)
-    endif()
-  endif()
-endif()
-
 ### Compile the cgal parts ###
 if(LIBIGL_WITH_CGAL) # to be cleaned
   find_package(CGAL REQUIRED)
@@ -472,7 +457,6 @@ if(NOT ${CMAKE_PROJECT_NAME} STREQUAL ${PROJECT_NAME})
   set(LIBIGL_INCLUDE_DIRS ${LIBIGL_INCLUDE_DIRS} PARENT_SCOPE)
   set(LIBIGL_LIBRARIES ${LIBIGL_LIBRARIES} PARENT_SCOPE)
   set(LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES ${LIBIGL_ANTTWEAKBAR_EXTRA_LIBRARIES} PARENT_SCOPE)
-  #set(LIBIGL_BBW_EXTRA_LIBRARIES         ${LIBIGL_BBW_EXTRA_LIBRARIES}         PARENT_SCOPE)
   set(LIBIGL_CGAL_EXTRA_LIBRARIES        ${LIBIGL_CGAL_EXTRA_LIBRARIES}        PARENT_SCOPE)
   set(LIBIGL_COMISO_EXTRA_LIBRARIES      ${LIBIGL_COMISO_EXTRA_LIBRARIES}      PARENT_SCOPE)
   set(LIBIGL_CORK_EXTRA_LIBRARIES        ${LIBIGL_CORK_EXTRA_LIBRARIES}        PARENT_SCOPE)

+ 3 - 3
tutorial/403_BoundedBiharmonicWeights/main.cpp

@@ -21,7 +21,7 @@
 #include <igl/readMESH.h>
 #include <igl/readTGF.h>
 #include <igl/viewer/Viewer.h>
-#include <igl/bbw/bbw.h>
+#include <igl/bbw.h>
 //#include <igl/embree/bone_heat.h>
 
 #include <Eigen/Geometry>
@@ -139,11 +139,11 @@ int main(int argc, char *argv[])
   igl::boundary_conditions(V,T,C,VectorXi(),BE,MatrixXi(),b,bc);
 
   // compute BBW weights matrix
-  igl::bbw::BBWData bbw_data;
+  igl::BBWData bbw_data;
   // only a few iterations for sake of demo
   bbw_data.active_set_params.max_iter = 8;
   bbw_data.verbosity = 2;
-  if(!igl::bbw::bbw(V,T,b,bc,bbw_data,W))
+  if(!igl::bbw(V,T,b,bc,bbw_data,W))
   {
     return false;
   }

+ 1 - 4
tutorial/CMakeLists.txt

@@ -7,7 +7,6 @@ option(LIBIGL_WITH_VIEWER      "Use OpenGL viewer"  ON)
 option(LIBIGL_WITH_NANOGUI     "Use Nanogui menu"   OFF)
 
 ### libIGL options: choose your dependencies (by default everything is OFF, in this example we need the viewer) ###
-option(LIBIGL_WITH_BBW              "Use BBW"            ON)
 find_package(CGAL QUIET)
 option(LIBIGL_WITH_CGAL             "Use CGAL"           "${CGAL_FOUND}")
 option(LIBIGL_WITH_COMISO           "Use CoMiso"         ON)
@@ -114,9 +113,7 @@ endif()
 if(TUTORIALS_CHAPTER4)
   add_subdirectory("401_BiharmonicDeformation")
   add_subdirectory("402_PolyharmonicDeformation")
-  if(LIBIGL_WITH_BBW)
-    add_subdirectory("403_BoundedBiharmonicWeights")
-  endif()
+  add_subdirectory("403_BoundedBiharmonicWeights")
   add_subdirectory("404_DualQuaternionSkinning")
   add_subdirectory("405_AsRigidAsPossible")
   add_subdirectory("406_FastAutomaticSkinningTransformations")