The Textured Quad example textures a standard OpenGL quad with the image set from the Leap Motion cameras. Both images are included in one texture, with the left image above the right image.
The example uses callbacks to get tracking frames. When a frame becomes available, the example requests the corresponding image. When LeapC calls the image complete callback, the example sets an "imageReady" state variable. The example's GLUT idle function monitors the imageReady variable, and tells GLUT to redraw the display when the variable evaluates as true. The drawing is then performed when GLUT calls the display() function.
The quad is drawn using the OpenGL fixed function pipeline for simplicity. In all but the simplest cases, you should use the modern shader-based pipeline instead. Using shaders will also give you the ability to correct the image distortion for very little cost.
15 #include "ExampleConnection.h"
18 void* image_buffer = NULL;
19 uint64_t image_size = 0;
20 bool imageReady = false;
21 bool textureChanged = false;
22 uint32_t image_width = 0;
23 uint32_t image_height = 0;
25 int window; // GLUT window handle
27 /** Callback for when an image is available. */
28 static void OnImage(const LEAP_IMAGE_EVENT *imageEvent){
29 const LEAP_IMAGE_PROPERTIES* properties = &imageEvent->image[0].properties;
30 if (properties->bpp != 1)
33 if (properties->width*properties->height != image_size) {
34 void* prev_image_buffer = image_buffer;
35 image_width = properties->width;
36 image_height = properties->height;
37 image_size = image_width*image_height;
38 image_buffer = malloc(2 * image_size);
39 if (prev_image_buffer)
40 free(prev_image_buffer);
41 textureChanged = true;
44 memcpy(image_buffer, (char*)imageEvent->image[0].data + imageEvent->image[0].offset, image_size);
45 memcpy((char*)image_buffer + image_size, (char*)imageEvent->image[1].data + imageEvent->image[1].offset, image_size);
49 // Draw a textured quad displaying the image data
50 static void DrawImageQuad(float p1X, float p1Y, float p2X, float p2Y, int width, int height, void* imagedata){
51 glEnable(GL_TEXTURE_2D);
53 textureChanged = false;
54 glDeleteTextures(1, &texture);
55 glGenTextures(1, &texture);
56 glBindTexture(GL_TEXTURE_2D, texture);
57 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
58 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagedata);
59 checkGLError("Initializing texture.");
60 } else { //update existing texture
61 glBindTexture ( GL_TEXTURE_2D, texture);
62 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, imagedata);
63 checkGLError("Updating texture.");
65 //Draw a texture-mapped quad
67 glTexCoord2f(1, 1); glVertex2f((GLfloat)p1X, (GLfloat)p1Y);
68 glTexCoord2f(0, 1); glVertex2f((GLfloat)p2X, (GLfloat)p1Y);
69 glTexCoord2f(0, 0); glVertex2f((GLfloat)p2X, (GLfloat)p2Y);
70 glTexCoord2f(1, 0); glVertex2f((GLfloat)p1X, (GLfloat)p2Y);
72 checkGLError("Drawing quad.");
73 glDisable(GL_TEXTURE_2D);
77 static void display(void)
79 glMatrixMode(GL_MODELVIEW);
81 glTranslatef(-32, -24, -50); //"Camera" viewpoint
82 glClear(GL_COLOR_BUFFER_BIT);
84 DrawImageQuad(0, 0, 64, 48, image_width, image_height * 2, image_buffer);
92 static void reshape(int w, int h)
94 glViewport(0, 0, (GLsizei) w, (GLsizei) h);
95 glMatrixMode(GL_PROJECTION);
97 gluPerspective(60, 640/240, 1.0, 1000);
100 static void keyboard(unsigned char key, int x, int y)
105 glutDestroyWindow(window);
107 if(image_buffer) free(image_buffer);
114 static void idle(void){
119 int main(int argc, char *argv[])
121 ConnectionCallbacks.on_image = OnImage;
123 LEAP_CONNECTION *connection = OpenConnection();
124 LeapSetPolicyFlags(*connection, eLeapPolicyFlag_Images, 0);
130 glutInit(&argc, argv);
131 glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
132 glutInitWindowSize(640, 480);
133 window = glutCreateWindow("LeapC Image Example");
137 glutReshapeFunc(reshape);
138 glutKeyboardFunc(keyboard);
139 glutDisplayFunc(display);
142 glClearColor(0.0, 0.0, 0.0, 0.0);
143 glColor3f(1.0, 1.0, 1.0);
This example is only supported on platforms for which a working version of GLUT exists. It should not be overly difficult to port the example to a different OpenGL-based context, however.