-
Notifications
You must be signed in to change notification settings - Fork 40
/
animation.py
104 lines (88 loc) · 3.55 KB
/
animation.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
# Copyright (C) 2023 ETH Zurich, Manuel Kaufmann, Velko Vechev, Dario Mylonopoulos
import numpy as np
import trimesh
from aitviewer.renderables.meshes import Meshes
from aitviewer.utils.so3 import aa2rot_numpy
from aitviewer.viewer import Viewer
if __name__ == "__main__":
# Number of frames.
N = 200
# Load a simple untextured cube.
cube = trimesh.load("resources/cube.obj")
# Create sequences of position, scale and rotation values.
p1 = np.linspace(np.array([0, 0, 0]), np.array([5, 0, 0]), num=N)
p2 = np.linspace(np.array([0, 0, 0]), np.array([0, 0, 5]), num=N)
p3 = np.linspace(np.array([0, 0, 0]), np.array([0, 5, 0]), num=N)
r2 = aa2rot_numpy(np.linspace([0, 0, 0], np.array([0, np.pi, 0]), num=N))
s3 = np.linspace(1.0, 2.0, num=N)
# Create 3 cubes, specifying sequences for their position, rotation and/or scale.
# Each property can be either a single value (e.g. a single position of shape (3)) or an array
# of values (e.g. an array of positions with shape (N, 3) where N is the number of frames).
# Array properties will be animated when playing the sequence (you can start playing pressing the spacebar).
c1 = Meshes(
cube.vertices,
cube.faces,
name="C1",
position=p1,
color=(0.5, 0, 0, 1),
flat_shading=True,
)
c2 = Meshes(
cube.vertices,
cube.faces,
name="C2",
position=p2 + [3.0, 0.0, 0.0],
rotation=r2,
color=(0.3, 0, 0, 1),
flat_shading=True,
)
c3 = Meshes(
cube.vertices,
cube.faces,
name="C3",
position=p3 + [3.0, 0.0, 0.0],
scale=s3,
color=(0.1, 0.1, 0.1, 1),
flat_shading=True,
)
# Some properties of renderable objects can also be animated, such as the vertices of a mesh.
# Here we create an array of vertices and vertex colors with shape (N, V, 3) and (N, V, 4) respectively.
# Load a simple sphere.
sphere = trimesh.load("resources/planet/planet.obj")
# Create initial and final vertex positions.
vertices_begin = sphere.vertices
vertices_end = sphere.vertices.copy()
for i in range(3):
# Clamp vertices in each 3D direction preserving the sign to create a cube from the sphere.
vertices_begin[:, i] = np.sign(vertices_end[:, i]) * np.minimum(
np.abs(vertices_begin[:, i]), np.full((vertices_begin.shape[0]), 1.7)
)
# Linearly interpolate vertex positions.
vertices = np.linspace(vertices_begin, vertices_end, N)
# Linearly interpolate vertex colors.
vertex_colors_begin = np.tile(np.array([0, 0, 0.5, 1]), (vertices.shape[1], 1))
vertex_colors_end = np.tile(np.array([0, 0.5, 0.0, 1]), (vertices.shape[1], 1))
vertex_colors = np.linspace(vertex_colors_begin, vertex_colors_end, N)
# Create the node with the vertices and colors we computed.
cubesphere = Meshes(
vertices,
sphere.faces,
name="CubeSphere",
position=[-5, 2, 0],
scale=0.5,
vertex_colors=vertex_colors,
flat_shading=True,
)
# Create a viewer.
v = Viewer()
# Set the camera position.
v.scene.camera.position = (0, 10, 20)
# Add the parent object to the scene.
v.scene.add(c1)
# Add the other two cubes as children of the first and second cube respectively creating a hierarchy of 3 nodes.
# The transform (position, rotation and scale) of each node is also applied to all children.
c1.add(c2)
c2.add(c3)
# Add the animated mesh to the scene.
v.scene.add(cubesphere)
v.run()