In this exercise, you will implement an algorithm to interactively deform 3D models. You will construct a two-level multi-resolution surface representation and use naive Laplacian editing to deform it.
For this task, you will compute a mesh deformation based on the rotations and translations applied interactively to a subset of its vertices via the mouse. Let
Let
- the vertices in
$H$ translated/rotated using the user-provided transformation$t$ , and - the vertices in
$R$ properly deformed using the algorithm described next.
The algorithm is divided in three phases:
- removing high-frequency details,
- deforming the smooth mesh, and
- transferring high-frequency details to the deformed surface.
A minimal sphere-based interface for selecting vertices has been implemented in Selection.ipynb
.
To use it, execute the cell with widgets, and select numbered keys to specify the segment index (+
key to add more).
Use sliders to adjust the position and radius of the selector sphere, and Paint!
to mark the current segment.
Finally, the accepted segments are stored in the variable segments_recording
,
which you can save as npy
file for the next tasks. There are several prepared file with suffix .label.npy
in the data/
folder.
Note: the array seg
stored is of integer type, with values 0,1,2,... where seg==0
indicates the free vertices, seg==1
means the first selected segment and so on.
In Assignment5.ipynb
, another interface is provided to specify the displacement and rotation.
The dropdown menu specifies which segement is being manipulated, and the slider
specifies the displacement x,y,z
and rotation α,β,γ
, the updated vertex positions are stored in handle_vertex_positions
.
Note: within handle_vertex_positions
, only the entries corresponding to selections (seg>0
) are supposed to be used.
Fig. 2: Input and Smoothed Meshes
We remove the high-frequency details from the vertices
where
Relevant scipy
functions: scipy.sparse.csc_matrix
, scipy.sparse.diags
,
Fig. 3: Deformed/Smoothed Meshes
The new deformed mesh is computed similarly to the previous step, by solving the minimization:
where
Relevant scipy
functions: scipy.sparse.linalg.spsolve
Fig 4: Displacements on $B$ (left) and $B'$ (right)
The high-frequency details on the original surface are extracted from
- The unit vertex normal
- The normalized projection of one of
$v$ 's outgoing edges onto the tangent plane defined by the vertex normal. A stable choice is the edge whose projection onto the tangent plane is longest. - The cross-product between (1) and (2)
For every vertex
Fig 5: Final Deformation Results
Recommended outputs:
- Provide screenshots for 4 different deformed meshes. For each example, provide a rendering of
$\mathcal{S}$ ,$\mathcal{B}$ ,$\mathcal{B}'$ and$\mathcal{S}'$ .
To achieve real-time performance, you must prefactor the sparse bi-Laplacian matrix appearing in both linear systems. After the user specifies vertex sets
Available Packages: scikit-sparse
, numba
.
Relevant functions: sksparse.cholmod
, numba.jit
, numpy.einsum
, scipy.sparse.linalg.splu