网格变形
如果我们想根据少量约束来对一个三角网格进行变形,可以使用网格变形(mesh deformation)算法。Open3D 实现了 [SorkineAndAlexa2007] 提出的”尽可能刚性”(as-rigid-as-possible, ARAP)方法,它优化以下能量函数:
其中 是我们需要优化的旋转矩阵, 和 分别是优化前后的顶点位置; 是顶点 的邻居集合;权重 为余切权重(cotangent weights)。
Open3D 在 deform_as_rigid_as_possible 中实现了该方法。该方法的第一个参数是一组 constraint_ids,指向三角网格中的顶点;第二个参数 constraint_pos(原文如此)定义这些顶点在优化后应处于的位置。优化过程是一个迭代格式,因此我们还可以通过 max_iter 来设定迭代次数。
armadillo = o3d.data.ArmadilloMesh()mesh = o3d.io.read_triangle_mesh(armadillo.path)
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)在 Debug 日志级别下,求解器会输出建矩阵与每轮迭代的进度(迭代日志重复输出 [DeformAsRigidAsPossible],此处省略):
[Open3D DEBUG] [DeformAsRigidAsPossible] setting up S'[Open3D DEBUG] [DeformAsRigidAsPossible] done setting up S'[Open3D DEBUG] [DeformAsRigidAsPossible] setting up system matrix L[Open3D DEBUG] [DeformAsRigidAsPossible] done setting up system matrix L[Open3D DEBUG] [DeformAsRigidAsPossible] setting up sparse solver[Open3D DEBUG] [DeformAsRigidAsPossible] done setting up sparse solver[Open3D DEBUG] [DeformAsRigidAsPossible] ...(省略重复的迭代日志)...print('Original Mesh')R = mesh.get_rotation_matrix_from_xyz((0, np.pi, 0))o3d.visualization.draw_geometries([mesh.rotate(R, center=mesh.get_center())])print('Deformed Mesh')mesh_prime.compute_vertex_normals()o3d.visualization.draw_geometries( [mesh_prime.rotate(R, center=mesh_prime.get_center())])

输出:
Original MeshDeformed MeshSmoothed ARAP(平滑 ARAP)
Section titled “Smoothed ARAP(平滑 ARAP)”Open3D 还实现了 ARAP 目标的平滑版本,定义为:
该版本对相邻旋转矩阵之间的偏离进行惩罚。其中 是正则化项的权衡参数, 是表面积。
在 deform_as_rigid_as_possible 中,通过 energy 参数传入 Smoothed 即可使用该平滑目标。