|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tcg includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tcg/tcg_misc.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// tlin includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tlin/tlin.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// STD includes
|
|
Toshihiro Shimizu |
890ddd |
#include <assert.h></assert.h>
|
|
Toshihiro Shimizu |
890ddd |
#include <memory></memory>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "ext/plasticdeformer.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
107701 |
#include <cstring></cstring>
|
|
Campbell Barton |
107701 |
|
|
Toshihiro Shimizu |
890ddd |
/*! \file plasticdeformer.cpp
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
This file contains the implementation of a Mesh Deformer as specified in the
|
|
Toshihiro Shimizu |
890ddd |
Igarashi-Moscovich-Hughes paper "As-Rigid-As-Possible Shape Manipulation",
|
|
Toshihiro Shimizu |
890ddd |
with some slight modifications.
|
|
Toshihiro Shimizu |
890ddd |
\n\n
|
|
Toshihiro Shimizu |
890ddd |
Notably, the choice of handle points is not limited to mesh vertices, but free
|
|
Toshihiro Shimizu |
890ddd |
along the mesh surface. This can be achieved by constraining the classical
|
|
Toshihiro Shimizu |
890ddd |
least-squares minimization problems on a linear hyperplane, in the form:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\f$
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\left{ \begin{array}{c}
|
|
Toshihiro Shimizu |
890ddd |
v^t H v + v^t f + c \rightarrow \mbox{min} \\
|
|
Toshihiro Shimizu |
890ddd |
A v + d = 0
|
|
Toshihiro Shimizu |
890ddd |
\end{array} \right.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\f$
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
which can be solved using the Lagrange Multipliers theorem:
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\f$
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\Rightarrow \left{ \begin{array}{c}
|
|
Toshihiro Shimizu |
890ddd |
H v + f = A^t \lambda
|
|
Toshihiro Shimizu |
890ddd |
A v + d = 0
|
|
Toshihiro Shimizu |
890ddd |
\end{array} \right.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\Rightarrow \left( \begin{array}{c} H \\ A \end{array} \begin{array}{c} -A^t \\ 0 \end{array} \right)
|
|
Toshihiro Shimizu |
890ddd |
\left( \begin{array}{c} v \\ \lambda \end{array} \right) =
|
|
Toshihiro Shimizu |
890ddd |
\left( \begin{array}{c} -f \\ -d \end{array} \right)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
\f$
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//#define GL_DEBUG // Debug using OpenGL. Must deform while drawing.
|
|
Toshihiro Shimizu |
890ddd |
#ifdef GL_DEBUG // NOTE: You should force deformations,
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h" // see plasticdeformersstorage.cpp
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local structures
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//! A linear constraint of the kind k[0] * v0 + k[1] * v1 + k[2] * v2 = b; (b is not included though)
|
|
Toshihiro Shimizu |
890ddd |
struct LinearConstraint {
|
|
Toshihiro Shimizu |
890ddd |
int m_h; //!< Original handle index corresponding to this constraint
|
|
Toshihiro Shimizu |
890ddd |
int m_v[3]; //!< The mesh vertex indices v0, v1, v2
|
|
Toshihiro Shimizu |
890ddd |
double m_k[3]; //!< Constraint coefficients
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Forced to implement a sloppy substitute to C++11's std::unique_ptr -- since we're still compiling
|
|
Toshihiro Shimizu |
890ddd |
// C++03 on MAC... ARGH !
|
|
Toshihiro Shimizu |
890ddd |
template <typename d="" t,="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
class UniquePtr
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
T *m_t;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
UniquePtr() : m_t() {}
|
|
Toshihiro Shimizu |
890ddd |
UniquePtr(T *t) : m_t(t) {}
|
|
Toshihiro Shimizu |
890ddd |
~UniquePtr() { D::destroy(m_t); }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void reset(T *t = 0)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
D::destroy(m_t);
|
|
Toshihiro Shimizu |
890ddd |
m_t = t;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const T *get() const { return m_t; }
|
|
Toshihiro Shimizu |
890ddd |
T *get() { return m_t; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const T *operator->() const { return m_t; }
|
|
Toshihiro Shimizu |
890ddd |
T *operator->() { return m_t; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const T &operator*() const { return *m_t; }
|
|
Toshihiro Shimizu |
890ddd |
T &operator*() { return *m_t; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const T &operator[](size_t i) const { return m_t[i]; }
|
|
Toshihiro Shimizu |
890ddd |
T &operator[](size_t i) { return m_t[i]; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct SuperFactors_free {
|
|
Toshihiro Shimizu |
890ddd |
static inline void destroy(tlin::SuperFactors *f) { tlin::freeF(f); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
struct freer {
|
|
Toshihiro Shimizu |
890ddd |
static inline void destroy(void *d) { free(d); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
struct deleter {
|
|
Toshihiro Shimizu |
890ddd |
static inline void destroy(void *d) { delete d; }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
typedef UniquePtr<tlin::superfactors, superfactors_free=""> SuperFactorsPtr;</tlin::superfactors,>
|
|
Toshihiro Shimizu |
890ddd |
typedef UniquePtr<double, freer=""> DoublePtr;</double,>
|
|
Toshihiro Shimizu |
890ddd |
typedef UniquePtr<tpointd, deleter=""> TPointDPtr;</tpointd,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local functions
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void vertices(const TTextureMesh &mesh, int faceIdx,
|
|
Toshihiro Shimizu |
890ddd |
const TPointD *&p0, const TPointD *&p1, const TPointD *&p2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int v0, v1, v2;
|
|
Toshihiro Shimizu |
890ddd |
mesh.faceVertices(faceIdx, v0, v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
p0 = &mesh.vertex(v0).P(), p1 = &mesh.vertex(v1).P(), p2 = &mesh.vertex(v2).P();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void buildTriangularCoordinates(const TTextureMesh &mesh, int &faceIdx, const TPointD &p,
|
|
Toshihiro Shimizu |
890ddd |
double &c0, double &c1, double &c2)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
TPointD coords;
|
|
Toshihiro Shimizu |
890ddd |
const TPointD *p0, *p1, *p2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Follow the hint first
|
|
Toshihiro Shimizu |
890ddd |
if (faceIdx >= 0 && faceIdx < mesh.facesCount() &&
|
|
Toshihiro Shimizu |
890ddd |
mesh.faceContains(faceIdx, p)) {
|
|
Toshihiro Shimizu |
890ddd |
vertices(mesh, faceIdx, p0, p1, p2);
|
|
Toshihiro Shimizu |
890ddd |
coords = tcg::point_ops::triCoords(p, *p0, *p1, *p2);
|
|
Toshihiro Shimizu |
890ddd |
c1 = coords.x, c2 = coords.y, c0 = 1.0 - c1 - c2;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Find out the face searching on the mesh
|
|
Toshihiro Shimizu |
890ddd |
faceIdx = mesh.faceContaining(p);
|
|
Toshihiro Shimizu |
890ddd |
if (faceIdx >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
vertices(mesh, faceIdx, p0, p1, p2);
|
|
Toshihiro Shimizu |
890ddd |
coords = tcg::point_ops::triCoords(p, *p0, *p1, *p2);
|
|
Toshihiro Shimizu |
890ddd |
c1 = coords.x, c2 = coords.y, c0 = 1.0 - c1 - c2;
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void addConstraint1d(int j, const LinearConstraint &cnstr, tlin::spmat &mat)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i, var, nVars = 3;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < nVars; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
var = cnstr.m_v[i];
|
|
Toshihiro Shimizu |
890ddd |
mat.at(j, var) += cnstr.m_k[i];
|
|
Toshihiro Shimizu |
890ddd |
mat.at(var, j) = mat(j, var);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void addConstraint2d(int j, const LinearConstraint &cnstr, tlin::spmat &mat)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int i, varX, varY, k = j + 1, nVars = 3;
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0; i < nVars; ++i) {
|
|
Toshihiro Shimizu |
890ddd |
varX = 2 * cnstr.m_v[i], varY = varX + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
mat.at(j, varX) += cnstr.m_k[i];
|
|
Toshihiro Shimizu |
890ddd |
mat.at(k, varY) += cnstr.m_k[i];
|
|
Toshihiro Shimizu |
890ddd |
mat.at(varX, j) = mat(j, varX);
|
|
Toshihiro Shimizu |
890ddd |
mat.at(varY, k) = mat(k, varY);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void addGValues(
|
|
Toshihiro Shimizu |
890ddd |
int v0x, int v0y, int v1x, int v1y, int v2x, int v2y,
|
|
Toshihiro Shimizu |
890ddd |
double px, double py, double w, tlin::spmat &G)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double sqPy = py * py, one_px = 1.0 - px;
|
|
Toshihiro Shimizu |
890ddd |
double a = w * (one_px * one_px + sqPy),
|
|
Toshihiro Shimizu |
890ddd |
b = w * (px * one_px - sqPy),
|
|
Toshihiro Shimizu |
890ddd |
c = w * (py * one_px + px * py),
|
|
Toshihiro Shimizu |
890ddd |
d = w * (px * px + sqPy);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sqPy *= w;
|
|
Toshihiro Shimizu |
890ddd |
one_px *= w;
|
|
Toshihiro Shimizu |
890ddd |
px *= w;
|
|
Toshihiro Shimizu |
890ddd |
py *= w;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0x, v0x) += a;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0x, v1x) += b;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0x, v1y) += c;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0x, v2x) -= one_px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0x, v2y) -= py;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0y, v0y) += a;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0y, v1x) -= py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0y, v1y) += b;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0y, v2x) += py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v0y, v2y) -= one_px;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1x, v0x) += b;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1x, v0y) += -py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1x, v1x) += d;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1x, v2x) += -px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1x, v2y) += py;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1y, v0x) += c;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1y, v0y) += b;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1y, v1y) += d;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1y, v2x) -= py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v1y, v2y) -= px;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2x, v0x) -= one_px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2x, v0y) += py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2x, v1x) -= px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2x, v1y) -= py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2x, v2x) += w;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2y, v0x) -= py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2y, v0y) -= one_px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2y, v1x) += py;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2y, v1y) -= px;
|
|
Toshihiro Shimizu |
890ddd |
G.at(v2y, v2y) += w;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void buildF(double px, double py, tlin::spmat &F)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double one_px = 1.0 - px, sqPy = py * py;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
F.at(0, 0) = 1.0 + one_px * one_px + sqPy;
|
|
Toshihiro Shimizu |
890ddd |
F.at(1, 1) = F(0, 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
F.at(0, 2) = px * one_px - sqPy;
|
|
Toshihiro Shimizu |
890ddd |
F.at(0, 3) = py * one_px + px * py;
|
|
Toshihiro Shimizu |
890ddd |
F.at(1, 2) = -F(0, 3);
|
|
Toshihiro Shimizu |
890ddd |
F.at(1, 3) = F(0, 2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
F.at(2, 0) = F(0, 2);
|
|
Toshihiro Shimizu |
890ddd |
F.at(2, 1) = F(1, 2);
|
|
Toshihiro Shimizu |
890ddd |
F.at(3, 0) = F(0, 3);
|
|
Toshihiro Shimizu |
890ddd |
F.at(3, 1) = F(1, 3);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
F.at(2, 2) = 1.0 + px * px + sqPy;
|
|
Toshihiro Shimizu |
890ddd |
F.at(3, 3) = F(2, 2);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void build_c(double v0x, double v0y, double v1x, double v1y, double v2x, double v2y, double px, double py, double *c)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
c[0] = (v0x + v2x * (1.0 - px) + v2y * py);
|
|
Toshihiro Shimizu |
890ddd |
c[1] = (v0y - v2x * py + v2y * (1.0 - px));
|
|
Toshihiro Shimizu |
890ddd |
c[2] = (v1x + v2x * px - v2y * py);
|
|
Toshihiro Shimizu |
890ddd |
c[3] = (v1y + v2y * px + v2x * py);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void addHValues(int v0, int v1, double w, tlin::spmat &H)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
H.at(v0, v0) += w;
|
|
Toshihiro Shimizu |
890ddd |
H.at(v1, v0) -= w;
|
|
Toshihiro Shimizu |
890ddd |
H.at(v0, v1) -= w;
|
|
Toshihiro Shimizu |
890ddd |
H.at(v1, v1) += w;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
inline void add_f_values(int v0, int v1, double fit0, double fit1, double w, double *f)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
double f0_f1 = w * (fit0 - fit1);
|
|
Toshihiro Shimizu |
890ddd |
f[v0] += f0_f1;
|
|
Toshihiro Shimizu |
890ddd |
f[v1] -= f0_f1;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// PlasticDeformer::Imp definition
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
class PlasticDeformer::Imp
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
TTextureMeshP m_mesh; //!< Deformed mesh (cannot be changed)
|
|
Toshihiro Shimizu |
890ddd |
std::vector<plastichandle> m_handles; //!< Compiled handles</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
std::vector<linearconstraint> m_constraints1, m_constraints3; //!< Compiled constraints (depends on the above)</linearconstraint>
|
|
Toshihiro Shimizu |
890ddd |
bool m_compiled; //!< Whether the deformer is ready to deform()
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
Imp();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void initialize(const TTextureMeshP &mesh);
|
|
Toshihiro Shimizu |
890ddd |
void compile(const std::vector<plastichandle> &handles, int *faceHints);</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
void deform(const TPointD *dstHandles, double *dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void copyOriginals(double *dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat m_G; //!< Pre-initialized entries for the 1st
|
|
Toshihiro Shimizu |
890ddd |
//!< linear system
|
|
Toshihiro Shimizu |
890ddd |
SuperFactorsPtr m_invC; //!< C's factors (C is G plus linear constraints)
|
|
Toshihiro Shimizu |
890ddd |
DoublePtr m_q; //!< Step 1's known term
|
|
Toshihiro Shimizu |
890ddd |
DoublePtr m_out; //!< Step 1's result
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Step 1 members:
|
|
Toshihiro Shimizu |
890ddd |
// The first step of a MeshDeformer instance is about building the desired vertices configuration.
|
|
Toshihiro Shimizu |
890ddd |
void initializeStep1();
|
|
Toshihiro Shimizu |
890ddd |
void compileStep1(const std::vector<plastichandle> &handles);</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
void deformStep1(const TPointD *dstHandles, double *dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void releaseInitializedData();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
std::vector<superfactorsptr> m_invF; //!< Each of step 2's systems factorizations</superfactorsptr>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointDPtr m_relativeCoords; //!< Faces' p2 coordinates in (p0, p1)'s orthogonal reference
|
|
Toshihiro Shimizu |
890ddd |
double m_v[4], m_c[4]; //!< Known term and output coordinates
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointDPtr m_fitTriangles; //!< Output face coordinates
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Step 2 members:
|
|
Toshihiro Shimizu |
890ddd |
// The second step of MeshDeformer rigidly maps neighbourhoods of the original mesh
|
|
Toshihiro Shimizu |
890ddd |
// to fit as much as possible the neighbourhoods in the step 1 result.
|
|
Toshihiro Shimizu |
890ddd |
void initializeStep2();
|
|
Toshihiro Shimizu |
890ddd |
void compileStep2(const std::vector<plastichandle> &handles);</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
void deformStep2(const TPointD *dstHandles, double *dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Toshihiro Shimizu |
890ddd |
// NOTE: This step accepts separation in the X and Y components
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat m_H; //!< Step 3's system entries
|
|
Toshihiro Shimizu |
890ddd |
SuperFactorsPtr m_invK; //!< System inverse
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
DoublePtr m_fx, m_fy; //!< Known terms
|
|
Toshihiro Shimizu |
890ddd |
DoublePtr m_x, m_y; //!< Output values
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Step 3 members:
|
|
Toshihiro Shimizu |
890ddd |
// The third step of MeshDeformer glues together the mapped neighbourhoods from step2.
|
|
Toshihiro Shimizu |
890ddd |
void initializeStep3();
|
|
Toshihiro Shimizu |
890ddd |
void compileStep3(const std::vector<plastichandle> &handles);</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
void deformStep3(const TPointD *dstHandles, double *dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformer::Imp::Imp()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::initialize(const TTextureMeshP &mesh)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert("Input mesh must be squeezed!" &&
|
|
Toshihiro Shimizu |
890ddd |
mesh->verticesCount() == mesh->vertices().nodesCount() &&
|
|
Toshihiro Shimizu |
890ddd |
mesh->edgesCount() == mesh->edges().nodesCount() &&
|
|
Toshihiro Shimizu |
890ddd |
mesh->facesCount() == mesh->faces().nodesCount());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_mesh = mesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
initializeStep1();
|
|
Toshihiro Shimizu |
890ddd |
initializeStep2();
|
|
Toshihiro Shimizu |
890ddd |
initializeStep3();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_compiled = false; // Compilation is expected after a new initialization
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::compile(const std::vector<plastichandle> &handles,</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
int *faceHints)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_mesh);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_handles.clear(), m_handles.reserve(handles.size());
|
|
Toshihiro Shimizu |
890ddd |
m_constraints1.clear(), m_constraints3.clear();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LinearConstraint constr;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build the linear constraints raising from the mesh-handles pairing
|
|
Toshihiro Shimizu |
890ddd |
int h, hCount = handles.size();
|
|
Toshihiro Shimizu |
890ddd |
for (h = 0; h < hCount; ++h) {
|
|
Toshihiro Shimizu |
890ddd |
int localFaceIdx = -1, &faceIdx = faceHints ? faceHints[h] : localFaceIdx;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
::buildTriangularCoordinates(*m_mesh, faceIdx, handles[h].m_pos, constr.m_k[0], constr.m_k[1], constr.m_k[2]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (faceIdx >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
constr.m_h = h;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_mesh->faceVertices(faceIdx, constr.m_v[0], constr.m_v[1], constr.m_v[2]);
|
|
Toshihiro Shimizu |
890ddd |
m_constraints1.push_back(constr);
|
|
Toshihiro Shimizu |
890ddd |
if (handles[h].m_interpolate)
|
|
Toshihiro Shimizu |
890ddd |
m_constraints3.push_back(constr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Store the handles to retain precompiled data
|
|
Toshihiro Shimizu |
890ddd |
m_handles.push_back(handles[h]);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//m_handles = handles; // NOT directly copied like this: some handles could be
|
|
Toshihiro Shimizu |
890ddd |
// (geometrically) OUTSIDE the mesh!
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Now, invoke the actual compilation procedures
|
|
Toshihiro Shimizu |
890ddd |
m_compiled = true;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_handles.size() < 2)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
compileStep1(handles); // These may set m_compiled = false. Must still be
|
|
Toshihiro Shimizu |
890ddd |
compileStep2(handles); // called even when that happens - as they are
|
|
Toshihiro Shimizu |
890ddd |
compileStep3(handles); // responsible for resources reclamation.
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::deform(const TPointD *dstHandles, double *dstVerticesCoords)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
assert(m_mesh);
|
|
Toshihiro Shimizu |
890ddd |
assert(dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Deal with trivial cases
|
|
Toshihiro Shimizu |
890ddd |
if (!m_compiled || m_handles.size() == 0) {
|
|
Toshihiro Shimizu |
890ddd |
// Cannot deform anything - just copy the source mesh vertices into dst ones
|
|
Toshihiro Shimizu |
890ddd |
copyOriginals(dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
assert(dstHandles);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (m_handles.size() == 1) {
|
|
Toshihiro Shimizu |
890ddd |
// 1 handle inside the mesh - pure translational case
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const PlasticHandle &srcHandle = m_handles.front();
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &dstHandlePos = dstHandles[m_constraints1.front().m_h];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD shift(dstHandlePos - srcHandle.m_pos);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int v, vCount = m_mesh->verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (v = 0; v != vCount; ++v, dstVerticesCoords += 2) {
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[0] = m_mesh->vertex(v).P().x + shift.x;
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[1] = m_mesh->vertex(v).P().y + shift.y;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
deformStep1(dstHandles, dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
deformStep2(dstHandles, dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
deformStep3(dstHandles, dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::copyOriginals(double *dstVerticesCoords)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int v, vCount = m_mesh->verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (v = 0; v != vCount; ++v, dstVerticesCoords += 2) {
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[0] = m_mesh->vertex(v).P().x;
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[1] = m_mesh->vertex(v).P().y;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::releaseInitializedData()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Release m_G and m_H
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat temp;
|
|
Toshihiro Shimizu |
890ddd |
swap(m_G, temp);
|
|
Toshihiro Shimizu |
890ddd |
} // Ensure resources release by swapping them
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat temp;
|
|
Toshihiro Shimizu |
890ddd |
swap(m_H, temp);
|
|
Toshihiro Shimizu |
890ddd |
} // with newly initialized instances
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Plastic Deformation Step 1
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::initializeStep1()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int vCount = mesh.verticesCount(), vCount_2 = 2 * vCount;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_G = tlin::spmat(vCount_2, vCount_2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Initialize the linear system indices for the stored mesh
|
|
Toshihiro Shimizu |
890ddd |
int f, fCount = mesh.facesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0; f < fCount; ++f) {
|
|
Toshihiro Shimizu |
890ddd |
int v0, v1, v2;
|
|
Toshihiro Shimizu |
890ddd |
mesh.faceVertices(f, v0, v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int v0x = 2 * v0; // We'll use 2 params per vertex - with
|
|
Toshihiro Shimizu |
890ddd |
int v0y = v0x + 1; // adjacent x and y parameters
|
|
Toshihiro Shimizu |
890ddd |
int v1x = 2 * v1;
|
|
Toshihiro Shimizu |
890ddd |
int v1y = v1x + 1;
|
|
Toshihiro Shimizu |
890ddd |
int v2x = 2 * v2;
|
|
Toshihiro Shimizu |
890ddd |
int v2y = v2x + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &vx0 = mesh.vertex(v0);
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &vx1 = mesh.vertex(v1);
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::vertex_type &vx2 = mesh.vertex(v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD c0, c1, c2;
|
|
Toshihiro Shimizu |
890ddd |
c2 = tcg::point_ops::ortCoords(vx2.P(), vx0.P(), vx1.P());
|
|
Toshihiro Shimizu |
890ddd |
c0 = tcg::point_ops::ortCoords(vx0.P(), vx1.P(), vx2.P());
|
|
Toshihiro Shimizu |
890ddd |
c1 = tcg::point_ops::ortCoords(vx1.P(), vx2.P(), vx0.P());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
addGValues(v0x, v0y, v1x, v1y, v2x, v2y, c2.x, c2.y, vx2.P().rigidity, m_G);
|
|
Toshihiro Shimizu |
890ddd |
addGValues(v1x, v1y, v2x, v2y, v0x, v0y, c0.x, c0.y, vx0.P().rigidity, m_G);
|
|
Toshihiro Shimizu |
890ddd |
addGValues(v2x, v2y, v0x, v0y, v1x, v1y, c1.x, c1.y, vx1.P().rigidity, m_G);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::compileStep1(const std::vector<plastichandle> &handles)</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// First, release resources
|
|
Toshihiro Shimizu |
890ddd |
m_invC.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_q.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_out.reset();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Now, start compiling
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int vCount = mesh.verticesCount(), hCount = m_handles.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int cSize = 2 * (vCount + hCount); // Coefficients count
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Initialize C with G
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperMatrix *trC = 0;
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat C(cSize, cSize);
|
|
Toshihiro Shimizu |
890ddd |
C.entries() = m_G.entries();
|
|
Toshihiro Shimizu |
890ddd |
C.entries().hashFunctor().m_cols = C.cols();
|
|
Toshihiro Shimizu |
890ddd |
C.entries().rehash(C.entries().buckets().size()); // Rehash to entries according to C's size
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Add the entries constraining handles
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
std::vector<linearconstraint>::iterator ht, hEnd(m_constraints1.end());</linearconstraint>
|
|
Toshihiro Shimizu |
890ddd |
for (i = 0, ht = m_constraints1.begin(); ht != hEnd; ++i, ++ht)
|
|
Toshihiro Shimizu |
890ddd |
addConstraint2d(2 * (vCount + i), *ht, C);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::traduceS(C, trC);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build m_invC
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperFactors *invC = 0;
|
|
Toshihiro Shimizu |
890ddd |
tlin::factorize(trC, invC);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::freeS(trC);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (invC) {
|
|
Toshihiro Shimizu |
890ddd |
m_invC.reset(invC);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Reallocate arrays
|
|
Toshihiro Shimizu |
890ddd |
m_q.reset((double *)malloc(cSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
m_out.reset((double *)malloc(cSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
memset(m_q.get(), 0, 2 * vCount * sizeof(double)); // Initialize the system's known term with 0
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_compiled = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::deformStep1(const TPointD *dstHandles, double *dstVerticesCoords)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int vCount2 = 2 * m_mesh->verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
int cSize = vCount2 + 2 * m_handles.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Copy destination handles into the system's known term
|
|
Toshihiro Shimizu |
890ddd |
int i, h;
|
|
Toshihiro Shimizu |
890ddd |
for (i = vCount2, h = 0; i < cSize; i += 2, ++h) {
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &dstHandlePos = dstHandles[m_constraints1[h].m_h];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_q[i] = dstHandlePos.x; // NOTE: We could use calloc on-the-fly, sparing
|
|
Toshihiro Shimizu |
890ddd |
m_q[i + 1] = dstHandlePos.y; // some memory. Have to benchmark the cost, though...
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Solve the linear system
|
|
Toshihiro Shimizu |
890ddd |
double *out = m_out.get();
|
|
Toshihiro Shimizu |
890ddd |
tlin::solve(m_invC.get(), m_q.get(), out);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef GL_DEBUG
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(1.0, 0.0, 0.0); // Red
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_LINES);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Draw deformed mesh edges
|
|
Toshihiro Shimizu |
890ddd |
int e, eCount = m_mesh->edgesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (e = 0; e < eCount; ++e) {
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh::edge_type &ed = m_mesh->edge(e);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double *x0 = out + 2 * ed.vertex(0), *x1 = out + 2 * ed.vertex(1);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(*x0, *(x0 + 1));
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(*x1, *(x1 + 1));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Plastic Deformation Step 2
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::initializeStep2()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int f, fCount = mesh.facesCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Clear and re-initialize vars
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat F(4, 4);
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperMatrix *trF;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<superfactorsptr>(fCount).swap(m_invF);</superfactorsptr>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_relativeCoords.reset(new TPointD[fCount]);
|
|
Toshihiro Shimizu |
890ddd |
m_fitTriangles.reset(new TPointD[3 * fCount]);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build step 2's system factorizations (yep, can be done at this point)
|
|
Toshihiro Shimizu |
890ddd |
const TPointD *p0, *p1, *p2;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0; f < fCount; ++f) {
|
|
Toshihiro Shimizu |
890ddd |
::vertices(mesh, f, p0, p1, p2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TPointD c(tcg::point_ops::ortCoords(*p2, *p0, *p1));
|
|
Toshihiro Shimizu |
890ddd |
m_relativeCoords[f] = c;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
F.clear();
|
|
Toshihiro Shimizu |
890ddd |
buildF(c.x, c.y, F);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
trF = 0;
|
|
Toshihiro Shimizu |
890ddd |
tlin::traduceS(F, trF);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperFactors *invF = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::factorize(trF, invF);
|
|
Toshihiro Shimizu |
890ddd |
m_invF[f].reset(invF);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::freeS(trF);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::compileStep2(const std::vector<plastichandle> &handles)</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// Nothing to do :)
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::deformStep2(const TPointD *dstHandles, double *dstVerticesCoords)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int vCount = mesh.verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
memset(m_fx.get(), 0, vCount * sizeof(double)); // These should be part of step 3...
|
|
Toshihiro Shimizu |
890ddd |
memset(m_fy.get(), 0, vCount * sizeof(double)); // They are filled here just for convenience
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build fit triangles
|
|
Toshihiro Shimizu |
890ddd |
TPointD *fitTri = m_fitTriangles.get(), *relCoord = m_relativeCoords.get();
|
|
Toshihiro Shimizu |
890ddd |
double *out1 = m_out.get();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int f, fCount = mesh.facesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0; f < fCount; ++f, fitTri += 3, ++relCoord) {
|
|
Toshihiro Shimizu |
890ddd |
int v0, v1, v2;
|
|
Toshihiro Shimizu |
890ddd |
m_mesh->faceVertices(f, v0, v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const RigidPoint &p0 = mesh.vertex(v0).P(), &p1 = mesh.vertex(v1).P(), &p2 = mesh.vertex(v2).P();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double *v0x = out1 + (v0 << 1), *v0y = v0x + 1,
|
|
Toshihiro Shimizu |
890ddd |
*v1x = out1 + (v1 << 1), *v1y = v1x + 1,
|
|
Toshihiro Shimizu |
890ddd |
*v2x = out1 + (v2 << 1), *v2y = v2x + 1;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
build_c(
|
|
Toshihiro Shimizu |
890ddd |
*v0x, *v0y,
|
|
Toshihiro Shimizu |
890ddd |
*v1x, *v1y,
|
|
Toshihiro Shimizu |
890ddd |
*v2x, *v2y,
|
|
Toshihiro Shimizu |
890ddd |
relCoord->x, relCoord->y, m_c);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double *vPtr = (double *)m_v;
|
|
Toshihiro Shimizu |
890ddd |
tlin::solve(m_invF[f].get(), (double *)m_c, vPtr);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fitTri[0].x = m_v[0], fitTri[0].y = m_v[1];
|
|
Toshihiro Shimizu |
890ddd |
fitTri[1].x = m_v[2], fitTri[1].y = m_v[3];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fitTri[2].x = fitTri[0].x + relCoord->x * (fitTri[1].x - fitTri[0].x) + relCoord->y * (fitTri[1].y - fitTri[0].y);
|
|
Toshihiro Shimizu |
890ddd |
fitTri[2].y = fitTri[0].y + relCoord->x * (fitTri[1].y - fitTri[0].y) + relCoord->y * (fitTri[0].x - fitTri[1].x);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Scale with respect to baricenter. The baricenter is used since it makes distance from vertices equally
|
|
Toshihiro Shimizu |
890ddd |
// weighting - which is the same expected when minimizing positions (by collateral effect) in the next step.
|
|
Toshihiro Shimizu |
890ddd |
TPointD baricenter(
|
|
Toshihiro Shimizu |
890ddd |
(fitTri[0].x + fitTri[1].x + fitTri[2].x) / 3.0,
|
|
Toshihiro Shimizu |
890ddd |
(fitTri[0].y + fitTri[1].y + fitTri[2].y) / 3.0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double scale = sqrt(
|
|
Toshihiro Shimizu |
890ddd |
norm2(TPointD(p1.x - p0.x, p1.y - p0.y)) /
|
|
Toshihiro Shimizu |
890ddd |
norm2(TPointD(fitTri[1].x - fitTri[0].x, fitTri[1].y - fitTri[0].y)));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
fitTri[0] = scale * (fitTri[0] - baricenter) + baricenter;
|
|
Toshihiro Shimizu |
890ddd |
fitTri[1] = scale * (fitTri[1] - baricenter) + baricenter;
|
|
Toshihiro Shimizu |
890ddd |
fitTri[2] = scale * (fitTri[2] - baricenter) + baricenter;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build f -- note: this should be part of step 3, we're just avoiding the same cycle twice :)
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v0, v1, fitTri[0].x, fitTri[1].x, tmin(p0.rigidity, p1.rigidity), m_fx.get());
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v0, v1, fitTri[0].y, fitTri[1].y, tmin(p0.rigidity, p1.rigidity), m_fy.get());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v1, v2, fitTri[1].x, fitTri[2].x, tmin(p1.rigidity, p2.rigidity), m_fx.get());
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v1, v2, fitTri[1].y, fitTri[2].y, tmin(p1.rigidity, p2.rigidity), m_fy.get());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v2, v0, fitTri[2].x, fitTri[0].x, tmin(p2.rigidity, p0.rigidity), m_fx.get());
|
|
Toshihiro Shimizu |
890ddd |
add_f_values(v2, v0, fitTri[2].y, fitTri[0].y, tmin(p2.rigidity, p0.rigidity), m_fy.get());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#ifdef GL_DEBUG
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glColor3d(0.0, 0.0, 1.0); // Blue
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Draw fit triangles
|
|
Toshihiro Shimizu |
890ddd |
fitTri = m_fitTriangles.get();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0; f < fCount; ++f, fitTri += 3) {
|
|
Toshihiro Shimizu |
890ddd |
glBegin(GL_LINE_LOOP);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(fitTri[0].x, fitTri[0].y);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(fitTri[1].x, fitTri[1].y);
|
|
Toshihiro Shimizu |
890ddd |
glVertex2d(fitTri[2].x, fitTri[2].y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
glEnd();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#endif
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Plastic Deformation Step 3
|
|
Toshihiro Shimizu |
890ddd |
//******************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::initializeStep3()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
int vCount = mesh.verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_H = tlin::spmat(vCount, vCount);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int f, fCount = mesh.facesCount();
|
|
Toshihiro Shimizu |
890ddd |
for (f = 0; f < fCount; ++f) {
|
|
Toshihiro Shimizu |
890ddd |
int v0, v1, v2;
|
|
Toshihiro Shimizu |
890ddd |
mesh.faceVertices(f, v0, v1, v2);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const RigidPoint &p0 = mesh.vertex(v0).P(),
|
|
Toshihiro Shimizu |
890ddd |
&p1 = mesh.vertex(v1).P(),
|
|
Toshihiro Shimizu |
890ddd |
&p2 = mesh.vertex(v2).P();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
addHValues(v0, v1, tmin(p0.rigidity, p1.rigidity), m_H);
|
|
Toshihiro Shimizu |
890ddd |
addHValues(v1, v2, tmin(p1.rigidity, p2.rigidity), m_H);
|
|
Toshihiro Shimizu |
890ddd |
addHValues(v2, v0, tmin(p2.rigidity, p0.rigidity), m_H);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::compileStep3(const std::vector<plastichandle> &handles)</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
// First, release resources
|
|
Toshihiro Shimizu |
890ddd |
m_invK.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_x.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_y.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_fx.reset();
|
|
Toshihiro Shimizu |
890ddd |
m_fy.reset();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// If compilation already failed, skip
|
|
Toshihiro Shimizu |
890ddd |
if (!m_compiled)
|
|
Toshihiro Shimizu |
890ddd |
return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TTextureMesh &mesh = *m_mesh;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int vCount = mesh.verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
int kSize = vCount + m_constraints3.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Initialize K with H
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperMatrix *trK = 0;
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
tlin::spmat K(kSize, kSize);
|
|
Toshihiro Shimizu |
890ddd |
K.entries() = m_H.entries();
|
|
Toshihiro Shimizu |
890ddd |
K.entries().hashFunctor().m_cols = K.cols();
|
|
Toshihiro Shimizu |
890ddd |
K.entries().rehash(K.entries().buckets().size()); //Rehash to entries according to K's size
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Add the entries constraining handles
|
|
Toshihiro Shimizu |
890ddd |
int c, cnstrCount = m_constraints3.size();
|
|
Toshihiro Shimizu |
890ddd |
for (c = 0; c < cnstrCount; ++c) {
|
|
Toshihiro Shimizu |
890ddd |
// Add the linear constraint to the system
|
|
Toshihiro Shimizu |
890ddd |
addConstraint1d(vCount + c, m_constraints3[c], K);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::traduceS(K, trK);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Build m_invK
|
|
Toshihiro Shimizu |
890ddd |
tlin::SuperFactors *invK = 0;
|
|
Toshihiro Shimizu |
890ddd |
tlin::factorize(trK, invK);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
tlin::freeS(trK);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (invK) {
|
|
Toshihiro Shimizu |
890ddd |
m_invK.reset(invK);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_x.reset((double *)malloc(kSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
m_y.reset((double *)malloc(kSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
m_fx.reset((double *)malloc(kSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
m_fy.reset((double *)malloc(kSize * sizeof(double)));
|
|
Toshihiro Shimizu |
890ddd |
} else
|
|
Toshihiro Shimizu |
890ddd |
m_compiled = false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::Imp::deformStep3(const TPointD *dstHandles, double *dstVerticesCoords)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
int v, vCount = m_mesh->verticesCount();
|
|
Toshihiro Shimizu |
890ddd |
int c;
|
|
Toshihiro Shimizu |
890ddd |
int h, hCount = m_handles.size();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
for (c = 0, h = 0; h < hCount; ++h) {
|
|
Toshihiro Shimizu |
890ddd |
if (!m_handles[h].m_interpolate)
|
|
Toshihiro Shimizu |
890ddd |
continue;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
const TPointD &dstHandlePos = dstHandles[m_constraints1[h].m_h];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_fx[vCount + c] = dstHandlePos.x;
|
|
Toshihiro Shimizu |
890ddd |
m_fy[vCount + c] = dstHandlePos.y;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
++c;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
double *x = m_x.get(), *y = m_y.get();
|
|
Toshihiro Shimizu |
890ddd |
tlin::solve(m_invK.get(), m_fx.get(), x);
|
|
Toshihiro Shimizu |
890ddd |
tlin::solve(m_invK.get(), m_fy.get(), y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int i;
|
|
Toshihiro Shimizu |
890ddd |
for (i = v = 0; v < vCount; ++v, i += 2) {
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[i] = m_x[v];
|
|
Toshihiro Shimizu |
890ddd |
dstVerticesCoords[i + 1] = m_y[v];
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//**********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Plastic Deformer implementation
|
|
Toshihiro Shimizu |
890ddd |
//**********************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformer::PlasticDeformer()
|
|
Toshihiro Shimizu |
890ddd |
: m_imp(new Imp)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
PlasticDeformer::~PlasticDeformer()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
delete m_imp;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool PlasticDeformer::compiled() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return m_imp->m_compiled;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::initialize(const TTextureMeshP &mesh)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->initialize(mesh);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool PlasticDeformer::compile(const std::vector<plastichandle> &handles, int *faceHints)</plastichandle>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->compile(handles, faceHints);
|
|
Toshihiro Shimizu |
890ddd |
return compiled();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::deform(const TPointD *dstHandles, double *dstVerticesCoords) const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->deform(dstHandles, dstVerticesCoords);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void PlasticDeformer::releaseInitializedData()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_imp->releaseInitializedData();
|
|
Toshihiro Shimizu |
890ddd |
}
|