/dev/blah

things i want to remember, things i want to share

Développeur Python et adepte Linux depuis 2005, Core développeur Kivy, passionné par beaucoup trop de choses.
Profil Github gpg signature bitcoin address

Entries tagged “deformation”

Kivy image manipulations with Mesh and Textures

written by tshirtman, on 1/29/14 1:05 AM.

If you want to give a little life to interactive (or not) elements, it’s always nice to have more tricks to manipulate images for nifty effects.

One of such ways is mapping a Texture on a special canvas instruction, that will distort your texture based on the position of its points.

[kivy.graphics.Mesh](http://kivy.org/docs/api-kivy.graphics.html#kivy.graphics.Mesh) is such an instruction, and it has a simple interface, if not 100% straightforward, you basically call it this way.

Mesh:
vertices: (x1, y1, s1, v1, x2, y2, s2, v2, x3, y3, s3, v3...)
indices: (1, 2, 3...)
texture: some_texture
mode: some_mode

where all: x mean the horizontal coordinate of a point y mean the vertical coordinate of a point s mean the horizontal position of the texture attached to this point (between 0 and 1) v mean the vertical position of the texture attached to this point (between 0 and 1)

indices is useful if, for some (very good) reason, you don’t want to give the points in the order you’ll use them, or if you want to refer to a point multiple time (this won’t be demonstrated in this blog post, but try to think about a grid mapping, for example), now we will use it in the most simple way, just give the range of your number of points.

the texture needs to be a texture object, you can get such an object by getting the texture property of a [CoreImage](http://kivy.org/docs/api-kivy.core.image.html#kivy.core.image.Image) or an Image (or even a Label, if you want to).

Let’s say we have an image, for example, kivy logo.

from kivy.core.image import Image as CoreImage

texture = CoreImage('data/logo/kivy-icon-512.png').texture

(this will work wherever you are, because kivy look at his images anyway :))

This image is a circle, lets use that to cut it into a virtual pie and assign a part of the texture to each part, we’ll be using the triangle_fan mode of Mesh, that is a perfect fit for such an operation.

# the central point
points = [Window.width / 2, Window.height / 2, .5, .5]

# now go around
    i = 0
    while i < 2 * pi:
        i += 0.01 * pi
        points.extend([
    Window.width / 2 + cos(i) * 100,
    Window.height / 2 + sin(i) * 100,
    .5 + sin(i),
    .5 + cos(i)])

put that in a more complete program, and you get this:

from kivy.app import App
from kivy.lang import Builder
from kivy.core.image import Image as CoreImage
from kivy.properties import ListProperty, ObjectProperty
from kivy.clock import Clock
from kivy.core.window import Window
from math import sin, cos, pi


kv = '''
Widget:
    canvas:
        Color:
            rgba: 1, 1, 1, 1
        Mesh:
            vertices: app.mesh_points
            indices: range(len(app.mesh_points) / 4)
            texture: app.mesh_texture
            mode: 'triangle_fan'
'''


class MeshBallApp(App):
    mesh_points = ListProperty([])
    mesh_texture = ObjectProperty(None)

    def build(self):
        self.mesh_texture = CoreImage('data/logo/kivy-icon-512.png').texture
        Clock.schedule_interval(self.update_points, 0)
        return Builder.load_string(kv)

    def update_points(self, *args):
        points = [Window.width / 2, Window.height / 2, .5, .5]
        i = 0
        while i < 2 * pi:
            i += 0.01 * pi
            points.extend([
                Window.width / 2 + cos(i) * 100,
                Window.height / 2 + sin(i) * 100,
                .5 + cos(i),
                .5 + sin(i)])

        self.mesh_points = points

if __name__ == '__main__':
    MeshBallApp().run()

Now, this is not very impressive, we just have an image, there were much simpler ways to do that!

But now, we can tweek the rendering a lot, lets add some offseting of the texture, some radius change, and some wobbling, with sliders to control all this.

from kivy.app import App
from kivy.lang import Builder
from kivy.core.image import Image as CoreImage
from kivy.properties import ListProperty, ObjectProperty, NumericProperty
from kivy.clock import Clock
from kivy.core.window import Window
from math import sin, cos, pi


kv = '''
BoxLayout:
    Widget:
        canvas:
            Color:
                rgba: 1, 1, 1, 1
            Mesh:
                vertices: app.mesh_points
                indices: range(len(app.mesh_points) / 4)
                texture: app.mesh_texture
                mode: 'triangle_fan'
    BoxLayout:
        orientation: 'vertical'
        size_hint_x: None
        width: 100
        Slider:
            value: app.offset_x
            on_value: app.offset_x = args[1]
            min: -1
            max: 1
        Slider:
            value: app.offset_y
            on_value: app.offset_y = args[1]
            min: -1
            max: 1
        Slider:
            value: app.radius
            on_value: app.radius = args[1]
            min: 10
            max: 1000
        Slider:
            value: app.sin_wobble
            on_value: app.sin_wobble = args[1]
            min: -50
            max: 50
        Slider:
            value: app.sin_wobble_speed
            on_value: app.sin_wobble_speed = args[1]
            min: 0
            max: 50
            step: 1
'''


class MeshBallApp(App):
    mesh_points = ListProperty([])
    mesh_texture = ObjectProperty(None)
    radius = NumericProperty(500)
    offset_x = NumericProperty(.5)
    offset_y = NumericProperty(.5)
    sin_wobble = NumericProperty(0)
    sin_wobble_speed = NumericProperty(0)

    def build(self):
        self.mesh_texture = CoreImage('data/logo/kivy-icon-512.png').texture
        Clock.schedule_interval(self.update_points, 0)
        return Builder.load_string(kv)

    def update_points(self, *args):
        points = [Window.width / 2, Window.height / 2, .5, .5]
        i = 0
        while i < 2 * pi:
            i += 0.01 * pi
            points.extend([
                Window.width / 2 + cos(i) * (self.radius + self.sin_wobble * sin(i * self.sin_wobble_speed)),
                Window.height / 2 + sin(i) * (self.radius + self.sin_wobble * sin(i * self.sin_wobble_speed)),
                self.offset_x + sin(i),
                self.offset_y + cos(i)])

        self.mesh_points = points

if __name__ == '__main__':
    MeshBallApp().run()

which gives us:

Kivy image manipulations with Mesh and Text

Now we are talking!

Tip me if you like this :)

Tags

#FIXME 3G absurd ad_sense alterway aléatoire android animation anonymity atheism bach backlog bash bitcoins blog blogging boldness book books boulot bricolage bépo C canvas captcha captures carte SD censure christianity chroot CLI cli cloudwatt code colors comfort zone command line community company life conferences contest copwatch copwatchnord-idf core-devs cours ct705 culture deb debian debug deformation dehors dessin dev distribute distribution débutant déploiement développement ebooks eeepad eeepc effect ego empty en escher event firefly flappy bird flask fosdem foss fr fun game garden gdb geek culture git github goals graphics grrr gödel hack hackathon hacked hacking health hooks i3 images IMAP inspirational install isync java jeu jeu video jinja2 jni keyboard keynav kivy kv lame learning lib libre life linux lol macosx magnet mail mailing-list mails maths mbsync meetings memory leak mesh meta mint mirroir MIT module motivational mouse museomix mutt nexus7 no-mouse notmuch nottoomuch offlineimap onycroit opencourseware osc packaging paris passphrase password patch pentacatyl people perte de données ping pip planning plugin positioning pr procrastination programmation progress project projet property proudhon proxy psf publisher/consumer pull-down pygame pyjnius pypi python pythonar qtile raid rapsberry pi reading recorder references release religion responsive review reviews réseau réseaux sociaux résurection salon screenshots script self service shows shutil shyness sizing solib sortie sousous!!! spam spritz stash status systeme système templating terminal texture texture coordinates Thomas Paine thread thème tiling time time management. tip tips tools transformer tutorial tv twitter typematrix typing ubuntu ubuntu-fr ultimate-smash-friends unity update upload images useless usf utils value VDM video vie/mort vim virtualenv visite widget windows wm wmii work workflow workflow. zine études