Visualization Library

Your personal 3D visualization expert - info@visualizationlibrary.com
Home Download Documentation Screenshots Resources

Documentation

This section shows how to use Visualization Library, how to get started using the utility framework, the list of the main classes with a brief description, and how Visualization Library maps to OpenGL. In addition you can also download the HTML or CHM API documentation.

OpenGL Prerequisites

API Documentation

Visualization Library's Main Classes Overview

Class name Description
Drawable The base class of all the objects that can be rendered
Geometry A Drawable that represents a geometrical mesh
Text A Drawable that renders a text given a Font
DrawPixels A Drawable capable or rendering an Image
Actor An entity that associates a Drawable to a Transform
Transform Base class used to assemble Transform-trees. Implements a matrix transformation that can be applied to Actors, Lighs, Cameras and Planes
ShaderNode Base class used to assemble Shader-trees
Painter A special ShaderNode that manages the rendering, LOD and multipassing of a set of Actors
Shader Wraps all the render states of a ShaderNode
Camera Manages the camera model, viewport and render target
Viewport The rectangular sub-area of a framebuffer or "surface" in which a rendering is performed
RenderTarget The framebuffer or "surface" on which the rendering is performed
GLSLProgram, GLSLVertexShader, GLSLFragmentShader OpenGL Shading Language support classes
Light Represents a standard OpenGL light source: point light, directional light, spot light
Renderer Renders a given render-list on a particular Camera
RenderListCompiler Compiles a render-list given an Actor-list and a Camera
mat4, vec4, vec3, vec2, mat4d, vec4d, vec3d, vec2d, ivec4, ivec3, ivec2, quat Math support classes using the OpenGL Shading Language conventions

Quick OpenGL vs Visualization Library Mapping

OpenGL function / topic Visualization Library class or function
glEnable/glDisable ShaderNode::shader(), Shader::enable()/disable()
VBO, glVertex, glColor, glNormal, glTexCoord glVertexAttrib, glVertexPointer, glColorPointer, glNormalPointer, glTexCoordPointer, glVertexAttribPointer, glClientActiveTexture etc. Geometry::setVertexArray(), Geometry::setNormalArray(), Geometry::setColorArray(), Geometry::setTexCoordArray(), Geometry::setVertexAttrib(), GPUArrayBuffer, GPUArrayVec4/GPUArrayVec3/GPUArrayVec2/etc., GPUBuffer
glMapBuffer, glUnmapBuffer GPUBuffer::lockGPUBuffer(), GPUBuffer::unlockGPUBuffer()
glDrawArrays Geometry::addDrawCall(), DrawArrays
glDrawElements Geometry::addDrawCall(), DrawElements<>, DrawElementsUInt, DrawElementsUShort, DrawElementsUByte
glLight Light, Shader::addLight()
glClipPlane Plane, Shader::addClipPlane()
glDrawPixels DrawPixels, Image
glReadPixels Image, Image::readPixels()
glFrustum, glOrtho, gluProject, gluUnproject, gluOrtho2D, gluPerspective Camera, mat4d, mat4
Matrices
glLoadMatrix, glMatrixIdentity, glMultMatrix, glMatrixMode
mat4, mat4d, quat, Transform, Actor::setTransform() Light::followTransform(), Plane::followTransform(), Camera::followTransform
glViewport Viewport, Camera::setViewport()
Texturing
glBindTexture, glGenTextures, glDeleteTextures, glActiveTexture, glTexImage1D, glTexImage2D, glTexImage3D
Shader::textureUnit(int unit), Texture, Image, TextureUnit, TexParameter, TexEnv, TexGen
PBO - Pixel Buffer Object GPUBufferTemplate, DrawPixels
GLSL - OpenGL Shading Language GLSLProgram, GLSLVertexShader, GLSLFragmentShader, Shader::glslProgram()
glUniform* GLSLProgram, GLSLProgram::setUniform*(), Uniform, Actor::addUniform(), Actor::prerenderCallback()
FBO - Frame Buffer Object
RTT - Render To Texture
glGenFramebuffersEXT, glBindFramebufferEXT, glFramebufferRenderbufferEXT, glFramebufferTexture1DEXT, glFramebufferTexture2DEXT, glFramebufferTexture3DEXT, glRenderbufferStorageEXT, glDeleteRenderbuffersEXT
FBOAttachment, FBOColorBuffer, FBODepthBuffer, FBOStencilBuffer, FBOTexture1D, FBOTexture2D, FBOTexture3D, FBORenderTarget, RenderTarget, Camera::setRenderTarget()
MRT - Multiple Render Target
glDrawBuffer / glDrawBuffers
RenderTarget::setDrawBuffers()
RTT - Render To Texture (the "old" way)
glCopyTexImage1D, glCopyTexSubImage1D, glCopyTexImage2D, glCopyTexSubImage2D, glCopyTexImage3D, glCopyTexSubImage3D
CopyTexSubImage1D, CopyTexSubImage2D, CopyTexSubImage3D
glPixelTransfer PixelTransfer, Shader::glPixelTransfer()
glHint Hint, Shader::glHint()
glCullFace CullFace, Shader::glCullFace()
glFrontFace FrontFace, Shader::glFrontFace()
glDepthFunc DepthFunc, Shader::glDepthFunc()
glDepthMask DepthMask, Shader::glDepthMask()
glPolygonMode PolygonMode, Shader::glPolygonMode()
glShadeModel ShadeModel, Shader::glShadeModel()
glBlendFunc/glBlendFuncSeparate BlendFunc, Shader::glBlendFunc()
glSampleCoverage SampleCoverage, Shader::glSampleCoverage()
glBlendEquation BlendEquation, Shader::glBlendEquation()
glAlphaFunc AlphaFunc, Shader::glAlphaFunc()
glColorMaterial Material, Material::setColorMaterial()
glMaterial Material, Shader::glMaterial()
glLightModel LightModel, Shader::glLightModel()
glFog Fog, Shader::glFog()
glPolygonOffset PolygonOffset, Shader::glPolygonOffset()
glLogicOp LogicOp, Shader::glLogicOp()
glDepthRange DepthRange, Shader::glDepthRange()
glLineWidth LineWidth, Shader::glLineWidth()
glPointSize PointSize, Shader::glPointSize()
glPolygonStipple PolygonStipple, Shader::glPolygonStipple()
glLineStipple LineStipple, Shader::glLineStipple()
glPointParameter PointParameter, Shader::glPointParameter()
glStencilFunc StencilFunc, Shader::glStencilFunc()
glStencilOp StencilOp, Shader::glStencilOp()
glStencilMask StencilMask, Shader::glStencilMask()
glBlendColor BlendColor, Shader::glBlendColor()
glClipPlane ClipPlane, Shader::glClipPlane()
glColorMask ColorMask, Shader::glColorMask()
glScissor Scissor, Shader::glScissor()
glTexParameter TexParameter, TextureUnit,
Shader::textureUnit(int unit)->glTexParameter()
glTexEnv TexEnv, TextureUnit,
Shader::textureUnit(int unit)->glTexEnv()
glTexGen TexGen, TextureUnit,
Shader::textureUnit(int unit)->glTexGen()

Visualization Library's Recipes

Using The SDL And GLUT Utility Frameworks

Here you can see how to use the utility framework to create the classic rotating cube using the vlut::Program class:

#include "vl/Time.hpp"
#include "vl/mat4d.hpp"
#include "vlut/Program.hpp"
#include "vlut/GeometricalPrimitives.hpp"

class RotatingCube_Program: public vlut::Program
{
public:
  virtual void shutdown() {}

  /* called every frame */
  virtual void run()
  {
    /* rotates the cube around the Y axis 45 degrees per second */
    double degrees = vl::Time::getSeconds() * 45.0;
    vl::mat4d matrix = vl::mat4d::rotation( degrees, 0,1,0 );
    _CubeTransform->setLocalMatrix( matrix );
  }

  /* called once after the OpenGL window has been opened */
  void init()
  {
    /* allocate the Transform */
    _CubeTransform = new vl::Transform;
    /* bind the Transform with the transform tree of the rendring pipeline */
    pipeline()->transform()->addChild( _CubeTransform.get() );

    /* create the cube's Geometry */
    vl::ref<vl::Geometry> cube = vlut::makeBox( vl::vec3d(0,0,0), 10, 10, 10 );
    /* compute the cube's normals to support lighting */
    cube->computeSmoothNormals();
    /* allocate an Actor for the cube */
    vl::ref<vl::Actor> cube_actor1 = new vl::Actor;
    /* bind the cube's Geometry to the Actor */
    cube_actor1->setDrawable( cube.get() );
    /* bind the cube's Transform to the Actor */
    cube_actor1->setTransform( _CubeTransform.get() );

    /* allocate a Painter to draw our cube */
    vl::ref<vl::Painter> painter = new vl::Painter;
    /* bind our Painter to the shader-tree of the rendering pipeline */
    pipeline()->shaderNode()->addChild( painter.get() );
    /* add the cube's Actor to the Painter */
    painter->addActor( cube_actor1.get() );

    /* let's setup some render states! */
    
    /* enable depth test and lighting */
    painter->shader()->enable(vl::EN_DEPTH_TEST);
    /* add a Light to the scene, since no Transform is associated to the Light it will follow the camera */
    painter->shader()->addLight( new vl::Light );
    /* enable the standard OpenGL lighting */
    painter->shader()->enable(vl::EN_LIGHTING);
    /* set the material color of our cube */
    painter->shader()->glMaterial()->setDiffuse( vlut::crimson );
  }

protected:
  vl::ref<vl::Transform> _CubeTransform;
};
Using your vlut::Program with the SDL utility framework:
#include "vlSDL/SDL_Window.hpp"

int main(int numarg, char* args[])
{
  /* initialize Visualization Library */
  vl::visualization_library_init();

  /* setup the OpenGL context info */
  vl::OpenGLContextInfo info;
  info.setHasDoubleBuffer(true);
  info.setRGBABits( vl::ivec4(8,8,8,8) );
  info.setZBufferBits(24);
  info.setFullscreen(false);

  /* open the SDL window */
  vl::ref<vlSDL::SDL_Window> win =
    vlSDL::open_SDL_Window(
      "Visualization Library on SDL - Rotating Cube", /* window title */
      new RotatingCube_Program, /* vlut::Program to execute */
      info, /* OpenGL context info */
      512, /* window width */
      512, /* window height */
      vlut::black, /* background color */
      vl::vec3d(0,10,35), /* camera position */
      vl::vec3d(0,0,0) /* camera look at */
    );

  /* SDL supports only one window, so you cannot call vlSDL::open_SDL_Window() more than once! */
  
  /* enter the SDL main loop */
  vlSDL::sdlMainLoop();

  /* shut down Visualization Library */
  vl::visualization_library_shutdown();

  return 0;
}
Using your vlut::Program with the GLUT utility framework:
#include "vlGLUT/GLUT_Window.hpp"

int main ( int argc, char *argv[] )
{
  /* init GLUT */
  int pargc = argc;
  glutInit( &pargc, argv );

  /* init Visualization Library */
  vl::visualization_library_init();

  /* install Visualization Library shutdown function */
  atexit( vlGLUT::atexit_visualization_library_shutdown );

  /* setup the OpenGL context info */
  vl::OpenGLContextInfo info;
  info.setHasDoubleBuffer(true);
  info.setRGBABits( vl::ivec4(8,8,8,8) );
  info.setZBufferBits(24);
  info.setFullscreen(false);

  /* open a GLUT window */
  vl::ref<vlGLUT::GLUT_Window> win =
    vlGLUT::open_GLUT_Window(
      "Visualization Library on GLUT - Rotating Cube", /* window title */
      new RotatingCube_Program, /* vlut::Program to execute */
      info, /* OpenGL context info */
      50, /* window x position */
      50, /* window y position */
      512, /* window width */
      512, /* window height */
      vlut::black, /* background color */
      vl::vec3d(0,10,25), /* camera position */
      vl::vec3d(0,0,0) /* camera look at */
    );

  /* ... you can open more than one GLUT window! */

  /* enter the GLUT main loop */
  glutMainLoop();

  /* this point is never reached since glutMainLoop() never returns! */

  return 0;
}
Memory Management
  • Visualization Library classes are almost all derived from the class Object. The most notable exception to this rule are math classes like vec3, quat, mat4 etc. that need a specific memory layout to be passed to OpenGL.
  • Object-derived classes can be reference-counted using vl::ref<>
  • vl::ref<> is actually a boost::intrusive_ptr<> renamed for practical reasons
  • boost::intrusive_ptr<> compared to other smart pointers is:

    - easier to debug since you can read the reference count at any time
    - faster to allocate and deallocate since no reference-counted wrapper object is created (like for boost::shared_ptr)
    - uses less memory for the same reasons

  • Why Visualization Library uses vl::ref<>?

    Together with carefully designed data structures vl::ref<> and boost::intrusive_ptr<> let you dramatically reduce the amount of code needed to manage dynamic memory allocations, improving code reliability as well as readability.

  • How to use vl::ref<>:
    - for each new there must be a vl::ref<>
    /* when both "img" and "img2" go out of scope the referenced vl::Image is automatically deallocated */
    vl::ref<vl::Image> img = new vl::Image("picture.bmp");
    vl::ref<vl::Image> img2 = img1;
    
    to return a freshly created vl::ref<>
    /* the function gives the ownership of the Image to somebody else */
    vl::ref<vl::Image> create_noise_image()
    {
      vl::ref<vl::Image> image = new vl::Image;
      ...
      return image;
    }
    
    to create owner/user data structures
    class NodeTree: public vl::Object
    {
    public:
      NodeTree(): _Parent(NULL) {}
    
      /* vl::ref<> for the children since I'm their OWNER */
      std::vector< vl::ref<NodeTree> > _Children;
    
      /* naked pointer to refer to my parent node as a USER */
      NodeTree* _Parent;
    };
    
  • How NOT to use vl::ref<>
    - usually you don't need vl::ref<> as function arguments
    /* this is not necessary and slower */
    void filter_image( vl::ref<vl::Image> image )
    {
      ...
    }
    
    /* a better way woud be this */
    void filter_image( vl::Image* image )
    {
      ...
    }
    
    - never reference pointers to local variables
    /* when the local variable goes out of scope it will be destroyed but when "img" goes
    out of scope it will also try to deallocate the image, producing a segmentation fault */
    vl::Image local_image("picture.bmp");
    vl::ref<vl::Image> img = &local_image;
    
    - never pass naked pointers to functions, classes etc.
    /* during the function call somebody (a function or a class) could assign the naked pointer
    to a vl::ref<> that could deallocate the image by the time you try to use it again */
    vl::Image* img_ptr = vl::Image("picture.bmp");
    some_function(img_ptr);
    img_ptr->some_method(); /* can produce a segmentation fault */
    
    - never allocate objects meanwhile calling functions, classes constructors etc. if they don't have a precise owner/user relationship
    /* vl::Texture is not "owner" of vl::Image but is only a temporary user which means that it
    doesn't keep any vl::ref<> to the passed vl::Image whose pointer will be lost forever generating
    a memory leak */
    vl::ref<vl::Texture> tex = new vl::Texture( new vl::Image("picture.bmp") );
    
    /* this code is perfectly legal since vl::Painter is "owner" of vl::Actor which in turn is
    also "owner" of vl::Geometry and vl::Transform: when the painter is destroyed all the
    associated Actors will be destroyed which in turn destroy all the associated Drawables
    and Transforms (if not referenced by anyone else) */
    vl::ref<vl::Painter> painter = new vl::Painter;
    painter->addActor( new vl::Actor( new vl::Geometry, new vl::Transform ) );
    painter = NULL /* deallocates everything, no memory leaks */
    
  • To avoid problems there is a simple rule to follow: for each new there must be a vl::ref<>
  • Never call delete on an object which is also referenced by a vl::ref<>
  • Actually you shouldn't use delete at all, instead use std::vector<> for dynamic memory management
  • The existence of cyrcular dependencies is the main issue one has to face when handling garbage collection systems based on reference counting. If an object X keeps a vl::ref<> referencing an object Y which in turn keeps a vl::ref<> referencing the object X we have a cyrcular dependency. This is the simplest case but obviously the chain can be much longer and less evident. As you might have imagined if we don't break the cyrcular dependency X and Y will never be deallocated because each of them keeps a reference to the other, thus producing a memory leak.

    To minimize the cyrcular dependencies you should use vl::ref<> only for objects that own other objects and use naked pointers for temporary users. For example one could implement a tree data structure where each node points to it's children using vl::ref<>, this way when a node is deleted all it's children are deleted. But a class that uses the tree to perform a temporary task or computation should refer to the tree nodes using only naked pointers.

    If your nodes keep a pointer also to their parent node they should use naked pointers and not vl::ref<> since a children is not owner of the parent and this will avoid the cyrcular dependency parent<-->child.

    There are some cases in which you really need or want to keep cyrcular dependencies. In those cases you have to be aware of them and take the responsibility of disassembling them at the right moment in order to prevent memory leaks.

Multitexturing
#include "vlImage.hpp"
...

/* create the cube's Geometry */
vl::ref cube = vlut::makeBox( vl::vec3d(0,0,0), 10, 10, 10, true );
/* compute the cube's normals to support lighting */
cube->computeSmoothNormals();
/* use the same texture coordinates for texunit 0 and 1 */
cube->setTexCoordArray(1, cube->texCoordArray(0));
/* allocate an Actor for the cube */
vl::ref cube_actor1 = new vl::Actor;
/* bind the cube's Geometry to the Actor */
cube_actor1->setDrawable( cube.get() );

/* allocate a Painter to draw our cube */
vl::ref painter = new vl::Painter;
/* bind our Painter to the shader-tree of the rendering pipeline */
pipeline()->shaderNode()->addChild( painter.get() );
/* add the cube's Actor to the Painter */
painter->addActor( cube_actor1.get() );

/* load the texture's image */
vl::ref img1 = vl::loadImage(vl::envVarValue("VL_DATA_PATH")+"/holebox.tif");
/* first texture unit: create the texture from the Image */
painter->shader()->textureUnit(0)->setTexture( new vl::Texture(img1.get() ) );

/* load the texture's image */
vl::ref img2 = vl::loadImage(vl::envVarValue("VL_DATA_PATH")+"/detail.tif");
/* second texture unit: create the texture from the Image */
painter->shader()->textureUnit(1)->setTexture( new vl::Texture(img2.get() ) );
painter->shader()->textureUnit(1)->glTexEnv()->setMode( vl::TEM_MODULATE );

/* let's setup some render states! */

/* enable depth testing */
painter->shader()->enable(vl::EN_DEPTH_TEST);
/* enable double side lighting */
painter->shader()->addLight(new vl::Light);
painter->shader()->enable(vl::EN_LIGHTING);
painter->shader()->glLightModel()->setTwoSide(true);
/* enable alpha blending */
painter->shader()->enable(vl::EN_BLEND);
painter->shader()->glBlendFunc()->set(vl::BF_SRC_ALPHA, vl::BF_ONE_MINUS_SRC_ALPHA);
/* enable alpha test */
painter->shader()->enable(vl::EN_ALPHA_TEST);
painter->shader()->glAlphaFunc()->set(vl::FU_GEQUAL, 1.0f - 0.02f);
Transform Tree
...
Shader Tree
...
Lights And Materials
...
Geometrical Primitives
...
Custom Geometrical Meshes
...
Math
...

Blending
...
Line Smoothing
...
Text
...
OpenGL Shading Language
...
Frame Buffer Object
...

Professional Support - support@visualizationlibrary.com

Visualization Library - info@visualizationlibrary.com

Visualization Library and Visualization Library website are Copyright © 2005-2008 Michele Bosi VAT IT 02791110543