Creating transformsΒΆ
There are 4 basic transform nodes: Translate, Scale, Rotate and Skew. It is also possible to create custom transform with the Transform node (by passing down a 4x4 matrix). They can be used to transform the vertices of the shapes below in the graph.
Rotate a quad by 45Β°
![](transforms.rotate.png)
import pynopegl as ngl
@ngl.scene()
def rotate(cfg: ngl.SceneCfg):
cfg.aspect_ratio = (1, 1)
scene = ngl.DrawColor(geometry=ngl.Quad())
return ngl.Rotate(scene, angle=45)
![graph](transforms.rotate_graph.png)
Rotate a quad by 360Β° over the course of 3 seconds
import pynopegl as ngl
@ngl.scene()
def animated_rotate(cfg: ngl.SceneCfg):
cfg.aspect_ratio = (1, 1)
cfg.duration = 3
animkf = [
ngl.AnimKeyFrameFloat(0, 0),
ngl.AnimKeyFrameFloat(cfg.duration, 360),
]
scene = ngl.DrawColor(geometry=ngl.Quad())
return ngl.Rotate(scene, angle=ngl.AnimatedFloat(animkf))
![graph](transforms.animated_rotate_graph.png)
Translate a circle from one side to another, and back
import pynopegl as ngl
@ngl.scene()
def animated_translate(cfg: ngl.SceneCfg):
cfg.aspect_ratio = (1, 1)
cfg.duration = 3
animkf = [
ngl.AnimKeyFrameVec3(0, (-1 / 3, 0, 0)),
ngl.AnimKeyFrameVec3(cfg.duration / 2, (1 / 3, 0, 0)),
ngl.AnimKeyFrameVec3(cfg.duration, (-1 / 3, 0, 0)),
]
scene = ngl.DrawColor(geometry=ngl.Circle(0.5))
return ngl.Translate(scene, vector=ngl.AnimatedVec3(animkf))
![graph](transforms.animated_translate_graph.png)
Scale up and down a circle
import pynopegl as ngl
@ngl.scene()
def animated_scale(cfg: ngl.SceneCfg):
cfg.aspect_ratio = (1, 1)
cfg.duration = 3
animkf = [
ngl.AnimKeyFrameVec3(0, (1 / 3, 1 / 3, 1 / 3)),
ngl.AnimKeyFrameVec3(cfg.duration / 2, (3 / 4, 3 / 4, 3 / 4)),
ngl.AnimKeyFrameVec3(cfg.duration, (1 / 3, 1 / 3, 1 / 3)),
]
scene = ngl.DrawColor(geometry=ngl.Circle(0.5))
return ngl.Scale(scene, factors=ngl.AnimatedVec3(animkf))
![graph](transforms.animated_scale_graph.png)
To combine transforms, they have to be chained. The following example combines 3
of them: Scale(Translate(Rotate(...)))
:
A chain of animated transforms
import pynopegl as ngl
@ngl.scene()
def chained_transforms(cfg: ngl.SceneCfg):
cfg.duration = 5
cfg.aspect_ratio = (1, 1)
group = ngl.Group()
radius = 0.2
n = 10
step = 360 / n
shape = ngl.Circle(radius=radius, npoints=128)
draw = ngl.DrawColor(geometry=shape)
for i in range(n):
mid_time = cfg.duration / 2.0
start_time = mid_time / (i + 2)
end_time = cfg.duration - start_time
scale_animkf = [
ngl.AnimKeyFrameVec3(start_time, (0, 0, 0)),
ngl.AnimKeyFrameVec3(mid_time, (1, 1, 1), "exp_out"),
ngl.AnimKeyFrameVec3(end_time, (0, 0, 0), "exp_in"),
]
angle = i * step
rotate_animkf = [
ngl.AnimKeyFrameFloat(start_time, 0),
ngl.AnimKeyFrameFloat(mid_time, angle, "exp_out"),
ngl.AnimKeyFrameFloat(end_time, 0, "exp_in"),
]
tnode = draw
tnode = ngl.Scale(tnode, factors=ngl.AnimatedVec3(scale_animkf))
tnode = ngl.Translate(tnode, vector=(1 - radius, 0, 0))
tnode = ngl.Rotate(tnode, angle=ngl.AnimatedFloat(rotate_animkf))
group.add_children(tnode)
return group
![graph](transforms.chained_transforms_graph.png)