|
@@ -11,15 +11,13 @@
|
|
|
|
|
|
|
|
|
template <
|
|
|
- typename DerivedV,
|
|
|
typename DerivedF,
|
|
|
- typename DerivedNV,
|
|
|
+ typename DerivedS,
|
|
|
typename DerivedNF>
|
|
|
-IGL_INLINE void igl::upsample(
|
|
|
- const Eigen::PlainObjectBase<DerivedV>& V,
|
|
|
- const Eigen::PlainObjectBase<DerivedF>& F,
|
|
|
- Eigen::PlainObjectBase<DerivedNV>& NV,
|
|
|
- Eigen::PlainObjectBase<DerivedNF>& NF)
|
|
|
+IGL_INLINE void igl::upsample(const int n_verts,
|
|
|
+ const Eigen::PlainObjectBase<DerivedF>& F,
|
|
|
+ Eigen::SparseMatrix<DerivedS>& S,
|
|
|
+ Eigen::PlainObjectBase<DerivedNF>& NF)
|
|
|
{
|
|
|
// Use "in place" wrapper instead
|
|
|
assert(&V != &NV);
|
|
@@ -27,15 +25,18 @@ IGL_INLINE void igl::upsample(
|
|
|
using namespace std;
|
|
|
using namespace Eigen;
|
|
|
|
|
|
+ typedef Eigen::Triplet<DerivedS> Triplet_t;
|
|
|
+
|
|
|
Eigen::Matrix<
|
|
|
- typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
|
|
- FF,FFi;
|
|
|
+ typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
|
|
+ FF,FFi;
|
|
|
triangle_triangle_adjacency(F,FF,FFi);
|
|
|
|
|
|
// TODO: Cache optimization missing from here, it is a mess
|
|
|
|
|
|
// Compute the number and positions of the vertices to insert (on edges)
|
|
|
Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(),FF.cols(),-1);
|
|
|
+ Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols());
|
|
|
int counter = 0;
|
|
|
|
|
|
for(int i=0;i<FF.rows();++i)
|
|
@@ -45,33 +46,45 @@ IGL_INLINE void igl::upsample(
|
|
|
if(NI(i,j) == -1)
|
|
|
{
|
|
|
NI(i,j) = counter;
|
|
|
- if (FF(i,j) != -1) // If it is not a border
|
|
|
- NI(FF(i,j),FFi(i,j)) = counter;
|
|
|
+ NIdoubles(i,j) = 0;
|
|
|
+ if (FF(i,j) != -1) {
|
|
|
+ //If it is not a boundary
|
|
|
+ NI(FF(i,j), FFi(i,j)) = counter;
|
|
|
+ NIdoubles(i,j) = 1;
|
|
|
+ }
|
|
|
++counter;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- int n_odd = V.rows();
|
|
|
- int n_even = counter;
|
|
|
+ const int& n_odd = n_verts;
|
|
|
+ const int& n_even = counter;
|
|
|
+ const int n_newverts = n_odd + n_even;
|
|
|
|
|
|
- // Preallocate NV and NF
|
|
|
- NV.resize(V.rows()+n_even,V.cols());
|
|
|
- NF.resize(F.rows()*4,3);
|
|
|
+ //Construct vertex positions
|
|
|
+ std::vector<Triplet_t> tripletList;
|
|
|
|
|
|
// Fill the odd vertices position
|
|
|
- NV.block(0,0,V.rows(),V.cols()) = V;
|
|
|
+ for (int i=0; i<n_odd; ++i)
|
|
|
+ {
|
|
|
+ tripletList.emplace_back(i, i, 1.);
|
|
|
+ }
|
|
|
|
|
|
- // Fill the even vertices position
|
|
|
for(int i=0;i<FF.rows();++i)
|
|
|
{
|
|
|
for(int j=0;j<3;++j)
|
|
|
{
|
|
|
- NV.row(NI(i,j) + n_odd) = 0.5 * V.row(F(i,j)) + 0.5 * V.row(F(i,(j+1)%3));
|
|
|
+ if(NIdoubles(i,j)==0) {
|
|
|
+ tripletList.emplace_back(NI(i,j) + n_odd, F(i,j), 1./2.);
|
|
|
+ tripletList.emplace_back(NI(i,j) + n_odd, F(i,(j+1)%3), 1./2.);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+ S.resize(n_newverts, n_verts);
|
|
|
+ S.setFromTriplets(tripletList.begin(), tripletList.end());
|
|
|
|
|
|
// Build the new topology (Every face is replaced by four)
|
|
|
+ NF.resize(F.rows()*4,3);
|
|
|
for(int i=0; i<F.rows();++i)
|
|
|
{
|
|
|
VectorXi VI(6);
|
|
@@ -88,19 +101,43 @@ IGL_INLINE void igl::upsample(
|
|
|
NF.row((i*4)+2) = f2;
|
|
|
NF.row((i*4)+3) = f3;
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
+template <
|
|
|
+ typename DerivedV,
|
|
|
+ typename DerivedF,
|
|
|
+ typename DerivedNV,
|
|
|
+ typename DerivedNF>
|
|
|
+IGL_INLINE void igl::upsample(
|
|
|
+ const Eigen::PlainObjectBase<DerivedV>& V,
|
|
|
+ const Eigen::PlainObjectBase<DerivedF>& F,
|
|
|
+ Eigen::PlainObjectBase<DerivedNV>& NV,
|
|
|
+ Eigen::PlainObjectBase<DerivedNF>& NF,
|
|
|
+ const int number_of_subdivs)
|
|
|
+{
|
|
|
+ typedef Eigen::SparseMatrix<double> SparseMat;
|
|
|
+ typedef Eigen::Triplet<double> Triplet_t;
|
|
|
+
|
|
|
+ NV = V;
|
|
|
+ NF = F;
|
|
|
+ for(int i=0; i<number_of_subdivs; ++i) {
|
|
|
+ DerivedNF tempF = NF;
|
|
|
+ SparseMat S;
|
|
|
+ upsample(NV.rows(), tempF, S, NF);
|
|
|
+ NV = S*NV;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
template <
|
|
|
typename MatV,
|
|
|
typename MatF>
|
|
|
-IGL_INLINE void igl::upsample(
|
|
|
- MatV& V,
|
|
|
- MatF& F)
|
|
|
+IGL_INLINE void igl::upsample(MatV& V,
|
|
|
+ MatF& F,
|
|
|
+ const int number_of_subdivs)
|
|
|
{
|
|
|
const MatV V_copy = V;
|
|
|
const MatF F_copy = F;
|
|
|
- return upsample(V_copy,F_copy,V,F);
|
|
|
+ return upsample(V_copy,F_copy,V,F,number_of_subdivs);
|
|
|
}
|
|
|
|
|
|
#ifdef IGL_STATIC_LIBRARY
|