Archive for the Programming Category

Using ARRAY_BUFFER’s in PyOpenGL

Posted in How To, Programming, PyGLy with tags , , , , on 2013/02/16 by Adam Griffiths

I’m in the process of converting my code from Pyglet GL to PyOpenGL.
In doing so, my VBO objects stopped rendering.

It turns out the problem is glVertexAttribPointer.
The Pyglet GL version takes the last parameter (offset) as a number. I set this to 0 for arrays with no offset.

glVertexAttribPointer( in_position, 3, GL_FLOAT, GL_FALSE, 0, 0)

It seems that PyOpenGL expects the pointer value by absolute instead of relative.
The solution is to pass None instead of 0.

glVertexAttribPointer( in_position, 3, GL_FLOAT, GL_FALSE, 0, None)

If you have an actual offset to pass, you need to convert to a ctypes c_void_p (void*).
http://stackoverflow.com/questions/11132716/how-to-specify-buffer-offset-with-pyopengl

glVertexAttribPointer( in_position, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(offset))

Rotating a vector by a quaternion in GLSL

Posted in How To, Programming with tags , , , , on 2013/02/11 by Adam Griffiths

I’ve found numerous code samples which produce erroneous results in my shaders.

The functions I’ve found to work are the following:


vec4 multQuat(vec4 q1, vec4 q2)
{
return vec4(
q1.w * q2.x + q1.x * q2.w + q1.z * q2.y - q1.y * q2.z,
q1.w * q2.y + q1.y * q2.w + q1.x * q2.z - q1.z * q2.x,
q1.w * q2.z + q1.z * q2.w + q1.y * q2.x - q1.x * q2.y,
q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z
);
}

vec3 rotate_vector( vec4 quat, vec3 vec )
{
vec4 qv = multQuat( quat, vec4(vec, 0.0) );
return multQuat( qv, vec4(-quat.x, -quat.y, -quat.z, quat.w) ).xyz;
}

Source from here: http://www.opengl.org/discussion_boards/showthread.php/166386-Quaternions-and-hardware-skinning

And this version which is optimised:


vec3 rotate_vector( vec4 quat, vec3 vec )
{
return vec + 2.0 * cross( cross( vec, quat.xyz ) + quat.w * vec, quat.xyz );
}

Using gl_VertexID without any VBOs.

Posted in How To, Programming with tags , , , on 2013/02/03 by Adam Griffiths

Normally, gl_VertexID is the index of the currently rendered vertex element.

When you provide indices (GL_ELEMENT_ARRAY_BUFFER), gl_VertexID should match the value provided. Ie, the gl_VertexID value can repeat if you render the same element multiple times.

 

I say “should”, because this is NOT correct when you haven’t provided any VBO data.

This means, that if you are rendering using nothing but a shader and a GL_ELEMENT_ARRAY_BUFFER, the gl_VertexID will NOT match the indices you provide, and will instead be a sequence from 0 -> N.

The solution is to use a single VBO and use glDrawArrays.

 

Personally, I consider this a bug.

Getting Cocos 1.x / Kobold2D to work with the latest CocosBuilder

Posted in Development, How To, Programming, Rant with tags , , , , , on 2012/03/30 by Adam Griffiths

CocosBuilder is a brilliant tool that helps you rapidly develop Cocos2D applications.

But the latest versions require the Cocos 2.x branch.

Some of us are stuck with Cocos 1.x for the time being. So let’s figure out how to get things going.

Continue reading

Adventures in Kivy

Posted in How To, Programming, Rant with tags , , , , , , on 2012/03/22 by Adam Griffiths

So here is a semi-live blog as I delve into Kivy.

Mission #1: Attempt to resize the default window

Ok let’s start at the start.

We first create an object that inherits from App. Done.

Ok, and the examples all return a widget from the App’s build() method. So we don’t over-ride __init__… ok… thats… unique.

Perhaps the widget is the window if it is returned from the build() method?

Widget is not the window. Widget returned from build() is added to the window. So… where is the window created?

Window docs state the window has a constructor that lets you set the window size. Ok, cool. But we don’t create the window… so.. we can’t use the constructor… sigh.

Ok, Window has a static accessor.

kivy.core.window.Window = None

No comment on what is stored here but I assume it’s the instantiated window. It doesn’t mention when it is set… handy!

Only 1 window allowed. Ok… weird. Well… let’s try that.

import kivy.core.window.Window
AttributeError: 'module' object has no attribute 'window'

Awesome…

Let’s scour the code.

Screen capture of Kivy window module

No Window.py file……… how far does this rabbit hole go.

Ok, let’s check out the __init__.py file in the window module.

class WindowBase(EventDispatcher):
 '''WindowBase is a abstract window widget, for any window implementation.

So… window base is in there. Feel free to scream now.

So we can get this by importing kivy.core.window and just leaving the class off the end.

import kivy.core.window
...
def build(self):
    print kivy.core.window.Window.size
    return None
(800, 600)

Ok sweet, thats our window.

So let’s change its size.

def build(self):
    print kivy.core.window.Window.size
    kivy.core.window.Window.size = (1024, 768)
    print kivy.core.window.Window.size
    return None
File "/Users/adamgriffiths/Workspace/VirtualEnvs/progress_quest/lib/python2.7/site-packages/kivy/core/window/__init__.py", line 243, in _set_size
 if super(WindowBase, self)._set_size(size):
 AttributeError: 'super' object has no attribute '_set_size'

FFFFFFFUUUUUUUUUUU

Ok, so after some googling we find this post about the relationship between the App and Window classes.

His solution is to pass the size as a command line parameter……….. LAME. That kinda throws the whole configuration settings thing out the window.

Looking through the Kivy code we find this block inside their base window class’ __init__ method.

if 'fullscreen' not in kwargs:
    fullscreen = Config.get('graphics', 'fullscreen')
        if fullscreen not in ('auto', 'fake'):
        fullscreen = fullscreen.lower() in ('true', '1', 'yes', 'yup')
    kwargs['fullscreen'] = fullscreen
if 'width' not in kwargs:
    kwargs['width'] = Config.getint('graphics', 'width')
if 'height' not in kwargs:
    kwargs['height'] = Config.getint('graphics', 'height')

Ok, so we can try and set it via the global config object.

So let’s add that to our App class.

def build_config(self, config):
    config.adddefaultsection('graphics')
    config.setdefault('graphics', 'width', 1024)
    config.setdefault('graphics', 'height', 768)
    config.set('graphics', 'height', 1024)
    config.set('graphics', 'width', 768)

Run the code and……

(800, 600)

……. sigh

So let’s put some debug INSIDE kivy and see what is happening. We’ll also force it to pull the ‘graphics’ setting and ignore kwargs.

if True: #'width' not in kwargs:
    kwargs['width'] = Config.getint('graphics', 'width')
print kwargs['width']
if True: #'height' not in kwargs:
    kwargs['height'] = Config.getint('graphics', 'height')
print kwargs['height']

And the output…

800
600

…. calm blue ocean…. calm blue ocean….

Ok… google…

Hmm.. ok, this post on the kivy-users forum (because documentation is for lusers) shows a similar method.

They use the Config module directly instead of the config object passed to App….. because….. they’re not the same? Well.. let’s try it anyway.

from kivy.config import Config
Config.set('graphics', 'width', 1024)
Config.set('graphics', 'height', 768)

And our output

(800, 600)

Ok, weird because the window HAS ACTUALLY CHANGED SIZE.

Whatever. We’re all living in crazy-ville atm so let’s just pretend everything is normal.

So let’s move that inside our build_config() method.

def build_config(self, config):
    Config.set('graphics', 'height', 1024)
    Config.set('graphics', 'width', 768)

And the output

[INFO ] Kivy v1.1.1
[INFO ] [Logger ] Record log in /Users/adamgriffiths/.kivy/logs/kivy_12-03-22_40.txt
[INFO ] [Factory ] 102 symbols loaded
[INFO ] [Text ] using <pygame> as text provider
[INFO ] [Loader ] using <pygame> as thread loader
[INFO ] [Window ] using <pygame> as window provider
[WARNING] [Window ] Unable to use <pygame> as windowprovider
[CRITICAL] [Window ] Unable to find any valuable Window provider at all!
Fatal Python error: (pygame parachute) Segmentation Fault
Abort trap: 6

(╯°□°)╯︵ ┻━┻

Installing Kivy on OS-X from PIP and Homebrew

Posted in How To, Programming with tags , , , , , on 2012/03/19 by Adam Griffiths

Begin by following this guide to get your python environment setup.

If you aren’t using virtualenv, then feel free to ignore those commands (mkvirtalenv, cdvirtualenv).

Remember to run ‘brew’ commands as the current user and not root.

Install SDL

brew install sdl sdl_image sdl_mixer sdl_ttf smpeg portmidi

Install Mercurial to gain access to PyGame repository.

brew install mercurial

Create a virtual environment to work in

mkvirtualenv kivy
cdvirtualenv

Install our Kivy dependencies and then finally, Kivy itself.

pip install cython
pip install pil
pip install hg+http://bitbucket.org/pygame/pygame</pre>
pip install kivy

If you don’t install PIL or PyGame, you will get errors such as this

(kivy-test)Vibur:kivy-test adamgriffiths$ python src/main.py 
[INFO   ] Kivy v1.1.1
[INFO   ] [Logger      ] Record log in /Users/adamgriffiths/.kivy/logs/kivy_12-03-19_4.txt
[INFO   ] [Factory     ] 102 symbols loaded
[WARNING] [Image       ] Unable to use <pygame> as loader!
[WARNING] [Image       ] Unable to use <pil> as loader!
[WARNING] [Text        ] Unable to use <pygame> as textprovider
[WARNING] [Text        ] Associated module are missing
[WARNING] [Text        ] Unable to use <pil> as textprovider
[WARNING] [Text        ] Associated module are missing
[CRITICAL] [Text        ] Unable to find any valuable Text provider at all!
 Traceback (most recent call last):
   File "src/main.py", line 2, in <module>
     from kivy.uix.button import Button
   File "/Users/adamgriffiths/Workspace/VirtualEnvs/kivy-test/lib/python2.7/site-packages/kivy/uix/button.py", line 38, in <module>
     from kivy.uix.label import Label
   File "/Users/adamgriffiths/Workspace/VirtualEnvs/kivy-test/lib/python2.7/site-packages/kivy/uix/label.py", line 94, in <module>
     from kivy.core.text import Label as CoreLabel
   File "/Users/adamgriffiths/Workspace/VirtualEnvs/kivy-test/lib/python2.7/site-packages/kivy/core/text/__init__.py", line 520, in <module>
     Label.register('DroidSans',
 AttributeError: 'NoneType' object has no attribute 'register'

Installing Virtualenv and Pythonbrew on OS-X

Posted in How To, Programming with tags , , , on 2012/03/19 by Adam Griffiths

This post will help you get Pythonbrew and Virtualenv installed on OS-X. Two important libraries for Python development.

  • Pythonbrew lets you install multiple python installations without affecting your system’s Python install.
  • Virtualenv lets you set up isolated python installations and modules for each project.

Begin by installing Pythonbrew

# install pythonbrew locally
# do NOT install to your system python directory
curl -kL http://xrl.us/pythonbrewinstall | bash

Install your desired Python versions

# get a list of available python versions
python list -k

# install desired python
# force the install as python fails some tests at the moment
# https://twistedpairdevelopment.wordpress.com/2012/01/16/installing-python-with-pythonbrew-on-mac-os-x
pythonbrew install <VERSION>
pythonbrew use

# should print out
python --version

# virtualenvwrapper must be installed for each python version
pip install virtualenvwrapper

You can install virtualenv and virtualenvwrapper into the system Python, or into your newly installed python.

# install into system python
# do this if you plan to use the system python as default
sudo pip install virtualenv
sudo pip install virtualenvwrapper

You can install virtualenv and virtualenvwrapper into the system Python, or into your newly installed python.

# install into pythonbrew installed python
# do this if you want to over-ride the default python installation
pythonbrew switch <VERSION>
pip install virtualenv
pip install virtualenvwrapper

Add support for Pythonbrew to bash by adding the following to the end of your ~/.bashrc

Follow this guide if you want to make your .bashrc modular.

#-------------------------------------------------------------
# Python definitions
#-------------------------------------------------------------

# Pythonbrew
# add pythonbrew support
if [[ -s $HOME/.pythonbrew/etc/bashrc ]]; then
source $HOME/.pythonbrew/etc/bashrc
fi

Add virtualenvwrapper support to ~/.bashrc


#-------------------------------------------------------------
# Python definitions
#-------------------------------------------------------------

# Virtualenvwrapper
# virtualenv wrapper support
export WORKON_HOME=~/Workspace/VirtualEnvs

if [[ -s /usr/local/bin/virtualenvwrapper.sh ]]; then
source /usr/local/bin/virtualenvwrapper.sh
fi

# PIP
# tell pip to only install inside virtualenvs
export PIP_REQUIRE_VIRTUALENV=true

# make pip use the virtualenv dir
export PIP_VIRTUALENV_BASE=$WORKON_HOME

# add pip bash completion
# use eval to avoid the error "Could not find an activated virtualenv (required)."
eval `pip completion --bash`

Close the terminal and re-open it to reload your .bashrc.

When creating Virtualenv environments, virtualenv will use the currently set Python install.

If you wish to use a Python install other than the current system install, run the following command before running mkvirtualenv.


pythonbrew use <VERSION>

Note: I’ve found that virtualenvwrapper has stopped obeying this. To force virtualenvwrapper to install a specific version, do the following.

pythonbrew use <VERSION>
MY_PYTHON="$(command which python)"
mkvirtualenv -p $MY_PYTHON <NAME>

Some basic Virtualenvwrapper commands:

  • mkvirtualenv PROJECTNAME – create a new virtualenv project.
  • workon PROJECTNAME – enter the virtualenv for the project.
  • deactivate – stop working on the current virtualenv project.
  • cdvirtualenv – change to the directory of the current virtualenv project.

If you need to add environment variables to your project, edit the ‘bin/postactivate’ file inside the virtualenv directory. This file is executed when the ‘workon’ command is run and can be used to add more paths to $PYTHONHOME and other useful commands.

%d bloggers like this: