Mesh deformation¶
If we want to deform a triangle mesh according a small number of constraints, we can use mesh deformation algorithms. Open3D implements the as-rigid-as-possible method by [SorkineAndAlexa2007] that optimizes the following energy functional
\begin{equation} \sum_i \sum_{j \in \mathcal{N}(i)} w_{ij} || (\mathbf{p}'_i - \mathbf{p}'_j) - \mathbf{R}_i (\mathbf{p}_i - \mathbf{p}_j)||^2 \,, \end{equation}
where \(\mathbf{R}_i\) are rotation matrices that we want to optimize for, and \(\mathbf{p}'_i\) and \(\mathbf{p}_i\) are the vertex positions after and before the optimization, respectively. \(\mathcal{N}(i)\) is the set of neighbours of vertex \(i\). The weights \(w_{ij}\) are cot weights.
Open3D implementes this method in deform_as_rigid_as_possible
. The first argument to this method is a set of constraint_ids
that refer to the vertices in the triangle mesh. The second argument constrint_pos
defines at which position those vertices should be after the optimization. The optimization process is an iterative scheme. Hence, we also can define the number of iterations via max_iter
.
[2]:
mesh = o3dtut.get_armadillo_mesh()
vertices = np.asarray(mesh.vertices)
static_ids = [idx for idx in np.where(vertices[:, 1] < -30)[0]]
static_pos = []
for id in static_ids:
static_pos.append(vertices[id])
handle_ids = [2490]
handle_pos = [vertices[2490] + np.array((-40, -40, -40))]
constraint_ids = o3d.utility.IntVector(static_ids + handle_ids)
constraint_pos = o3d.utility.Vector3dVector(static_pos + handle_pos)
with o3d.utility.VerbosityContextManager(o3d.utility.VerbosityLevel.Debug) as cm:
mesh_prime = mesh.deform_as_rigid_as_possible(
constraint_ids, constraint_pos, max_iter=50)
[3]:
print('Original Mesh')
R = mesh.get_rotation_matrix_from_xyz((0,np.pi,0))
o3d.visualization.draw_geometries([mesh.rotate(R)])
print('Deformed Mesh')
mesh_prime.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh_prime.rotate(R)])
Original Mesh
Deformed Mesh
Smoothed ARAP¶
Open3D also implements a smoothed version of the ARAP objective defined as
\begin{equation} \sum_i \sum_{j \in \mathcal{N}(i)} w_{ij} || (\mathbf{p}'_i - \mathbf{p}'_j) - \mathbf{R}_i (\mathbf{p}_i - \mathbf{p}_j)||^2 + \alpha A ||\mathbf{R}_i - \mathbf{R}_j||^2\,, \end{equation}
that penalizes a deviation of neighbouring rotation matrices. \(\alpha\) is a trade-off parameter for the regularization term and \(A\) is the surface area.
The smoothed objective can be used in deform_as_rigid_as_possible
by using the argument energy
with the parameter Smoothed
.