Part 1: Drawing with PyOpenGL using moden openGL buffers.

This is part 1 of a series and it is about getting started with visualizing triangle meshes with Python 2.7 using the libraries PyOpenGL and PyQt41.

Part 1
Part 2
Part 3

I will assume you know python, you will not need a lot of Qt or OpenGL experience, though I will also not go into the deeper details of how OpenGL works. For that I refer you to official documentation and the excellent (C++) tutorials at https://open.gl/. Although they are C++, there is a lot of explanation about OpenGL and why to do certain calls in a certain order.

On a final note: I will make generalizations and simplifications when explaining things. If you think something works different then I say it probably does, this is to try and convey ideas to beginners, not to explain low level openGL implementations.

Part 1: Drawing a mesh using buffers.

1.1. Setting up

Download & run Python with default settings:
https://www.python.org/ftp/python/2.7.12/python-2.7.12.amd64.msi

Download & run PyQt4 with default settings:
https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.11.4/PyQt4-4.11.4-gpl-Py2.7-Qt4.8.7-x64.exe/download

Paste the following in a windows command window (windows key + R -> type “cmd.exe” -> hit enter):
C:/Python27/Scripts/pip install setuptools
C:/Python27/Scripts/pip install PyOpenGL

1.2. Creating an OpenGL enabled window in Qt.

The first thing to know about OpenGL is that any operation requires OpenGL to be initialized. OpenGL is not something you just “import”, it has to be attached to a (possibly hidden) window. This means that any file loading or global initialization has to be postponed until OpenGL is available.

The second thing to know about OpenGL is that it is a big state machine. Any setting you change is left until you manually set it back. This means in Python we may want to create some contexts (using contextlib) to manage the safe setting and unsetting of certain states. I will however not go this far.

Similar to this Qt also requires prior initialization. So here’s some relevant code:

# import the necessary modules
from PyQt4.QtCore import * # QTimer
from PyQt4.QtGui import * # QApplication
from PyQt4.QtOpenGL import * # QGLWidget
from OpenGL.GL import * # OpenGL functionality
from OpenGL.GL import shaders # Utilities to compile shaders, we may not actually use this

# this is the basic window
class OpenGLView(QGLWidget):
def initializeGL(self):
# here openGL is initialized and we can do our real program initialization
pass

def resizeGL(self, width, height):
# openGL remembers how many pixels it should draw,
# so every resize we have to tell it what the new window size is it is supposed
# to be drawing for
pass

def paintGL(self):
# here we can start drawing, on show and on resize the window will redraw
# automatically
pass

# this initializes Qt
app = QApplication([])
# this creates the openGL window, but it isn't initialized yet
window = OpenGLView()
# this only schedules the window to be shown on the next Qt update
window.show()
# this starts the Qt main update loop, it avoids python from continuing beyond this
# line and any Qt stuff we did above is now going to actually get executed, along with
# any future events like mouse clicks and window resizes
app.exec_()

Running this should get you a black window that is OpenGL enabled. So let’s fill in the view class to draw something in real-time. This will show you how to make your window update at 60-fps-ish, how to set a background color and how to handle resizes.

class OpenGLView(QGLWidget):
    def initializeGL(self):
        # set the RGBA values of the background
        glClearColor(0.1, 0.2, 0.3, 1.0)
        # set a timer to redraw every 1/60th of a second
        self.__timer = QTimer()
        self.__timer.timeout.connect(self.repaint) # make it repaint when triggered
        self.__timer.start(1000 / 60) # make it trigger every 1000/60 milliseconds
   
    def resizeGL(self, width, height):
        # this tells openGL how many pixels it should be drawing into
        glViewport(0, 0, width, height)
   
    def paintGL(self):
        # empty the screen, setting only the background color
        # the depth_buffer_bit also clears the Z-buffer, which is used to make sure
        # objects that are behind other objects actually are not shown drawing 
        # a faraway object later than a nearby object naively implies that it will 
        # just fill in the pixels with itself, but if there is already an object there 
        # the depth buffer will handle checking if it is closer or not automatically
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        # the openGL window has coordinates from (-1,-1) to (1,1), so this fills in 
        # the top right corner with a rectangle. The default color is white.
        glRecti(0, 0, 1, 1)

Note that the QTimer forces the screen to redraw, but because we are not animating any data this will not be visible right now.

1.3. Creating a Vertex Array Object (VAO)

In OpenGL there is a lot we can put into a mesh, not only positions of vertices, but also triangulation patterns, vertex colors, texture coordinates, normals etcetera. Because OpenGL is a state machine (as described at the start of 2.) this means that when drawing 2 different models a lot of settings need to be swapped before we can draw it. This is why the VAO was created, as it is a way to group settings together and be able to draw a mesh (once set up properly) in only 2 calls. It is not less code, but it allows us to move more code to the initialization stage, winning performance and reducing risk of errors resulting in easier debugging.

Our mesh however will not be very complicated. We require 2 sets of data, the vertex positions and the triangulation (3 integers per triangle pointing to what vertex to use for this triangle).
Untitled
As you can see this would result in the following data:
Positions = [0, 0, 1, 0, 0, 1, 1, 1]
Elements = [0, 1, 2, 1, 3, 2]
4 2D vertices and 2 triangles made of 3 indices each.

So let’s give this data to a VAO at the bottom of initializeGL.

# generate a model
# set up the data
positions = (0, 0, 1, 0, 0, 1, 1, 1)
elements = (0, 1, 2, 1, 3, 2)
# apply the data
# generate a vertex array object so we can easily draw the resulting mesh later
self.__vao = glGenVertexArrays(1)
# enable the vertex array before doing anything else, so anything we do is captured in the VAO context
glBindVertexArray(self.__vao)
# generate 2 buffers, 1 for positions, 1 for elements. this is memory on the GPU that our model will be saved in.
bufs = glGenBuffers(2)
# set the first buffer for the main vertex data, that GL_ARRAY_BUFFER indicates that use case
glBindBuffer(GL_ARRAY_BUFFER, bufs[0])
# upload the position data to the GPU
# some info about the arguments:
# GL_ARRAY_BUFFER: this is the buffer we are uploading into, that is why we first had to bind the created buffer, else we'd be uploading to nothing
# sizeof(ctypes.c_float) * len(positions): openGL wants our data as raw C pointer, and for that it needs to know the size in bytes.
# the ctypes module helps us figure out the size in bytes of a single number, then we just multiply that by the array length
# (ctypes.c_float * len(positions))(*positions): this is a way to convert a python list or tuple to a ctypes array of the right data type
# internally this makes that data the right binary format
# GL_STATIC_DRAW: in OpenGL you can specify what you will be doing with this buffer, static means draw it a lot but never access or alter the data once uploaded.
# I suggest changing this only when hitting performance issues at a time you are doing way more complicated things. In general usage static is the fastest.
glBufferData(GL_ARRAY_BUFFER, sizeof(ctypes.c_float) * len(positions), (ctypes.c_float * len(positions))(*positions), GL_STATIC_DRAW)
# set the second buffer for the triangulation data, GL_ELEMENT_ARRAY_BUFFER indicates the use here
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufs[1])
# upload the triangulation data
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ctypes.c_uint) * len(elements), (ctypes.c_uint * len(elements))(*elements), GL_STATIC_DRAW)
# because the data is now on the GPU, our python positions & elements can be safely garbage collected hereafter
# turn on the position attribute so OpenGL starts using our array buffer to read vertex positions from
glEnableVertexAttribArray(0)
# set the dimensions of the position attribute, so it consumes 2 floats at a time (default is 4)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, None)

So that was quite some code, and it is quite simple because we only have positions to deal with right now. But first let’s try to draw it!
Replace the glRecti call with:

# enable the vertex array we initialized, it will bind the right buffers in the background again
glBindVertexArray(self.__vao)
# draw triangles based on the active GL_ELEMENT_ARRAY_BUFFER
# that 6 is the element count, we can save the len(elements) in initializeGL in the future
# that None is because openGL allows us to supply an offset for what element to start drawing at
# (we could only draw the second triangle by offsetting by 3 indices for example)
# problem is that the data type for this must be None or ctypes.c_void_p.
# In many C++ example you will see just "0" being passed in
# but in PyOpenGL this doesn't work and will result in nothing being drawn.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, None)

Now we should have an identical picture. Some more info about glVertexAttribPointer:

In OpenGL we can upload as many buffers as we want, but for now I’ll stick with the 2 we have. This means that if we want to (for example) add colors to our mesh, we have to set up multiple attrib pointers, that both point to different parts of the buffer. I like to keep all my vertex data concatenated, so that we could get (x,y,r,g,b,x,y,r,g,b…) etcetera in our buffer.

Now for OpenGL to render it not only wants to know what buffer to look at (the array_buffer), but it also wants to know how to interpret that data, and what data is provided. OpenGL understand this through attribute locations. Here we activate attribute location 0 (with glEnableVertexAttribArray) and then set our buffer to be 2 floats per vertex at attribute location 0.

The default openGL attribute locations are as follows:
0: position
1: tangent
2: normal
3: color
4: uv

To support multiple attributes in a single buffer we have to use the last 2 arguments of glVertexAttribPointer. The first of those is the size of all data per vertex, so imagine a 2D position and an RGB color that would be 5 * sizeof(float). The second of those is where this attribute location starts. Here’s an example to set up position and color:

vertex_data = (0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1) ##
vertex_element_size = 5 ##
elements = (0, 1, 2, 1, 3, 2)
self.__vao = glGenVertexArrays(1)
glBindVertexArray(self.__vao)
bufs = glGenBuffers(2)
glBindBuffer(GL_ARRAY_BUFFER, bufs[0])
glBufferData(GL_ARRAY_BUFFER, sizeof(ctypes.c_float) * len(vertex_data), (ctypes.c_float * len(vertex_data))(*vertex_data), GL_STATIC_DRAW) ##
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufs[1])
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ctypes.c_uint) * len(elements), (ctypes.c_uint * len(elements))(*elements), GL_STATIC_DRAW)
glEnableVertexAttribArray(3) ##
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(ctypes.c_float) * vertex_element_size, ctypes.c_void_p(2 * sizeof(ctypes.c_float))) ##
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(ctypes.c_float) * vertex_element_size, None) ##

This is an update to initializeGL, new / changed code ends in ## (because I don’t know how to override the syntax highlighting), and your rectangle will immediately start showing colors2!

One last thing. add this to the top of paintGL:

import time
glLoadIdentity()
glScalef(self.height() / float(self.width()), 1.0, 1.0)
glRotate((time.time() % 36.0) * 10, 0, 0, 1)

The first line (after the import) restores the transform state, the second line corrects aspect ratio (so a square is really square now), the last line rotates over time. We are using a startup time because Python’s time is a too large value, by subtracting the application start time from it we get a value OpenGL can actually work with.

That’s it for part 1!

1PyQt5, PySide, PySide2 are (apart from some class renames) also compatible with this.

2The color attribute binding only works on NVidia, there is no official default attribute location and most other drivers will ignore glVertexAttribPointer (or do something random) if you do not use a custom shader. So if you’re not seeing colors, don’t worry and try diving into shaders later!

Simple C++ Snippets

These are some simple Win32 C++ snippets I often find myself coming back to when I want to mess around with something. Instead of spending a long time setting up a good environment with strong libraries available I quite often want “just a window” to start doing stuff with. That in itself is much easier than you may often find described online.

So be warned, ugly code ahead!

Part 1, windows and GL context
A C++ program to display a static window; you can’t do anything with it though, it does not process events.

#include <windows.h>
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd = CreateWindow("edit", NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    while(true);
    return 0;
}

We can add event processing, but this is more involved. So let’s split that up. First we need to define a custom window “class” or type that describes mostly which callback this kind of window should use.

HWND CustomWindow(const char* name, HINSTANCE hInstance, WNDPROC callback)
{
    WNDCLASSEX WndClsEx = { 0 };
    WndClsEx.cbSize = sizeof(WNDCLASSEX);
    WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
    WndClsEx.lpfnWndProc = callback;
    WndClsEx.lpszClassName = name;
    WndClsEx.hInstance = hInstance;
    RegisterClassEx(&WndClsEx);

    return CreateWindow(name, name, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
}

We initialize to 0 for safety. The window class can also get default icons, cursors, colors etc. but those can also be changed with Win32 functions later on, so I tend not to bother with them here.

When having many types of windows I tend to use OOP, with only one custom window type, and have an std::map to go from HWND to wrapped instance.then I just call soemthing like WindowBaseClass::instances.find(hWnd)->Update();.

The above function expects a callback argument, this is a function pointer adhering to the Win32 callback. A very basic one allows the user to use ALT+F4 and the close button to end the program completely. Note that this is not something you wish to do in a multi window application; in which case you probably should check for the number of windows before quitting.

LRESULT CALLBACK CustomWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(WM_QUIT);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}

Now let’s do a proper event loop which will defer message to the custom window proc and exit as required by the quit message.

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd = CustomWindow("UI", hInstance, CustomWindowProc);
    MSG msg;
    do
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if(msg.message == WM_QUIT)
            {
                return msg.wParam;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    } while(true);
    return msg.wParam;
}

The thing I do the most is extend a window into an openGL context to start rendering in openGL, ignoring any actual Win32 stuff and just testing some graphics thing. This function enriches a created window with an openGL context and returns it’s handle.

HDC GLWindow(HWND hWnd)
{
    /// Creates & "makes current" (activates) an OpenGL target inside the given window
    HDC hDC = GetDC(hWnd);
    const PIXELFORMATDESCRIPTOR pfd = { 0, 0, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd);
    wglMakeCurrent(hDC, wglCreateContext(hDC));
    return hDC;
}

The simple example we started with can become this instead:

#include <windows.h>
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    HWND hWnd = CreateWindow("edit", NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    HDC hDC = GLWindow(hWnd);
    glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
    do
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glColor3f(1.0f, 0.9f, 0.8f);
        glRecti(-1, -1, 1, 1);
        SwapBuffers(hDC);
    } while(true);
    return 0;
}

OpenGL has a default viewport with the (-1, -1) coordinate at the bottom left and (1, 1) at the top right. A useful thing is to shift this to have (0, 0) at the bottom left and the window (width, height) at the top right. Sometimes we want to flip it vertically to start e.g. drawing text from the top.

/// Mirror mode bitmask
enum class Mirror 
{
    None = 0b00,
    Horizontal = 0b01,
    Vertical = 0b10,
    Both = Horizontal | Vertical,
};
/// Operators for the bit mask
Mirror operator&(Mirror lhs, Mirror rhs){ return (Mirror)((int)lhs & (int)rhs); }
void GLPixelSpace(HWND hWnd, Mirror flip = Mirror::None)
{
	/// Make viewport coordinates match pixel coordinates; requires a "Current" GL context (wglMakeCurrent, as initialized for us by GLWindow).
	float x = ((flip & Mirror::Horizontal) == Mirror::Horizontal) ? 1.0f : -1.0f;
	float y = ((flip & Mirror::Vertical) == Mirror::Vertical) ? 1.0f : -1.0f;
	glTranslatef(x, y, 0.0f);
	// Get the window's draw-able area
	RECT area;
	GetClientRect(hWnd, &area);
	// Compute scale so 1 pixel matches 1 unit.
	x = ((flip & Mirror::Horizontal) == Mirror::Horizontal) ? -2.0f : 2.0f;
	y = ((flip & Mirror::Vertical) == Mirror::Vertical) ? -2.0f : 2.0f;
	glScalef(x / (area.right - area.left), y / (area.bottom - area.top), 1.0f);
}

Call this once before entering the drawing loop to have it as default, or use

glPushMatrix();
glLoadIdentity();
GLPixelSpace(hWnd);
// Pixel-space drawing code here
glPopMatrix();

Update: FontStash is awesome!
Not long after I wrote this post I switched to use FontStash.

Here’s a minimal example using some of the functions defined above.

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	HWND hWnd = CreateWindow("edit", NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW, 100, 100, 800, 600, NULL, NULL, hInstance, NULL);
	HDC hDC = GLWindow(hWnd);
	GLPixelSpace(hWnd, Mirror::Vertical);
	
	FONScontext* fs = glfonsCreate(512, 512, FONS_ZERO_TOPLEFT);
	int fontNormal = fonsAddFont(fs, "sans", "C:/Windows/Fonts/Calibri.ttf");
	
	glClearColor(0.3f, 0.3f, 0.32f, 1.0f);
	
	unsigned int yellow = glfonsRGBA(255, 180, 70, 255);
	fonsClearState(fs);
	fonsSetFont(fs, fontNormal);
	fonsSetColor(fs, yellow);

	do
	{
		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		
		glDisable(GL_DEPTH_TEST);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		
		fonsSetSize(fs, 48);
		float y = 0;
		fonsSetAlign(fs, FONS_ALIGN_LEFT | FONS_ALIGN_TOP);
		fonsDrawText(fs, 4, y, "The quick brown",NULL);
		y += 48;
		fonsSetSize(fs, 24);
		fonsDrawText(fs, 4, y, "fox jumped over the lazy dog",NULL);
		
		fonsDrawDebug(fs, 800.0, 50.0);

		glEnable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);
		SwapBuffers(hDC);
	}
	while(!GetAsyncKeyState(VK_ESCAPE));

	glfonsDelete(fs);

	return 0;
}
Part 2, openGL fonts using FTGL & FreeType2
A related thing is font rendering. There are tons of options, I’m going to reference the openGL font survey about that.

I just want to supply a TTF file I already have with my application and use that inside of it. I want a flexible system that is fast, can batch, does not flood my memory too greedily when rendering various sizes and has good kerning with font-metrics capabilities.

GLX which seems linux only.
GLC which is Adobe Type 1 fonts only, seems fairly old, has issues with rotating fonts & aliasing.
GLUT’s default font renderer, which is not friendly to introducing new fonts.
GLTT which seems the first decent flexible library.
FTGL which seems GLTT 2.0 using the more modern FreeType 2.0 library (instead of 1.0).
WGL which I tried and flickered and it is in general hard to customize appearance / do anti-aliasing.
GLF is last and seems just as fine as GLTT, be it also outdated with it’s own font file format which as no tools or documentation.

Texture mapping fonts is also not an option for on the fly text display as we are limited to predefined texture atlasses for specific glyphs of specific sizes, which is a lot of manual labour; though I would probably recommend it for a game, combined with BMFont it’s pretty powerful and fast to render large amounts of static (even 3D) text in a single draw call, with minimal memory usage if the atlas is a distance field as well as described here.

So with that out of the way, imagine a rant about the poor distribution of binaries for both FreeType and FTGL. I was happy to discover both these projects (on sourceforge) had a project setup for a ton of build environments on various platforms with various toolsets. It was very easy to copy the vc2008 project, open it in vs2012, auto-upgrade and change the output paths to match a new vs2012 target directory.

I have attached compiled lib and dll binaries from both FTGL and FreeType compiled on windows 7 using visual studio 2012 update 4.

ftgl-2.1.3-rc5__with__freetype-2.6__binaries

Here is a header for intelligently loading windows, openGL and FTGL in the right order, including the required libraries as we go. All you need to do in your project settings is set up the additional include and additional library directories if you’re placing these files elsewhere.

// settings.h
#pragma once


#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
#include <windows.h>


#pragma comment(lib, "opengl32.lib")
#include <gl/gl.h>


#define FTGL_LIBRARY_STATIC
#ifdef NDEBUG
#pragma comment(lib, "freetype26")
#ifdef FTGL_LIBRARY_STATIC
#pragma comment(lib, "ftgl_static")
#else
#pragma comment(lib, "ftgl")
#endif
#else
#pragma comment(lib, "freetype26d")
#ifdef FTGL_LIBRARY_STATIC
#pragma comment(lib, "ftgl_static_D")
#else
#pragma comment(lib, "ftgl_D")
#endif
#endif
#include <FTGL/ftgl.h>

Here is a full code sample that has a simple or a custom window (#define SIMPLE) which uses the above file to render a rect and a piece of text in a win32 window using openGl.

/*
References

http://www.functionx.com/win32/Lesson01c.htm
For window with custom class setup

http://sizecoding.blogspot.nl/2007/10/tiny-opengl-windowing-code.html
For basic wglContext setup

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644943(v=vs.85).aspx
For buffer swaps between messages

http://ftgl.sourceforge.net/docs/html/ftgl-tutorial.html
For basic font creation

http://stackoverflow.com/questions/28151464/how-to-change-color-in-rgb-format-in-ftgl-opengl
For requiring FTGLUseTextureFont to have glColor work as expected.

http://stackoverflow.com/questions/28313786/undefined-symbol-in-static-library-but-exists-when-in-same-vs-solution
For knowing to define FTGL_LIBRARY_STATIC

https://www.opengl.org/archives/resources/features/fontsurvey/
For the font options which showed FTGL as my preferred option.
*/


#include "settings.h"


// #define SIMPLE


HWND Window(HINSTANCE hInstance)
{
    /// Creates an arbitrary default window
    return CreateWindow("edit", NULL, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
}


LRESULT CALLBACK CustomWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
    case WM_DESTROY:
        PostQuitMessage(WM_QUIT);
        break;
    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    return 0;
}


HWND CustomWindow(const char* name, HINSTANCE hInstance, WNDPROC callback)
{
    WNDCLASSEX WndClsEx = { 0 };
    WndClsEx.cbSize = sizeof(WNDCLASSEX);
    WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
    WndClsEx.lpfnWndProc = callback;
    // WndClsEx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    // WndClsEx.hCursor = LoadCursor(NULL, IDC_ARROW);
    // WndClsEx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    WndClsEx.lpszClassName = name;
    WndClsEx.hInstance = hInstance;
    // WndClsEx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&WndClsEx);

    return CreateWindow(name, name, WS_VISIBLE | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
}


HDC GLWindow(HWND hWnd)
{
    /// Creates & "makes current" (activates) an OpenGL target inside the given window
    HDC hDC = GetDC(hWnd);
    static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0 };
    SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd);
    wglMakeCurrent(hDC, wglCreateContext(hDC));
    return hDC;
}


void GLPixelSpace(HWND hWnd)
{
    /// Make viewport coordinates match pixel coordinates; requires a "Current" GL context (wglMakeCurrent, as initialized for us by GLWindow).
    glTranslatef(-1.0f, -1.0f, 0.0f);
    // Get the window's draw-able area
    RECT area;
    GetClientRect(hWnd, &area);
    // Compute scale so 1 pixel matches 1 unit.
    glScalef(2.0f / (area.right - area.left), 2.0f / (area.bottom - area.top), 1.0f);
}


void GLPixelSpace_FlipY(HWND hWnd)
{
    /// Make viewport coordinates match pixel coordinates; requires a "Current" GL context (wglMakeCurrent, as initialized for us by GLWindow).
    glTranslatef(-1.0f, 1.0f, 0.0f);
    // Get the window's draw-able area
    RECT area;
    GetClientRect(hWnd, &area);
    // Compute scale so 1 pixel matches 1 unit.
    glScalef(2.0f / (area.right - area.left), -2.0f / (area.bottom - area.top), -1.0f);
}


void Draw(FTGLTextureFont& font)
{
    // Draw background
    glClear(GL_COLOR_BUFFER_BIT);

    // Draw foreground
    // Set foreground color
    glColor3f(1.0f, 0.9f, 0.8f);
    glRecti(0, 0, 200, 100);
    // Set foreground color
    glColor3f(0.2f, 0.3f, 0.4f);
    font.Render("Hello World!");
}


int ExecSimple(HDC hDC)
{
    /// Simple render loop
    FTGLTextureFont font("C:/Windows/Fonts/Roboto-Light.ttf");
    font.FaceSize(32);
    do
    {
        Draw(font);
        SwapBuffers(hDC);
    } while(true);
    return 0;
}


int Exec(HDC hDC)
{
    /// Render loop with windows messages
    FTGLTextureFont font("C:/Windows/Fonts/Roboto-Light.ttf");
    font.FaceSize(32);
    MSG msg;
    do
    {
        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if(msg.message == WM_QUIT)
            {
                return msg.wParam;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        Draw(font);
        SwapBuffers(hDC);
    } while(true);
    return msg.wParam;
}


INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
#ifdef SIMPLE
    HWND hWnd = Window(hInstance);
    HDC hDC = GLWindow(hWnd);
    GLPixelSpace(hWnd);
    glClearColor(0.1f, 0.2f, 0.3f, 1.0f); // Set background color
    return ExecSimple(hDC);
#else
    HWND hWnd = CustomWindow("UI", hInstance, CustomWindowProc);
    HDC hDC = GLWindow(hWnd);
    GLPixelSpace(hWnd);
    glClearColor(0.1f, 0.2f, 0.3f, 1.0f); // Set background color
    return Exec(hDC);
#endif
}

Maya plugin factory

These are 2 utilities I mostly want to use in other projects myself and now they’re easier to find.

Utility to check the variable ‘stat’ and raise & return if something’s wrong. I always have 1 MStatus running through a function and it’s always named ‘stat’… The raised exception prints the file and line number as well!

utils.hpp

#ifndef UTILS_HPP


#define THROWSTAT if(stat != MS::kSuccess){ stat.perror(MString(__FILE__) + " line " + __LINE__); return stat; }
#define THROWSTATMSG(MSG) if(stat != MS::kSuccess){ stat.perror(MString(__FILE__) + " line " + __LINE__ + ": " + MSG); return stat; }


#define UTILS_HPP
#endif

This is the plugin factory. It registers the plugin with “Unknown” as author, you may wish to change that… There’s three interesting bits here.

First is the inclusion of MFnPlugin. Normally you can’t include this file twice because things get defined causing multiple defined objects and linking errors. With these defines the plugin will be safely included and all we get is access to the MFnPlugin class, which is all we need and great and safe!

Next there’s the initializePlugin function. Here you can use the macros to register nodes and commands.
> REGISTERNODE registers a node by the class name. Depending on whether you want maya nodes and functions with capital letters or not you’ll have to drop the common C++ style of classes start with a capital.

And the third interesting bit is, all the rest is automated. No uninitialize, no struggling with ids, all that stuff. The only bit you might want to change is the base value of __id. It is the first ID and any new node will increment the ID by 1. I don’t know much about where to find which ids are actually guaranteed to be free so this is just kind of random.

main.cpp

#include <vector>

#undef NT_PLUGIN
#define MNoVersionString
#include <maya/MFnPlugin.h>
#undef MNoVersionString
#define NT_PLUGIN


#include "utils.hpp"


int __id = 0x00208600;
std::vector<int> ids;
int id()
{
	ids.push_back(__id);
	return __id++;
}

std::vector<MString> cmds;


#define REGISTERNODE(NODE) stat = plugin.registerNode(#NODE, id(), NODE::sCreator, NODE::sInitialize); THROWSTATMSG("RegisterNode failed, is the TypeID already in use?")
#define REGISTERNODETYPE(NODE, TYPE) stat = plugin.registerNode(#NODE, id(), NODE::sCreator, NODE::sInitialize, TYPE); THROWSTAT
#define REGISTERCOMMAND(COMMAND) cmds.push_back(#COMMAND); stat = plugin.registerCommand(#COMMAND, COMMAND::sCreator, COMMAND::sNewSyntax); THROWSTAT


MStatus initializePlugin(MObject& pluginObj)
{
	MFnPlugin plugin(pluginObj, "Uknown", "1.0", "any");
	MStatus stat;
	
	REGISTERNODE(MyNode);
	REGISTERNODETYPE(MyShape, MPxNode::kLocatorNode);
	REGISTERCOMMAND(MyFunction);

	return stat;
}


MStatus uninitializePlugin(MObject& pluginObj)
{
	MFnPlugin plugin(pluginObj);
	MStatus stat;
	for(size_t i = ids.size() - 1; i >= 0; --i)
	{
		stat = plugin.deregisterNode(ids[i]); THROWSTAT
	}
	for(size_t i = cmds.size() - 1; i >= 0; --i)
	{
		stat = plugin.deregisterCommand(cmds[i]); THROWSTAT
	}
	return stat;
}

So yes, this may make your registering plugins life easier. Was messing about with automating other things as well, such as getting and setting plugs, but I feel that got a bit wonky in the end. May be continued…

Natural IK Chain

So RiggingDojo.com shared this video series from Yutaca Sawai:

I decided to test it, and quickly made a script to generate a chain of n-segments
Essentially the left chain is the important one (bold in the video) and the rest are just a construct to propagate a single rotation to a full fletched motion.

Open Maya, run this Python script, see for yourself how one rotation and a bunch of parented joints & ikhandles can generate complex motion!

def joint(x,y,z):
    jt = cmds.joint()
    cmds.xform(jt, t=[x,y,z], ws=True)
    return cmds.ls(jt, l=True)[0]
    
def ikHandle(start, end):
    sl = cmds.ls(sl=True)
    cmds.select(start, end)
    ikh = cmds.ikHandle()[0]
    cmds.select(sl)
    return ikh

def constructBase(cycles = 10):
    cmds.select(cl=True)
    rotator = joint(1,0,0)
    
    #demonstrative animation
    cmds.currentTime(0)
    cmds.setKeyframe('%s.rz'%rotator)
    cmds.currentTime(60)
    cmds.setAttr('%s.rz'%rotator, 360)
    cmds.setKeyframe('%s.rz'%rotator)
    cmds.playbackOptions(min=0, max=60)
    
    root = joint(0,1,0)
    chain2root = joint(-2,-1,0)
    cmds.select(root)
    joint(-2,-1,0)
    anchor = joint(0,-3,0)
    cmds.group(ikHandle(root, anchor)) #group to make the ik handle fixed in place
    
    #chain 1
    cmds.select(anchor)
    ikGroups1 = []
    parents1 = []
    for i in range(cycles):
        ikGroups1.append([joint(2,-1 - i * 8,0)])
        joint(2,-5 - i * 8,0)
        ikGroups1[-1].append(joint(-2,-5 - i * 8,0))
        parents1.append(joint(-2,-9 - i * 8,0))

    #chain 2
    cmds.select(chain2root)
    ikGroups2 = []
    parents2 = []
    for i in range(cycles):
        parents2.append(joint(-2,-5 - i * 8,0))
        ikGroups2.append([joint(2,-5 - i * 8,0)])
        joint(2,-9 - i * 8,0)
        ikGroups2[-1].append(joint(-2,-9 - i * 8,0))
    for i in range(len(ikGroups2)):
        cmds.parent(ikHandle(*ikGroups2[i]), parents1[i])
        
    for i in range(len(ikGroups1)):
        cmds.parent(ikHandle(*ikGroups1[i]), parents2[i])


constructBase()

Classes & Javascript relations

Javascript uses objects for everything, these objects are based on prototypes, their definitions, which are also objects.

You can create an object and extend its prototype,
then instantiate this object to get an instance of this prototype. Just like any class definition & instance you can then have the instance operate independently of the prototype.

classes
So the first thing is the class definition, in javascript, this is a function. You give a function your class name and any member variables & default values can be set inside this function.

function BaseClass()
{
    this.a = 'b';
}

Now to instantiate the class, much like C# syntax, you do the following:

var myObject = new BaseClass();

‘myObject’ will now have an ‘a’ property, with a value of ‘b’.

functions
To add functions we must extend the prototype:

function BaseClass()
{
    this.a = 'b'
}
BaseClass.prototype.log = function()
{
    console.log(this.a);
}

And similarly, to have this function use the console (a global variable most browsers provide for debugging) print our ‘a’ value we can simply use this:

var myObject = new BaseClass();
myObject.log();

static properties
Private static properties can be local variables inbetween the prototype functions, public static properties can be added to the class object instead of its prototype. Contrary to other languages these properties can not be accessed using the this. object at all and the private properties are just a hack by placing variables in a temporary scope so when later on dynamically altering the prototype these variables are still not acessible.

public statics

BaseClass.staticLogSomething = function()
{
    console.log('something');
}

private statics
These are often wrapped in a surrounding function like so (notice the return!):

var BaseClass = function()
{
    var privateStatic = 0;
    function BaseClass()
    {
        this.a = 'b'
    }
    BaseClass.prototype.log = function()
    {
        console.log(this.a);
    }
    BaseClass.staticLogSomething = function()
    {
        console.log(privateStatic);
        privateStatic += 1;
    }
    return BaseClass;
}();

subclassing
Subclassing actually means creating a new class and then extending its prototype with the base class prototype so we share its functions and even know its constructor.

Then inside the constructor function we can use the base class constructor to inherit all initialized member variables. The hacky statics as described above won’t transfer because they are members of the base class definition object, which is a level above the prototype (which is the bit we inherit).

function SubClass()
{
    BaseClass.call(this);
}
SubClass.prototype = Object.create(BaseClass.prototype);

That’s all there is to it. Now we can extend this function by adding properties, overriding properties, etcetera. This second subclass overrides the ‘a’ and ‘log’ properties and adds a ‘b’ property which is also logged.

function SubClass2()
{
    BaseClass.call(this);
    this.a = 'c';
    this.b = 'd';
}

SubClass2.prototype = Object.create(BaseClass.prototype);

SubClass2.prototype.log = function()
{
    console.log(this.a);
    console.log(this.b);
}

Now this is some test code, putting these three classes together you can clearly see the functionality:

var a = new SubClass();
a.log();
var c = new SubClass();
c.log(); // to prove the sub class has the base class data & functions
var d = new SubClass2();
d.log(); // to prove the sub class can override this data
console.log(d.a); // to prove things are accessable and 'c' == 'this' inside its functions
d.a = 'f';
console.log(d.a); // to prove we can alter values
var e = new SubClass2();
console.log(e.a); // to prove that that does not affect the prototype

// now let's see what static's do when inherited
var iBase = new BaseClass();
var iSub = new SubClass();
BaseClass.staticLogSomething();
SubClass.staticLogSomething(); // this will trigger an error because staticLogSomething must be accessed by its object, in this case the BaseClass defintion object

calling base functions
One last thing to add, when you wish to call a baseclass function inside your subclass, all you need to do is ‘call’ its function via the prototype and pass in a reference to this (and any other arguments after that).

So essentially Subclass2.log could have been this:

SubClass2.prototype.log = function()
{
    BaseClass.prototype.log.call(this);
    console.log(this.b);
}