-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflow_example.py
128 lines (106 loc) · 3.55 KB
/
flow_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python3
"""
This script show the real-time fairing of a closed mesh.
A small time step is taken in order to keep the animation smooth,
but larger time step works too.
"""
from functools import partial
import numpy as np
import trimesh
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import art3d
from matplotlib.colors import LightSource
from matplotlib import animation
from transformal.operators import mean_curvature
from transformal.transform import transform, scalar_curvature, get_oriented_one_ring
def vertex_to_face(trimesh, vval):
"""Interpolates vertex value to the face's center."""
assert vval.shape[0] == trimesh.vertices.shape[0]
return np.mean(vval[trimesh.faces], axis=1)
def to_cmap(v, v_min=None, v_max=None):
"""Returns rgba values."""
if v_min is None:
v_min = v.min()
if v_max is None:
v_max = v.max()
return plt.cm.plasma((v - v_min) / (v_max - v_min))
# Type hint to supress warnings of the editor since load can
# return different subclass of geometry
mesh: trimesh.Trimesh = trimesh.load("meshes/deform.ply")
vertices = mesh.vertices
nv = vertices.shape[0]
nf = mesh.faces.shape[0]
print("number of vertices", nv)
# center the object
vertices[:] = vertices - np.mean(vertices, axis=0)
# The one ring is needed for many subsequent routines
one_ring = get_oriented_one_ring(mesh)
# Defines the plot
fig, ax = plt.subplots(1, 1, figsize=(8, 7), subplot_kw={"projection": "3d"})
ax.axis("off")
# Use cuvature to define the coloration of the mesh's faces
k = scalar_curvature(
mesh, mean_curvature(vertices, one_ring["data"], one_ring["max_length"])
)
k_min = k.min()
k_max = k.max()
# Define the colors of the mesh
cm = to_cmap(vertex_to_face(mesh, k), k_min, k_max)
# Defines illumination
light = LightSource(90, 100)
FRACTION = 0.9
shade = light.shade_normals(mesh.face_normals, fraction=FRACTION)
shade.shape = (nf, 1, 1)
cm.shape = (nf, 1, 4)
cm = light.blend_overlay(cm, intensity=shade)
cm.shape = (nf, 4)
# creates the poligon collection (mesh faces)
triangles = vertices[mesh.faces]
polycol = art3d.Poly3DCollection(
triangles,
facecolors=cm,
edgecolors=(1, 1, 1, 0.2),
alpha=1,
)
def init_func(axes, polycolection, initial_vertices, figure):
"""Intialize the plot for animation."""
axes.add_collection(polycolection)
lim = (initial_vertices.min(), initial_vertices.max())
axes.set_xlim(*lim)
axes.set_ylim(*lim)
axes.set_zlim(*lim)
axes.set_box_aspect([1, 1, 1])
# ax.set_xlabel("x")
# ax.set_ylabel("y")
# ax.set_zlabel("z")
figure.tight_layout(pad=0)
def animate(i):
"""Animation funcion"""
dt = 0.5
if i > 5:
rho = -dt * scalar_curvature(
mesh, mean_curvature(vertices, one_ring["data"], one_ring["max_length"])
)
transform(vertices, rho, one_ring)
centerofmass = np.mean(vertices, axis=0)
vertices[:] = vertices - centerofmass # keeps the mesh centered
cmap = to_cmap(vertex_to_face(mesh, k), k_min, k_max)
intensity = light.shade_normals(mesh.face_normals, fraction=FRACTION)
intensity.shape = (nf, 1, 1)
cmap.shape = (nf, 1, 4)
cmap = light.blend_overlay(cmap, intensity=intensity)
cmap.shape = (nf, 4)
polycol.set_facecolor(cmap)
polycol.set_verts(vertices[mesh.faces])
return (polycol,)
ani = animation.FuncAnimation(
fig,
animate,
frames=60,
interval=50,
blit=False,
repeat=False,
init_func=partial(init_func, ax, polycol, vertices, fig),
)
plt.show()
# ani.save("animation.gif")