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