Animation¶
-
class
taichi_glsl.gui.
Animation
(img=None, circles=None, title='Animation', res=(512, 512), **kwargs)¶ Bases:
taichi_glsl.odop.DataOriented
Handy Shadertoy-alike GUI base class.
I’m able to:
Enable you to focus on computation, no need to hand-write a GUI event loop.
Easy-to-use image / video export wrapper like
self.set_output_video(path)
.Shadertoy-alike input variables including
self.iMouse
,self.iKeyDirection
.Callback style event processing system incuding
self.on_click(x, y)
.Easily port to Jupyter notebook by simply
self.gui_backend = 'ipython'
.
See examples/export_video.py for example:
import taichi as ti import taichi_glsl as ts ti.init() class MyAnimation(ts.Animation): def on_init(self): self.img = ti.Vector.field(3, ti.f32, (512, 512)) self.set_output_video('/tmp/video.gif') self.define_input() @ti.kernel def on_render(self): for I in ti.grouped(self.img): uv = I / self.iResolution self.img[I] = ti.cos(uv.xyx + self.iTime + ts.vec(0, 2, 4)) * 0.5 + 0.5 MyAnimation().start()
And what’s more, examples/particles.py:
import taichi as ti import taichi_glsl as ts ti.init() class MyAnimation(ts.Animation): def on_init(self): self.N = 8192 self.dt = 0.01 self.pos = ti.Vector.field(2, ti.f32, self.N) self.vel = ti.Vector.field(2, ti.f32, self.N) self.circles = self.pos # alias to make ts.Animation know self.attract_strength = ti.field(ti.f32, ()) self.attract_pos = ti.Vector.field(2, ti.f32, ()) self.resolution = (512, 512) self.title = 'Particles' self.define_input() @ti.kernel def on_start(self): for i in self.pos: self.pos[i] = ts.randND(2) self.vel[i] = ts.randSolid2D() @ti.kernel def on_advance(self): for i in self.pos: acc = ts.vec(0.0, -1.0) if any(self.iKeyDirection): # ASWD? acc = self.iKeyDirection if any(self.iMouseButton): dir = ts.normalize(self.iMouse - self.pos[i]) * 2 if self.iMouseButton[0]: # LMB pressed? acc += dir if self.iMouseButton[1]: # RMB pressed? acc -= dir self.vel[i] += acc * self.dt for i in self.pos: self.vel[i] = ts.boundReflect(self.pos[i], self.vel[i], 0, 1, 0.8) for i in self.pos: self.pos[i] += self.vel[i] * self.dt MyAnimation().start()
Attributes Summary
(PS, int, RO) Get current frame number start from 0.
(TS, int32, RO) Current frame number start from 0.
(TS, 2D float32 vector, RO) Direction according to ASWD / arrow keys.
(TS, 2D float32 vector, RO) Current mouse position from 0 to 1.
(TS, 3D int32 vector, RO) Current mouse button status.
(TS, 2D int32 vector, RO) Window size / screen resolution.
(TS, float32, RO) Current time in seconds.
(PS, tuple of two float, RO) Get mouse position / cursor coordinate from 0 to 1.
(PS, tuple of two int, RW) Get or set window size / screen resolution.
(PS, float32, RO) Get current time in seconds.
Methods Summary
Should be called if you wish to use
self.iXXX
as uniform scalars.Called to advance / step the physics scene.
on_click
(x, y, btn)on_clicking
(x, y, btn)on_close
()on_drag
(x, y)on_event
(e)Called when a event occurred, hook me if you want a raw event control.
on_exit
()on_hover
(x, y)on_init
()Called when initializing
Animation()
.on_not_clicking
(x, y)Called per GUI main loop.
on_press
(key)on_pressing
(key)on_release
(key)Called to render the displayed image.
on_show
()on_start
()Called when GUI main loop started, i.e.
on_unclick
(x, y, btn)on_wheel
(x, y, dx, dy)set_output_video
(path[, framerate])Export frames painted in GUI to a video.
start
()Call me when GUI is ready to start shows up.
Attributes Documentation
-
frame
¶ (PS, int, RO) Get current frame number start from 0.
-
iFrame
¶ (TS, int32, RO) Current frame number start from 0.
-
iKeyDirection
¶ (TS, 2D float32 vector, RO) Direction according to ASWD / arrow keys.
If A or left arrow is pressed, then
self.iKeyDirection
isvec(-1.0, 0.0)
. If D or right arrow is pressed, thenself.iKeyDirection
isvec(1.0, 0.0)
. If W or up arrow is pressed, thenself.iKeyDirection
isvec(0.0, 1.0)
. If S or down arrow is pressed, thenself.iKeyDirection
isvec(0.0, -1.0)
.
-
iMouse
¶ (TS, 2D float32 vector, RO) Current mouse position from 0 to 1.
-
iMouseButton
¶ (TS, 3D int32 vector, RO) Current mouse button status.
self.iMouseButton[0]
is1
if LMB is pressed.self.iMouseButton[1]
is1
if MMB is pressed.self.iMouseButton[2]
is1
if RMB is pressed. Otherwise,0
.
-
iResolution
¶ (TS, 2D int32 vector, RO) Window size / screen resolution.
-
iTime
¶ (TS, float32, RO) Current time in seconds.
-
mouse
¶ (PS, tuple of two float, RO) Get mouse position / cursor coordinate from 0 to 1.
-
resolution
¶ (PS, tuple of two int, RW) Get or set window size / screen resolution.
-
time
¶ (PS, float32, RO) Get current time in seconds.
Methods Documentation
-
define_input
()¶ Should be called if you wish to use
self.iXXX
as uniform scalars.If you are familiar with Shadertoy, then this is for you :)
-
on_advance
()¶ Called to advance / step the physics scene.
I.e. update
self.circles
if you’re using it.
-
on_click
(x, y, btn)¶
-
on_clicking
(x, y, btn)¶
-
on_close
()¶
-
on_drag
(x, y)¶
-
on_escape
()¶
-
on_event
(e)¶ Called when a event occurred, hook me if you want a raw event control.
-
on_exit
()¶
-
on_hover
(x, y)¶
-
on_init
()¶ Called when initializing
Animation()
.Set up self.* properties for application usage here:
Property
Type
Default
Description
img
np.array
None
Image to display.
circles
np.array
None
Circles to paint.
circle_radius
scalar
1
Radius of circles.
circle_color
RGB hex
0x000000
Color of circles.
background_color
RGB hex
0x000000
background color of window.
title
string
"Animation"
Title of the window.
screenshot_dir
string
None
Path to save screenshots.
resolution
tuple
img.shape
The size of window / screen.
auto_clean
boolean
False
Zero the image before render.
colormap
MPL CMap
None
matplotlib.cm
color map.gui_backend
string
native
native, matplotlib, or none
-
on_not_clicking
(x, y)¶
-
on_not_pressing
()¶
-
on_post_render
()¶
-
on_pre_event
()¶ Called per GUI main loop.
-
on_pre_exit
()¶
-
on_pre_render
()¶
-
on_press
(key)¶
-
on_pressing
(key)¶
-
on_release
(key)¶
-
on_render
()¶ Called to render the displayed image.
I.e. update
self.img
if it’s used.
-
on_show
()¶
-
on_start
()¶ Called when GUI main loop started, i.e.
Animation().start()
.
-
on_unclick
(x, y, btn)¶
-
on_update_input
()¶
-
on_wheel
(x, y, dx, dy)¶
-
set_output_video
(path, framerate=24)¶ Export frames painted in GUI to a video.
FIXME: Only work for
self.img
render, doesn’t work forself.circles
for now. Useself.screenshot_dir = '/tmp'
, thencd /tmp && ti video
if you wish to.
-
start
()¶ Call me when GUI is ready to start shows up.
A common usage for application can be:
MyAnimation().start()
.