Geometry Processing Research in Python
Let us end this tutorial on a light note. The last two common geometry processing tasks that we will learn how to do are subdivision and decimation.
Sometimes you have a coarse mesh, and you want to transform it into a fine,
dense, and smooth mesh.
One way to achieve this is to subdivide the mesh.
Gpytoolbox implements Loop subdivision, a standard
method for this task.
To use it, call the subdivide function with the method='loop' option.
With the iters option, you can specify how much you want to subdivide/smooth
your surface:
import gpytoolbox as gpy, numpy as np, polyscope as ps
V,F = gpy.read_mesh("data/penguin_low_res.obj")
V1,F1 = gpy.subdivide(V, F, method='loop')
V3,F3 = gpy.subdivide(V, F, method='loop', iters=3)
ps.init()
ps_penguin0 = ps.register_surface_mesh("penguin coarse", V, F,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin1 = ps.register_surface_mesh("penguin finer", V1, F1,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin3 = ps.register_surface_mesh("penguin finest", V3, F3,
material='wax', smooth_shade=True, edge_width=1.)
ps.show()This displays (enabling the different surfaces separately)
Loop subdivision is a linear operation.
This means that there is a matrix S such that V1 == S*V.
We can use this property to upsample any function u on the coarse mesh V
to the subdivided mesh V1 with S*u.
To obtain the matrix S from Gpytoolbox, set the property return_matrix=True:
import gpytoolbox as gpy, numpy as np, polyscope as ps
V,F = gpy.read_mesh("data/penguin_low_res.obj")
u = V[:,1]
V1,F1,S = gpy.subdivide(V, F, method='loop', return_matrix=True)
ps.init()
ps_penguin0 = ps.register_surface_mesh("penguin coarse", V, F,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin0.add_scalar_quantity("u", u, enabled=True)
ps_penguin1 = ps.register_surface_mesh("penguin finer", V1, F1,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin1.add_scalar_quantity("u", S*u, enabled=True)
ps.show()This displays (enabling the different surfaces separately)
What if you have a very fine mesh, but you want a coarse mesh? This is what decimation is for.
In Gpytoolbox you can get a coarse mesh from a fine edge using the decimate
method.
It takes as arguments the mesh V, F, and the face ratio (what do you want
the ratio of faces in the new mesh to be like compared to the old mesh):
import gpytoolbox as gpy, numpy as np, polyscope as ps
V,F = gpy.read_mesh("data/penguin_high_res.obj")
V1,F1,_,_ = gpy.decimate(V, F, face_ratio=0.2)
V2,F2,_,_ = gpy.decimate(V, F, face_ratio=0.05)
ps.init()
ps_penguin0 = ps.register_surface_mesh("penguin fine", V, F,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin1 = ps.register_surface_mesh("penguin decimated", V1, F1,
material='wax', smooth_shade=True, edge_width=1.)
ps_penguin2 = ps.register_surface_mesh("penguin decimated more", V2, F2,
material='wax', smooth_shade=True, edge_width=1.)
ps.show()This displays (enabling the different surfaces separately)
NOTE: Instead of face_ratio, you can also specify your desired target face
count directly with the num_faces argument.
That was everything in this tutorial for now. You now know how to get started with a few basic geometry processing tasks in Python. Now, go have fun with your own research project!
Oded Stein 2024. Geometry Processing Research in Python


