Monthly Archives: Липень 2015

Пишемо переглядач молекул з Pyglet

Я хотів створити серію уроків про графіку в OpenGL по слідах NeHe, але отримав іншу пропозицію, і пріоритети змінились. Ну й графіка в наш час людей не так цікавить. Але так як задачу я почав робити, просто витирати її з списку проектів буде не цікаво, краще опублікувати те що є і перенести в список закінчених проектів. Чим я зараз й займусь.

Ідея програми – намалювати атоми сферами різних кольорів і розмістити їх в різних місцях простору, таким чином отримавши молекулу. Для цього нам треба знати координати. Для цього ми використаємо Open Babel – хімічну експертну систему. Ось інструкції з інсталяції, apt-get install python-openbabel якщо кому лінь їх читати.

Глюкоза

Молекула глюкози

Користуючись нею, ми можемо перетворити формулу SMILES, на список координат атомів:

import pybel

smile = raw_input('Enter SMILE molecule:')
molecule = pybel.readstring('smi', smile)
molecule.make3D()

for atom in molecule.atoms:
    print atom.type, ' '.join(map(str, atom.coords))

SMILES можна знайти в статтях вікіпедії про різні речовини. Ось наприклад глюкоза: OC[C@H]1OC(O)[C@H](O)[C@@H](O)[C@@H]1O. І її координати:

O3 3.08232699168 1.41136753836 1.97383867659
C3 2.63605783234 0.116724346362 2.37092125466
C3 2.87897272901 -0.854338624684 1.21070216538
H 2.47296741411 -0.36351143938 0.319191621385
O3 4.29331227545 -1.03408976253 1.03052197614
C3 2.18198168708 -2.2062426467 1.4123437219
H 2.52686439483 -2.70828022178 2.32628341407
O3 0.757046712076 -2.07375697965 1.48816465135
C3 2.4834103428 -3.09613160782 0.198042289604
H 2.03158506981 -2.66605342385 -0.704362586236
O3 1.84366255476 -4.36331585678 0.373985237387
C3 3.99532722341 -3.24522583591 0.00523555683618
H 4.41250004827 -3.77444425583 0.871020029013
O3 4.29626886035 -4.03252960027 -1.15195954921
C3 4.62954125722 -1.84273135567 -0.0947112115177
H 5.71887138656 -1.95252927548 -0.108137148969
O3 4.3079363412 -1.18316983652 -1.31789119536
HO 2.91473185309 2.02688340774 2.71060639162
H 1.56956736943 0.19992674022 2.5985040442
H 3.17829013287 -0.18365904297 3.27321534863
HO 0.532102901531 -1.64213847492 2.33074495499
HO 0.907383263524 -4.15051515566 0.55676359202
HO 3.89297302828 -3.59188323274 -1.91963488602
HO 3.3506978517 -1.05986229308 -1.37211748251

Ок, залишилось написати програму що бере оці координати і створює таку картинку як у цій публікації (увага, ввесь код звідси і аж до кінця публікації – це одна програма):

#! /usr/bin/python3
from random import random

import pyglet
from pyglet.window import key, Window
from pyglet.gl import *
from pyglet.gl.glu import *

window = Window()

Об’єкт наступного класу просто буде повертати кортеж з кольором для кожної назви атома. Деякі атоми ми задамо вручну, щодо правильної палітри – дивіться статтю CPK coloring.

class Palette(object):
    def __init__(self):
        self.colors = {
            'H': (0.0, 0.5, 0.5),
            'HO': (1.0, 0.5, 0.5),
            'C3': (0.1, 0.1, 0.1),
            'Car': (0.1, 0.1, 0.1),
            'O3': (1.0, 0.0, 0.0),
        }

    def get_color(self, name):
        if name not in self.colors:
            print(name)
            self.colors[name] = (random(), random(), random())
        return self.colors[name]

palette = Palette()

Молекула – це по суті список атомів (кожен з яких четвірка з назви і трьох координат), що буде завантажувати себе з файлу при створенні екземпляру класу, і вміє малювати себе:

class Molecule(object):
    def __init__(self, fn):
        self.atoms = []
        with open(fn) as f:
            for l in f:
                el, x, y, z = l.split()
                self.atoms.append(
                    (el, float(x), float(y), float(z))
                )

    def draw(self):
        for atom in self.atoms: # для кожного атома
            glPushMatrix() # зберегти матрицю моделі
            glTranslatef(*atom[1:]) # змістити матрицю моделі в координати атома
            # намалювати сферу радіусу 1 і кольору відповідного типу атома
            draw_sphere(1, palette.get_color(atom[0]))
            glPopMatrix() # завантажити збережену матрицю моделі

molecule = Molecule('glucose.dat') # створити молекулу глюкози

def draw_sphere(radius, color):
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    
    # довго пояснювати що таке колір матеріалу, я й сам не до кінця знаю.
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (GLfloat * 3)(*color))
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,
        (GLfloat * 3)(*map(lambda x: x/2, color))
    )
    # glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat * 3)(*color))

    sphere = gluNewQuadric()
    gluSphere(sphere, radius, 50, 50) # 50, 50 - це кількість меридіанів та паралелей. 
    # якщо потрібно багато атомів - зменшіть їх кількість для збільшення продуктивності.

Тепер займемось власне перемальовуванням екрану:

@window.event
def on_draw():
    update_frame(0)

rotation = 0 # Глобальна зміна з поточним поворотом моделі
def update_frame(dt):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity() # завантажити матрицю ідентичності 

    global rotation
    rotation += dt * 10 # чим більше часу пройшло - тим більше повертаємо
    glRotatef(rotation, 0, 1, 0) # навколо осі y
    molecule.draw() # і малюємо нашу молекулу.

При зміні розмірів вікна (і при його створенні) ініціалізуємо всілякі налаштування OpenGL:

@window.event
def on_resize(width, height):
    glClearColor(0.0, 0.3, 0.0, 0.0) # задаємо колір фону

    glEnable(GL_DEPTH_TEST) # вмикаємо буфер глибини

    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glLightf(GL_LIGHT0, GL_POSITION, 1, 5, 4) # ставимо одне світло

    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, width / height, .1, 1000) # перспективна проекція з кутом 45
    gluLookAt( # ставимо камеру і націлюємо її в цент сцени
     1, 4, 15, # eye
     0, 0, 0, # target
     0, 1, 0  # up
    )
    glMatrixMode(GL_MODELVIEW) 
    return pyglet.event.EVENT_HANDLED

При натисканні клавіш “вліво” і “вправо” оновлюємо кадр, повернувши трішки модель. А також оновлюємо 50 разів на секунду. І запускаємо цикл подій:

@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.LEFT:
        update_frame(-1)
    elif symbol == key.RIGHT:
        update_frame(1)

pyglet.clock.schedule_interval(update_frame, 0.02)

pyglet.app.run()

На цьому і все. Можна було звісно написати набагато краще, без глобальних змінних, з кращими поворотами камери і кращим освітленням і т.п. Але поки що є важливіші речі. (Хоча, якщо ви захочете онлайн курс, і зможете зробити так що мені не треба буде ходити на роботу – можемо щось придумати ;) ).

Ах, і стаття з якої взято інформацію про те як отримати координати для атомів молекули: Patrick Fuller – Molecules in Blender


Filed under: Графіка, Кодерство Tagged: освіта, OpenGL, Python

Пишемо переглядач молекул з Pyglet

Я хотів створити серію уроків про графіку в OpenGL по слідах NeHe, але отримав іншу пропозицію, і пріоритети змінились. Ну й графіка в наш час людей не так цікавить. Але так як задачу я почав робити, просто витирати її з списку проектів буде не цікаво, краще опублікувати те що є і перенести в список закінчених проектів. Чим я зараз й займусь.

Ідея програми – намалювати атоми сферами різних кольорів і розмістити їх в різних місцях простору, таким чином отримавши молекулу. Для цього нам треба знати координати. Для цього ми використаємо Open Babel – хімічну експертну систему. Ось інструкції з інсталяції, apt-get install python-openbabel якщо кому лінь їх читати.

Глюкоза

Молекула глюкози

Користуючись нею, ми можемо перетворити формулу SMILES, на список координат атомів:

import pybel

smile = raw_input('Enter SMILE molecule:')
molecule = pybel.readstring('smi', smile)
molecule.make3D()

for atom in molecule.atoms:
    print atom.type, ' '.join(map(str, atom.coords))

SMILES можна знайти в статтях вікіпедії про різні речовини. Ось наприклад глюкоза: OC[C@H]1OC(O)[C@H](O)[C@@H](O)[C@@H]1O. І її координати:

O3 3.08232699168 1.41136753836 1.97383867659
C3 2.63605783234 0.116724346362 2.37092125466
C3 2.87897272901 -0.854338624684 1.21070216538
H 2.47296741411 -0.36351143938 0.319191621385
O3 4.29331227545 -1.03408976253 1.03052197614
C3 2.18198168708 -2.2062426467 1.4123437219
H 2.52686439483 -2.70828022178 2.32628341407
O3 0.757046712076 -2.07375697965 1.48816465135
C3 2.4834103428 -3.09613160782 0.198042289604
H 2.03158506981 -2.66605342385 -0.704362586236
O3 1.84366255476 -4.36331585678 0.373985237387
C3 3.99532722341 -3.24522583591 0.00523555683618
H 4.41250004827 -3.77444425583 0.871020029013
O3 4.29626886035 -4.03252960027 -1.15195954921
C3 4.62954125722 -1.84273135567 -0.0947112115177
H 5.71887138656 -1.95252927548 -0.108137148969
O3 4.3079363412 -1.18316983652 -1.31789119536
HO 2.91473185309 2.02688340774 2.71060639162
H 1.56956736943 0.19992674022 2.5985040442
H 3.17829013287 -0.18365904297 3.27321534863
HO 0.532102901531 -1.64213847492 2.33074495499
HO 0.907383263524 -4.15051515566 0.55676359202
HO 3.89297302828 -3.59188323274 -1.91963488602
HO 3.3506978517 -1.05986229308 -1.37211748251

Ок, залишилось написати програму що бере оці координати і створює таку картинку як у цій публікації (увага, ввесь код звідси і аж до кінця публікації – це одна програма):

#! /usr/bin/python3
from random import random

import pyglet
from pyglet.window import key, Window
from pyglet.gl import *
from pyglet.gl.glu import *

window = Window()

Об’єкт наступного класу просто буде повертати кортеж з кольором для кожної назви атома. Деякі атоми ми задамо вручну, щодо правильної палітри – дивіться статтю CPK coloring.

class Palette(object):
    def __init__(self):
        self.colors = {
            'H': (0.0, 0.5, 0.5),
            'HO': (1.0, 0.5, 0.5),
            'C3': (0.1, 0.1, 0.1),
            'Car': (0.1, 0.1, 0.1),
            'O3': (1.0, 0.0, 0.0),
        }

    def get_color(self, name):
        if name not in self.colors:
            print(name)
            self.colors[name] = (random(), random(), random())
        return self.colors[name]

palette = Palette()

Молекула – це по суті список атомів (кожен з яких четвірка з назви і трьох координат), що буде завантажувати себе з файлу при створенні екземпляру класу, і вміє малювати себе:

class Molecule(object):
    def __init__(self, fn):
        self.atoms = []
        with open(fn) as f:
            for l in f:
                el, x, y, z = l.split()
                self.atoms.append(
                    (el, float(x), float(y), float(z))
                )

    def draw(self):
        for atom in self.atoms: # для кожного атома
            glPushMatrix() # зберегти матрицю моделі
            glTranslatef(*atom[1:]) # змістити матрицю моделі в координати атома
            # намалювати сферу радіусу 1 і кольору відповідного типу атома
            draw_sphere(1, palette.get_color(atom[0]))
            glPopMatrix() # завантажити збережену матрицю моделі

molecule = Molecule('glucose.dat') # створити молекулу глюкози

def draw_sphere(radius, color):
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
    
    # довго пояснювати що таке колір матеріалу, я й сам не до кінця знаю.
    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, (GLfloat * 3)(*color))
    glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION,
        (GLfloat * 3)(*map(lambda x: x/2, color))
    )
    # glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (GLfloat * 3)(*color))

    sphere = gluNewQuadric()
    gluSphere(sphere, radius, 50, 50) # 50, 50 - це кількість меридіанів та паралелей. 
    # якщо потрібно багато атомів - зменшіть їх кількість для збільшення продуктивності.

Тепер займемось власне перемальовуванням екрану:

@window.event
def on_draw():
    update_frame(0)

rotation = 0 # Глобальна зміна з поточним поворотом моделі
def update_frame(dt):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity() # завантажити матрицю ідентичності 

    global rotation
    rotation += dt * 10 # чим більше часу пройшло - тим більше повертаємо
    glRotatef(rotation, 0, 1, 0) # навколо осі y
    molecule.draw() # і малюємо нашу молекулу.

При зміні розмірів вікна (і при його створенні) ініціалізуємо всілякі налаштування OpenGL:

@window.event
def on_resize(width, height):
    glClearColor(0.0, 0.3, 0.0, 0.0) # задаємо колір фону

    glEnable(GL_DEPTH_TEST) # вмикаємо буфер глибини

    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glLightf(GL_LIGHT0, GL_POSITION, 1, 5, 4) # ставимо одне світло

    glViewport(0, 0, width, height)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(45, width / height, .1, 1000) # перспективна проекція з кутом 45
    gluLookAt( # ставимо камеру і націлюємо її в цент сцени
     1, 4, 15, # eye
     0, 0, 0, # target
     0, 1, 0  # up
    )
    glMatrixMode(GL_MODELVIEW) 
    return pyglet.event.EVENT_HANDLED

При натисканні клавіш “вліво” і “вправо” оновлюємо кадр, повернувши трішки модель. А також оновлюємо 50 разів на секунду. І запускаємо цикл подій:

@window.event
def on_key_press(symbol, modifiers):
    if symbol == key.LEFT:
        update_frame(-1)
    elif symbol == key.RIGHT:
        update_frame(1)

pyglet.clock.schedule_interval(update_frame, 0.02)

pyglet.app.run()

На цьому і все. Можна було звісно написати набагато краще, без глобальних змінних, з кращими поворотами камери і кращим освітленням і т.п. Але поки що є важливіші речі. (Хоча, якщо ви захочете онлайн курс, і зможете зробити так що мені не треба буде ходити на роботу – можемо щось придумати ;) ).

Ах, і стаття з якої взято інформацію про те як отримати координати для атомів молекули: Patrick Fuller – Molecules in Blender


Filed under: Графіка, Кодерство Tagged: освіта, OpenGL, Python

Шпаргалка по Docker

Docker в порівнянні з гіпервізором другого типу.

Docker в порівнянні з гіпервізором другого типу.

Докер – штука для керування лінукс-контейнерами. А Лінукс-контейнери – це особливий вид гіпервізора, який дозволяє створювати на лінуксі віртуальні лінукси. Це мінус що тільки лінукси, але плюс що ядро операційної системи для кожного контейнера спільне, тому ці контейнери набагато легші в порівнянні з повноцінними віртуальними машинами.

Віртуальні машини корисні для ізоляції середовища. Наприклад середовища розробки. Хоча цим може займатись і Vagrant. А ще Vagrant може керувати не тільки машинами на VirtualBox, а й контейнерами Docker. Коли що використувати – здається справа особистих вподобань. Хоча мені кажуть що так як контейнери більш легковісні, тут інша філософія роботи, наприклад “кожному процесу свій контейнер”. Ось цікаве обговорення питання що коли варто використовувати, в якому беруть участь автор Vagrant та автор Docker.

Але краще раз попробувати ніж сто разів прочитати:

Інсталяція

На Linux найпростіше, хоч і не безпечно:

wget -qO- https://get.docker.com/ | sh

Запуск контейнера

bunyk@ubuntu:~$ docker run docker/whalesay cowsay boo 
Post http:///var/run/docker.sock/v1.19/containers/create: dial unix 
/var/run/docker.sock: no such file or directory.
Are you trying to connect to a TLS-enabled daemon without TLS?

Якщо бачите таку помилку – значить або докер ще не запущений:

bunyk@ubuntu:~$ sudo service docker start

Або ваш користувач не знаходиться в групі докера:

sudo usermod -aG docker bunyk

Різні інші дії

# скачати образ (щоб він не качався коли ми будемо робити йому run)
docker pull

# список всіх скачаних образів
docker images

# всі запущені контейнери
docker ps

# всі (не лише запущені) контейнери
docker ps -a

# показати лише ідентифікатори контейнерів
docker ps -q

 # видалити всі контейнери
docker rm $(docker ps -aq)

# останній запущений контейнер
docker ps -l

# видалити контейнер
docker rm

# видалити образ
docker rmi

# запустити інтерактивну програму в контейнері
docker run -t -i debian /bin/bash

# запустити демона в контейнері
docker run -d debian /bin/sh -c "while true; do echo hello world; sleep 1; done"

# запустити контейнер так, що директорію хоста /host/dir буде змонтовано як /container/dir
docker run -v /host/dir:/container/dir debian

# слідкувати за логами демона в контейнері
docker logs -f ecstatic_lovelace

# збудувати образ з Dockerfile поточної директорії
docker build -t ouruser/ourrepo .

Filed under: Інструменти, Кодерство Tagged: linux

Шпаргалка по Docker

Docker в порівнянні з гіпервізором другого типу.

Docker в порівнянні з гіпервізором другого типу.

Докер – штука для керування лінукс-контейнерами. А Лінукс-контейнери – це особливий вид гіпервізора, який дозволяє створювати на лінуксі віртуальні лінукси. Це мінус що тільки лінукси, але плюс що ядро операційної системи для кожного контейнера спільне, тому ці контейнери набагато легші в порівнянні з повноцінними віртуальними машинами.

Віртуальні машини корисні для ізоляції середовища. Наприклад середовища розробки. Хоча цим може займатись і Vagrant. А ще Vagrant може керувати не тільки машинами на VirtualBox, а й контейнерами Docker. Коли що використувати – здається справа особистих вподобань. Хоча мені кажуть що так як контейнери більш легковісні, тут інша філософія роботи, наприклад “кожному процесу свій контейнер”. Ось цікаве обговорення питання що коли варто використовувати, в якому беруть участь автор Vagrant та автор Docker.

Але краще раз попробувати ніж сто разів прочитати:

Інсталяція

На Linux найпростіше, хоч і не безпечно:

wget -qO- https://get.docker.com/ | sh

Запуск контейнера

bunyk@ubuntu:~$ docker run docker/whalesay cowsay boo 
Post http:///var/run/docker.sock/v1.19/containers/create: dial unix 
/var/run/docker.sock: no such file or directory.
Are you trying to connect to a TLS-enabled daemon without TLS?

Якщо бачите таку помилку – значить або докер ще не запущений:

bunyk@ubuntu:~$ sudo service docker start

Або ваш користувач не знаходиться в групі докера:

sudo usermod -aG docker bunyk

Різні інші дії

# скачати образ (щоб він не качався коли ми будемо робити йому run)
docker pull

# список всіх скачаних образів
docker images

# всі запущені контейнери
docker ps

# всі (не лише запущені) контейнери
docker ps -a

# показати лише ідентифікатори контейнерів
docker ps -q

 # видалити всі контейнери
docker rm $(docker ps -aq)

# останній запущений контейнер
docker ps -l

# видалити контейнер
docker rm

# видалити образ
docker rmi

# запустити інтерактивну програму в контейнері
docker run -t -i debian /bin/bash

# запустити демона в контейнері
docker run -d debian /bin/sh -c "while true; do echo hello world; sleep 1; done"

# запустити контейнер так, що директорію хоста /host/dir буде змонтовано як /container/dir
docker run -v /host/dir:/container/dir debian

# слідкувати за логами демона в контейнері
docker logs -f ecstatic_lovelace

# збудувати образ з Dockerfile поточної директорії
docker build -t ouruser/ourrepo .

Filed under: Інструменти, Кодерство Tagged: linux

OpenGL в Python

Мене якось запитали про це, але без підготовки пояснити було важко, крім того мета була амбітна – намалювати молекулу, тому вийшло не так добре як би хотілось. Спробую написати короткий покроковий вступ в цю тему, який приблизно слідує послідовності в старих уроках Nehe (так, я чув що вони застаріли, але для нового OpenGL з шейдерами я якихось гарних послідовних уроків не бачив).

Інсталяція та перше вікно

Найперше що потрібно графічним програмам – вікно. Щоб створити вікно, нам треба якусь бібліотеку, наприклад PyQt, PySide, PyGtk, WxPython чи PyGame – їх купа. Потрібно також щоб це вікно підтримувало контекст OpenGL (тобто могло дозволити відеокарті виводити свої дані в область вікна). З цим може справитись багато бібліотек, але ми виберемо Pyglet. Тому що в ній мало зайвого, і вона ставиться традиційно:

pip install pyglet

Ну, і як годиться – почнемо з найпростішої програми:

import pyglet

window = pyglet.window.Window(width=640, height=480, caption="Hello OpenGL!")
pyglet.app.run()

Отримаємо вікно заданої ширини та висоти, і з заданим заголовком:

Наше перше вікно

Наше перше вікно

Елементарно, правда?

Фарби

Давайте ще зафарбуємо вікно в білий колір. Для цього потрібно знати що кольори задаються переважно інтенсивністю світла в моделі RGB (червоний, зелений, голубий), числами від 0 до 1. Тобто білий – це 1.0, 1.0, 1.0, сірий – 0.5, 0.5, 0.5, і т.п. Детальніше на вікіпедії.

import pyglet
from pyglet.gl import * # імпортуємо всі функції OpenGL
# вони починатимуться з префіксів gl або glu, тому простір імен надто не засмічуватимуть

window = pyglet.window.Window(width=640, height=480, caption="Hello OpenGL!")

# я не буду довго пояснювати що таке декоратор. Просто знайте, що 
# @window.event позначає функції що відповідають за обробку подій

@window.event
def on_draw(): 
    # викликатиметься, коли операційна система вирішить що вікно треба перемалювати
    # наприклад, коли ми забрали вікно що було над нашим, або вперше виводимо його на екран  

    glClearColor(1.0, 1.0, 1.0, 1.0) # Задати колір яким ми будемо очищати екран. 
    # Четверте число - прозорість.
    # Я його сам не дуже розумію, але обов’язково треба чотири параметри.

    glClear(GL_COLOR_BUFFER_BIT) # очистити буфер кольору 
    # (бувають і інші буфери, але про це пізніше)

pyglet.app.run()

To be continued

В цьому уроці я хотів ще написати про те як намалювати трикутник, але часу мало (тобто є інші пріорітети). Зате ми створили вікно і навчились змінювати його колір. Ну й краще напевне писати менше але частіше. Якщо пілотний епізод цього курсу буде популярний – подумаю чи випускати перший сезон.

P.S. Май на увазі, якщо ти не хочеш навчити свою дівчину програмувати – вона може знайти когось хто схоче. :P Або взагалі сама з допомогою інтернету звикне вчитись.


Filed under: Графіка, Кодерство Tagged: OpenGL, Python

OpenGL в Python

Мене якось запитали про це, але без підготовки пояснити було важко, крім того мета була амбітна – намалювати молекулу, тому вийшло не так добре як би хотілось. Спробую написати короткий покроковий вступ в цю тему, який приблизно слідує послідовності в старих уроках Nehe (так, я чув що вони застаріли, але для нового OpenGL з шейдерами я якихось гарних послідовних уроків не бачив).

Інсталяція та перше вікно

Найперше що потрібно графічним програмам – вікно. Щоб створити вікно, нам треба якусь бібліотеку, наприклад PyQt, PySide, PyGtk, WxPython чи PyGame – їх купа. Потрібно також щоб це вікно підтримувало контекст OpenGL (тобто могло дозволити відеокарті виводити свої дані в область вікна). З цим може справитись багато бібліотек, але ми виберемо Pyglet. Тому що в ній мало зайвого, і вона ставиться традиційно:

pip install pyglet

Ну, і як годиться – почнемо з найпростішої програми:

import pyglet

window = pyglet.window.Window(width=640, height=480, caption="Hello OpenGL!")
pyglet.app.run()

Отримаємо вікно заданої ширини та висоти, і з заданим заголовком:

Наше перше вікно

Наше перше вікно

Елементарно, правда?

Фарби

Давайте ще зафарбуємо вікно в білий колір. Для цього потрібно знати що кольори задаються переважно інтенсивністю світла в моделі RGB (червоний, зелений, голубий), числами від 0 до 1. Тобто білий – це 1.0, 1.0, 1.0, сірий – 0.5, 0.5, 0.5, і т.п. Детальніше на вікіпедії.

import pyglet
from pyglet.gl import * # імпортуємо всі функції OpenGL
# вони починатимуться з префіксів gl або glu, тому простір імен надто не засмічуватимуть

window = pyglet.window.Window(width=640, height=480, caption="Hello OpenGL!")

# я не буду довго пояснювати що таке декоратор. Просто знайте, що 
# @window.event позначає функції що відповідають за обробку подій

@window.event
def on_draw(): 
    # викликатиметься, коли операційна система вирішить що вікно треба перемалювати
    # наприклад, коли ми забрали вікно що було над нашим, або вперше виводимо його на екран  

    glClearColor(1.0, 1.0, 1.0, 1.0) # Задати колір яким ми будемо очищати екран. 
    # Четверте число - прозорість.
    # Я його сам не дуже розумію, але обов’язково треба чотири параметри.

    glClear(GL_COLOR_BUFFER_BIT) # очистити буфер кольору 
    # (бувають і інші буфери, але про це пізніше)

pyglet.app.run()

To be continued

В цьому уроці я хотів ще написати про те як намалювати трикутник, але часу мало (тобто є інші пріорітети). Зате ми створили вікно і навчились змінювати його колір. Ну й краще напевне писати менше але частіше. Якщо пілотний епізод цього курсу буде популярний – подумаю чи випускати перший сезон.

P.S. Май на увазі, якщо ти не хочеш навчити свою дівчину програмувати – вона може знайти когось хто схоче. :P Або взагалі сама з допомогою інтернету звикне вчитись.


Filed under: Графіка, Кодерство Tagged: OpenGL, Python