blShapePartialDisk — Construct and render static or dynamic partial disk shapes in opengl

This entry is part 3 of 6 in the series blShapeAPI -- BarbatoLabs Shape API

Introduction

As part of the blShapeAPI series, in this article I present blShapePartialDisk, which is derived from blShapeQuadric and builds a partial disk. Just like blShapeQuadric, this shape can be static or dynamic, and with only a few lines of code can produce astonishing results.

Here’s a simple example that I built using the blShapePartialDiskc class together with the blImageAPI to get a webcam feed.

Here you can see my hand being dynamically drawn on top of a partial disk built using blShapePartialDisk. We can easily use it for generating dynamic terrains, building all types of different shapes. Each vertex can have its own height, normal, texture coordinate and color.

Note: The texture coordinates are generated by default such that the texture is not stretched on the disk. Of course, the function that generates the texture coordinates allows you to choose how you want the texture coordinates to be generated.

Dependencies

blShapePartialDisk is derived from blShapeQuadric

  1. blVector3d — From the blMathAPI library

The code

My code uses inline documentation and follows a clean structure, (at least to me). The blShapePartialDisk class is saved in a file called blShapePartialDisk.hpp as follows:

blShapePartialDisk.hpp (Click to see code…)

Usage

To show the potential of blShapePartialDisk, the following snippet shows how to create a height map, grab a video feed from a webcam, and use the grabbed frames to assign the height of the map’s vertices. It assigns the value of the frames pixels as the height of the vertices:
Note: The following snippet grabs the webcam feed naively, in later posts I will show you how to grab the video in parallel to the rendering thread.

#include "vbAPI/vbAPI.hpp"
using namespace vbAPI;

#include <SFML/Window.hpp>

int main(int argc, char *argv[])
{
    // Create an OpenGL window
    // using the sfml library
    sf::WindowSettings Settings;
    Settings.DepthBits         = 24;
    Settings.StencilBits       = 8;
    Settings.AntialiasingLevel = 2;

    sf::Window App(sf::VideoMode(500,500,32),
                   "SFML OpenGL",
                   sf::Style::Close,
                   Settings);

    glClearDepth(1.f);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    // Enable Z-buffer read and write
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);
    glEnable(GL_TEXTURE_2D);

    // Setup a perspective projection
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(90.f, 1.f, 1.f, 1000.f);

    // Connect to the webcam
    blCaptureDevice Webcam;
    Webcam.ConnectToWebcam(0);

    // The webcam frame grayscale
    blImage<float> Frame;

    // Create a texture
    blTexture MyTexture;

    // Create a partial disk surface
    // and use triangles drawing mode
    blShapePartialDisk<float> MyDisk(0.15,0.5,0,270,20,30);
    MyDisk.SetDrawingMode(GL_TRIANGLES);
    MyDisk.GenerateVertices();
    MyDisk.GenerateNormals();
    MyDisk.GenerateTextureCoords();
    //MyDisk.GenerateVBOs(true);

    // Grab a new frame from the webcam
    Webcam.QueryFrame(Frame);

    // Load the grabbed frame into our texture
    MyTexture.LoadImageToTexture(Frame,true,false);

    // Generate the vertices using
    // the frame as our height map
    MyDisk.GenerateVertices(Frame.GetImageDataCast(),Frame.size1(),Frame.size2(),0.0f,1.0f);

    // Generate the normals and texture coords
    MyDisk.GenerateNormals();
    MyDisk.GenerateTextureCoords();

    // Create a boolean to exit
    // when the user decides to do so
    bool Running = true;

    while (Running)
    {
        sf::Event MyEvent;
        while(App.GetEvent(MyEvent))
        {
            if(MyEvent.Type == sf::Event::Closed)
                Running = false;
        }

        // Let's make sure our app is the
        // active opengl rendering context
        App.SetActive();

        // Let's do some clearing
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDisable(GL_CULL_FACE);

        // Let's do some moving around
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, 0.0f, -2.0f);
        glColor4f(1,1,1,1);

        // Grab a new frame from the webcam
        Webcam.QueryFrame(Frame);

        // Load the grabbed frame into our texture
        MyTexture.LoadImageToTexture(Frame,true,false);

        // Generate the vertices using
        // the frame as our height map
        MyDisk.GenerateVertices(Frame.GetImageDataCast(),Frame.size1(),Frame.size2(),0,1);

        // Draw the partial disk
        MyDisk.Draw(true,true,false);

        // Let's move around a bit
        glTranslatef(1,0.5,0);
        glRotatef(-50,1,1,0);

        // Let's apply a yellow tint to it
        glColor4f(1,1,0,1);

        // Let's draw the partial disk again
        MyDisk.Draw(true,true,true);

        // Display the opengl stuff
        App.Display();
    }
}

The resulting output is the following window:

Downloads

I have put all the files into a zip file which can be downloaded here. All you have to do is extract it somewhere, let’s say in a directory called blShapeAPI, and then include the blShapeAPI.hpp file as follows:

#include "blShapeAPI/blShapeAPI.hpp"
using namespace blShapeAPI;

Note: The blShapeAPI depends on the blMathAPI and thus you’ll need both APIs:
blMathAPI.zip Ver 02/22/2011 2:50am (1748) blShapeAPI.zip Ver 11/27/2010 11:40PM (1229)

Updates

I forgot to mention that you’ll also need the glext.h file for opengl extensions with a special function to search for extensions which I placed in this file: GLext.zip (1904)

11/21/2010 — I updated the GenerateVertices function, so that when you generate a height map, you can control the maximum map height.

11/24/2010 — Changed the function to generate texture coordinates for the GL_QUADS case. Before it was not generating the correct number of texture coordinates, and thus it was causing an access error.

About Vincenzo Barbato

Known to his friends as Enzo, he's an outside-the-box engineer/researcher whose interests and expertise span many fields, including controls systems, multi-physics simulations, mechatronics, oil technologies, data analysis and machine vision just to name a few.

Refusing to grow up, he's on a continuous journey to develop simple and creative solutions that have the power of disrupting industries by optimizing systems and processes.

Married to a beautiful wife, with two beautiful daughters and two identical twin boys, his home is a never ending chaotic fountain of inspiration.

His outlook on life:

"Never blindly accept what you're told, listen, but then question, with curiosity, creativity and collaboration we can change the world"

About Enzo

Known to his friends as Enzo, he's an outside-the-box engineer/researcher whose interests and expertise span many fields, including controls systems, multi-physics simulations, mechatronics, oil technologies, data analysis and machine vision just to name a few. Refusing to grow up, he's on a continuous journey to develop simple and creative solutions that have the power of disrupting industries by optimizing systems and processes. Married to a beautiful wife, with two beautiful daughters and two identical twin boys, his home is a never ending chaotic fountain of inspiration. His outlook on life: "Never blindly accept what you're told, listen, but then question, with curiosity, creativity and collaboration we can change the world"

Leave a Reply

Your email address will not be published. Required fields are marked *