Table of Contents

13. Examples

This chapter contains example VglTools programs. The source code for all examples resides in devtools/src/vgl/exam. Example 1 illustrates the drawing of basic primitive types and changing their attributes such as line width, etc. Example 2 illustrates drawing primitives in 3D with lighting, z-buffering and transformations. The Example 3 suite draws "Hello World" to a graphics window using OpenGL in both X windows as well Microsoft Windows. In addition an implementation in raw X windows is given. The Example 4 suite illustrates drawing to two windows using OpenGL and X windows or Microsoft windows. Examples 5 through 8 and example 12 demonstrate various aspects of VglTools using OpenGL and are written to execute under either X windows or Microsoft Windows. Examples 9 through 11 use a simple helper module in files vgldev.c and vgldev.h which allow the examples to be executed on any VglTools supported platform using OpenGL, X11 or GDI.

Table of Contents

13.1 Example 1, Drawing Basic Point, Line and Polygon Primitives

This example illustrates opening a graphics window in a standalone application and drawing basic point, line and polygon primitives in a base color. Initially an OpenGLDev rendering object is instanced along with an associated DrawFun object. Once the DrawFun object has been loaded with OpenGLDev rendering functions using vgl_OpenGLDevDrawFun, all drawing is done using the abstract DrawFun. The graphics window is positioned, sized and opened. By default a double buffered, RGBA frame buffer is configured. The basic rendering cycle involves clearing the graphics buffers using vgl_DrawFunClear, generating graphics primitives and then swapping the graphics buffers using vgl_DrawFunSwap.

This example sets base colors using vgl_DrawFunColor. The point, line and polygon primitives are generated using the simplest form of these primitive calls. The point size and line width are set so that the points and lines in this example are more easily seen.

A C++ version of this example is in file exam1cc.cxx.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data */ 
static Vfloat xpoint[2][3] = {
   {-.5, .5, 0.}, {.5, .5, 0.} };
                   /* line data */ 
static Vfloat xline[3][3] = {
   {-.5, 0., 0.}, {0.,.1,0.}, {.5, 0., 0.} };
                   /* triangle data */ 
static Vfloat xtris[6][3] = {
   {-.5, -.7, 0.}, {-.1,-.7,0.}, {-.3, -.3, 0.},
   { .1, -.7, 0.}, { .5,-.7,0.}, { .3, -.3, 0.} };

/*----------------------------------------------------------------------
                      Drawing Basic Point, Line and Polygon Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);
                   /* turn on multisampling */ 
   vgl_DrawFunVisualWindow (df,VGL_VISUAL_MULTISAMPLE);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* default projection limits are bi-unit cube */ 
                   /* clear frame buffer and depth buffers */
   vgl_DrawFunClear (df);

                   /* set current color to white */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* set current point size to 4 pixels */
   vgl_DrawFunPointSize (df,4);
                   /* draw two points */ 
   vgl_DrawFunPolyPoint (df,2,xpoint);

                   /* set current line width to 2 */
   vgl_DrawFunLineWidth (df,2);
                   /* draw linestrip with 3 points */ 
   vgl_DrawFunPolyLine (df,VGL_LINESTRIP,3,xline);

                   /* set current color to red */ 
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
                   /* draw 2 triangles */ 
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,6,xtris,VGL_NOSHADE,NULL);
                   /* swap buffers */
   vgl_DrawFunSwap (df);

                   /* wait 10 seconds */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.2 Example 1a, Drawing Vertex Color Point, Line and Polygon Primitives

This example draws the same primitives as Example 1 except it uses vertex based colors. Note that the point, line and polygon primitives have added the string "Color" to the primitive functions and a vertex color array is added to the argument lists. The color array allows for red, green and blue components (no alpha component).

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data */ 
static Vfloat xpoint[2][3] = {
   {-.5, .5, 0.}, {.5, .5, 0.} };
static Vfloat cpoint[2][3] = {
   {1., 0., 0.}, {0., 0., 1.} };
                   /* line data */ 
static Vfloat xline[3][3] = {
   {-.5, 0., 0.}, {0.,.1,0.}, {.5, 0., 0.} };
static Vfloat cline[3][3] = {
   {1., 0., 0.}, {0.,1.,0.}, {0., 0., 1.} };
                   /* triangle data */ 
static Vfloat xtris[6][3] = {
   {-.5, -.7, 0.}, {-.1,-.7,0.}, {-.3, -.3, 0.},
   { .1, -.7, 0.}, { .5,-.7,0.}, { .3, -.3, 0.} };
static Vfloat ctris[6][3] = {
   {1., 0., 0.}, {0.,1.,0.}, {0., 0., 1.},
   {1., 0., 0.}, {0.,1.,0.}, {0., 0., 1.} };

/*----------------------------------------------------------------------
                      Drawing Vertex Color Point, Line and Polygon Primitives
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* default projection limits are bi-unit cube */ 
                   /* clear frame buffer and depth buffers */
   vgl_DrawFunClear (df);

                   /* set current point size to 4 pixels */
   vgl_DrawFunPointSize (df,4);
                   /* draw two points */ 
   vgl_DrawFunPolyPointColor (df,2,xpoint,cpoint);

                   /* set current line width to 2 */
   vgl_DrawFunLineWidth (df,2);
                   /* draw linestrip with 3 points */ 
   vgl_DrawFunPolyLineColor (df,VGL_LINESTRIP,3,xline,cline);

                   /* draw 2 triangles */ 
   vgl_DrawFunPolygonColor (df,VGL_TRIANGLES,6,xtris,ctris,VGL_NOSHADE,NULL);
                   /* swap buffers */
   vgl_DrawFunSwap (df);

                   /* wait 10 seconds */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.3 Example 1b, Drawing Vertex Array Point, Line and Polygon Primitives

This example draws the same primitives as Example 1 except it uses vertex array based colors, normals and textures. Note that the point, line and polygon primitives have added the string "Array" to the primitive functions and all primitive types allow color, normal, texture and data arrays. The color and normal arrays may be typed as either floats or bytes. The data arrays are not used in this example. The input argument arrangement of the "Array" primitives makes it possible to optimize the drawing of the primitives using modern graphics hardware. The use of the Array primitives is recommended for drawing large numbers of graphics primitives.

Three scenes are drawn. The first scene draws the points, lines and triangles using various options for the vertex color input. The triangles are drawn with varying transparency across the triangles. The second scene draws dashed lines and stippled triangles. Note the use of the Bitmap object to set the stipple pattern. The third scene draws a textured linestrip and textured triangles using a 1 dimensional texture using the Texture object. It is typical to draw textured primitives in a base color of white so that the primitive is drawn in exactly the texture color.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data */ 
static Vfloat xpoint[2][3] = {
   {-.5, .5, 0.}, {.5, .5, 0.} };
static Vfloat cpoint[2][3] = {
   {1., 0., 0.}, {0., 0., 1.} };
                   /* line data */ 
static Vfloat xline[3][3] = {
   {-.5, 0., 0.}, {0.,.1,0.}, {.5, 0., 0.} };
static Vuchar cline[3][4] = {
   {255,0,0,255}, {0,255,0,255}, {0,0,255,255} };
static Vfloat tline[3] = {
   0.,.5,1. };
                   /* triangle data */ 
static Vfloat xtris[6][3] = {
   {-.5, -.7, 0.}, {-.1,-.7,0.}, {-.3, -.3, 0.},
   { .1, -.7, 0.}, { .5,-.7,0.}, { .3, -.3, 0.} };
static Vuchar ctris[6][4] = {
   {255,0,0,255}, {0,255,0,0}, {0,0,255,255},
   {255,0,0,255}, {0,255,0,0}, {0,0,255,255} };
static Vfloat ttris[6] = {
   0.,1.,1.,
   0.,1.,1. };

/*----------------------------------------------------------------------
                      Drawing Vertex Array Point, Line and Polygon Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;
   vgl_Bitmap *bitmap;
   vgl_Texture *texture;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* default projection limits are bi-unit cube */ 
                   /* clear frame buffer and depth buffers */
   vgl_DrawFunClear (df);

                   /* set current point size to 4 pixels */
   vgl_DrawFunPointSize (df,4);
                   /* draw two points */ 
   vgl_DrawFunPolyArray (df,VGL_POINTS,2,xpoint,VGL_COLOR_3F,cpoint,
                         0,NULL,0,NULL,0,NULL);

                   /* set current line width to 2 */
   vgl_DrawFunLineWidth (df,2);
                   /* draw linestrip with 3 points */ 
   vgl_DrawFunPolyArray (df,VGL_LINESTRIP,3,xline,VGL_COLOR_4B,cline,
                         0,NULL,0,NULL,0,NULL);

                   /* draw 2 triangles */ 
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_ON);
   vgl_DrawFunPolyArray (df,VGL_TRIANGLES,6,xtris,VGL_COLOR_4B,ctris,
                         0,NULL,0,NULL,0,NULL);
                   /* swap buffers */
   vgl_DrawFunSwap (df);

                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* now draw dashed lines and stippled polygons */ 
                   /* define bitmap */
   bitmap = vgl_BitmapBegin ();
   vgl_BitmapLoad (bitmap,BITMAP_SQUARE4);
   vgl_DrawFunBitmapDefine (df,1,bitmap);
   vgl_DrawFunClear (df);

                   /* set current line type to dashed */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_DASH);
                   /* draw linestrip with 3 points */ 
   vgl_DrawFunPolyArray (df,VGL_LINESTRIP,3,xline,VGL_COLOR_4B,cline,
                         0,NULL,0,NULL,0,NULL);

                   /* draw 2 triangles */ 
   vgl_DrawFunBitmapSelect (df,1);
   vgl_DrawFunPolyArray (df,VGL_TRIANGLES,6,xtris,VGL_COLOR_4B,ctris,
                         0,NULL,0,NULL,0,NULL);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* now draw textured lines and triangles */
                   /* define texture */
                   /* built-in is index 1 */
   texture = vgl_TextureBegin ();
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_DrawFunClear (df);

                   /* select texture and draw a base color of white */ 
   vgl_DrawFunTextureSelect (df,1);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* set current line type to solid */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_SOLID);
                   /* draw linestrip with 3 points */
   vgl_DrawFunPolyArray (df,VGL_LINESTRIP,3,xline,0,NULL,
                         0,NULL,VGL_1DTEXTURE,tline,0,NULL);

                   /* draw 2 triangles */
   vgl_DrawFunBitmapSelect (df,0);
   vgl_DrawFunPolyArray (df,VGL_TRIANGLES,6,xtris,0,NULL,
                         0,NULL,VGL_1DTEXTURE,ttris,0,NULL);

   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.4 Example 1c, Drawing Vertex Buffer Point, Line and Polygon Primitives

This example draws the same primitives as Example 1b except it uses vertex buffer objects. Note that the point, line and polygon primitives have added the string "Buffer" to the primitive functions and all primitive types allow color, normal, texture and data arrays.

All of the vertex coordinates, color, normals, textures and data are copied explicitly to graphics memory from client memory. A block of graphics memory if first allocated using vgl_DrawFunInitBuffer. this function returns a vertex buffer object identifier, vboid. Note that it is possible that this memory allocation may fail. If this is the case, a complete application would need to be able to revert to the equivalent "Array" graphics primitives which would use client memory. It also possible that vgl_DrawFunCopyBuffer may fail if the amount of data to be copied to the vertex buffer exceeds the size of the vertex buffer. In this case an offset of -1 is returned and another vertex buffer would need to be allocated using vgl_DrawFunInitBuffer to be used to hold the vertex data.

All the vertex data is copied to the vertex buffer and an offset into the vertex buffer is returned for each set of vertex data. The graphics memory to be used for each drawing primitive is addressed using the vertex buffer identifier and respective offsets. After drawing is completed, the graphics memory associated with the vertex buffer is freed using vgl_DrawFunTermBuffer.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data */ 
static Vfloat xpoint[2][3] = {
   {-.5, .5, 0.}, {.5, .5, 0.} };
static Vfloat cpoint[2][3] = {
   {1., 0., 0.}, {0., 0., 1.} };
                   /* line data */ 
static Vfloat xline[3][3] = {
   {-.5, 0., 0.}, {0.,.1,0.}, {.5, 0., 0.} };
static Vuchar cline[3][4] = {
   {255,0,0,255}, {0,255,0,255}, {0,0,255,255} };
static Vfloat tline[3] = {
   0.,.5,1. };
                   /* triangle data */ 
static Vfloat xtris[6][3] = {
   {-.5, -.7, 0.}, {-.1,-.7,0.}, {-.3, -.3, 0.},
   { .1, -.7, 0.}, { .5,-.7,0.}, { .3, -.3, 0.} };
static Vuchar ctris[6][4] = {
   {255,0,0,255}, {0,255,0,0}, {0,0,255,255},
   {255,0,0,255}, {0,255,0,0}, {0,0,255,255} };
static Vfloat ttris[6] = {
   0.,1.,1.,
   0.,1.,1. };

/*----------------------------------------------------------------------
                      Drawing Vertex Buffer Point, Line and Polygon Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
   Vint vboid;
   Vint vboof1, vboof2, vboof3, vboof4, vboof5;
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;
   vgl_Bitmap *bitmap;
   vgl_Texture *texture;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* default projection limits are bi-unit cube */ 
                   /* clear frame buffer and depth buffers */
   vgl_DrawFunClear (df);

                   /* assume a buffer object of 100K bytes is large enough */
   vgl_DrawFunInitBuffer (df,100000,&vboid);
                   /* check to see if vertex buffer is created */ 
   if(vboid == 0) {
      fprintf(stderr,"Can not create buffer\n");
      exit(0);
   }
                   /* copy two points */ 
   vgl_DrawFunCopyBuffer (df,vboid,2,xpoint,VGL_COLOR_3F,cpoint,
                          0,NULL,0,NULL,0,NULL,&vboof1);

                   /* copy linestrip with 3 points */ 
   vgl_DrawFunCopyBuffer (df,vboid,3,xline,VGL_COLOR_4B,cline,
                          0,NULL,0,NULL,0,NULL,&vboof2);

                   /* copy 2 triangles */ 
   vgl_DrawFunCopyBuffer (df,vboid,6,xtris,VGL_COLOR_4B,ctris,
                          0,NULL,0,NULL,0,NULL,&vboof3);

                   /* now copy textured lines and triangles */ 
   vgl_DrawFunCopyBuffer (df,vboid,3,xline,0,NULL,0,NULL,VGL_1DTEXTURE,tline,
                          0,NULL,&vboof4);
   vgl_DrawFunCopyBuffer (df,vboid,6,xtris,0,NULL,0,NULL,VGL_1DTEXTURE,ttris,
                          0,NULL,&vboof5);

                   /* now draw */ 
                   /* set current point size to 4 pixels */
   vgl_DrawFunPointSize (df,4);
   vgl_DrawFunPolyBuffer (df,vboid,vboof1,VGL_POINTS,2,VGL_COLOR_3F,0,0,0);
                   /* set current line width to 2 */
   vgl_DrawFunLineWidth (df,2);
   vgl_DrawFunPolyBuffer (df,vboid,vboof2,
                          VGL_LINESTRIP,3,VGL_COLOR_4B,0,0,0);
                   /* turn on blend transparency */ 
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_ON);
   vgl_DrawFunPolyBuffer (df,vboid,vboof3,
                          VGL_TRIANGLES,6,VGL_COLOR_4B,0,0,0);
                   /* swap buffers */
   vgl_DrawFunSwap (df);

                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* now draw dashed lines and stippled polygons */ 
                   /* define bitmap */
   bitmap = vgl_BitmapBegin ();
   vgl_BitmapLoad (bitmap,BITMAP_SQUARE4);
   vgl_DrawFunBitmapDefine (df,1,bitmap);
   vgl_DrawFunClear (df);

                   /* set current line type to dashed */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_DASH);
                   /* draw linestrip with 3 points */ 
   vgl_DrawFunPolyBuffer (df,vboid,vboof2,
                          VGL_LINESTRIP,3,VGL_COLOR_4B,0,0,0);

                   /* draw 2 triangles */ 
   vgl_DrawFunBitmapSelect (df,1);
   vgl_DrawFunPolyBuffer (df,vboid,vboof3,
                          VGL_TRIANGLES,6,VGL_COLOR_4B,0,0,0);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* now draw textured lines and triangles */
                   /* define texture */
                   /* built-in is index 1 */
   texture = vgl_TextureBegin ();
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_DrawFunClear (df);

                   /* select texture and draw a base color of white */ 
   vgl_DrawFunTextureSelect (df,1);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* set current line type to solid */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_SOLID);
                   /* draw linestrip with 3 points */
   vgl_DrawFunPolyBuffer (df,vboid,vboof4,
                          VGL_LINESTRIP,3,0,0,VGL_1DTEXTURE,0);

                   /* draw 2 triangles */
   vgl_DrawFunBitmapSelect (df,0);
   vgl_DrawFunPolyBuffer (df,vboid,vboof5,
                          VGL_TRIANGLES,6,0,0,VGL_1DTEXTURE,0);

   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* free buffer memory */ 
   vgl_DrawFunTermBuffer (df,vboid);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_BitmapEnd (bitmap);
   vgl_TextureEnd (texture);
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.5 Example 1d, Drawing Element Indexed Array Primitives

This example draws similar primitives as Example 1 except it uses element indexed vertex array based colors, normals and textures. A display list, DList, object is used to store the first scene. This is then used to illustrate writing the graphics primitives to a file, restoring the display list from the file and rendering the scene in software using the RendBuf object and finally writing the resulting image to a file.

All primitive types allow color, normal, texture and data arrays. The color and normal arrays may be typed as either floats or bytes. The data arrays are not used in this example. The use of the ElemArray primitives is recommended for drawing large numbers of graphics primitives which share vertices. For example, in the limit, a large triangle mesh will contain almost the same number of unique vertices as triangles. When drawing such a mesh only the index array needs to be 3 times the number of triangles. The vertex attributes will be on the order of the number of triangles.

Three unique scenes are drawn. The first scene is redrawn after the third scene using a display list restored from an object file. It is redrawn again in software using a RendBuf object.

#include "base/base.h"
#include "vgl/vgl.h"

static Vfloat xs[4][3] = {
   {-.5,-.5, 0.}, { .5,-.5, 0.},
   { .5, .5, 0.}, {-.5, .5, 0.} };
static Vfloat ts[4] = {
   0.,1.,1.,0. };

static Vfloat cpoint[4][3] = {
   {1., 0., 0.}, {0., 0., 1.},
   {0., 1., 0.}, {1., 1., 1.} };
static Vuchar cline[4][4] = {
   {255,255,255,255}, {255,255,255,255}, {255,255,255,255}, {255,255,255,255} };
static Vuchar ctri[4][4] = {
   {255,0,0,255}, {0,255,0,255}, {0,0,255,255}, {255,225,255,0} };

static Vuint ixpoint[4] = {0,1,2,3};
static Vuint ixline[5] = {0,1,2,3,0};
static Vuint ixtri[6] = {0,1,2,0,2,3};

static Vfloat xtext[3] = {-.7,.8,0.};
static Vfloat xtext1[3] = {-.7,.7,0.};
static Vfloat ctext[3] = {1.,1.,1.};

/*----------------------------------------------------------------------
                      Drawing Element Indexed Array Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DList  *dlist;
   vgl_DrawFun *df, *dfl, *dfr;
   vgl_Bitmap *bitmap;
   vgl_Texture *texture;
   vgl_RendBuf *rendbuf;
   vgl_FBuffer *fbuffer;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();
   dfl = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* load dlist drawing functions */ 
   dlist = vgl_DListBegin();
   vgl_DListDrawFun (dlist,dfl);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,df);

                   /* draw first display to DList */ 
                   /* default projection limits are bi-unit cube */ 
   vgl_DrawFunColor (dfl,ctext);
   vgl_DrawFunText (dfl,xtext,"PolyElemArray");

                   /* set current point size to 8 pixels */
   vgl_DrawFunPointSize (dfl,8);
                   /* draw four points */ 
   vgl_DrawFunPolyElemArray (dfl,VGL_POINTS,4,ixpoint,xs,
                             VGL_COLOR_3F,cpoint,0,NULL,0,NULL,0,NULL);

                   /* set current line width to 4 */
   vgl_DrawFunLineWidth (dfl,4);
                   /* draw lineloop */ 
   vgl_DrawFunPolyElemArray (dfl,VGL_LINELOOP,4,ixline,xs,
                             VGL_COLOR_4B,cline,0,NULL,0,NULL,0,NULL);

                   /* draw triangles, white point is fully transparent */ 
   vgl_DrawFunSetMode (dfl,VGL_BLENDTRANSMODE,VGL_ON);
   vgl_DrawFunPolyElemArray (dfl,VGL_TRIANGLES,6,ixtri,xs,
                             VGL_COLOR_4B,ctri,0,NULL,0,NULL,0,NULL);
                   /* write display list to file, render again later */ 
   vgl_DListWrite (dlist,SYS_ASCII,"exam1d.asc");
   printf("Write first frame object to exam1d.asc\n");
                   /* now render */ 
   vgl_DrawFunClear (df);
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (df);

                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* now draw dashed lines and stippled polygons */ 
                   /* define bitmap */
   bitmap = vgl_BitmapBegin ();
   vgl_BitmapLoad (bitmap,BITMAP_SQUARE4);
   vgl_DrawFunBitmapDefine (df,1,bitmap);
   vgl_DrawFunClear (df);

   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"PolyElemArray");
   vgl_DrawFunText (df,xtext1,"Dashed lines, stippled polygons");

                   /* set current line type to dashed */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_DASH);
                   /* draw linestrip with 5 points */ 
   vgl_DrawFunPolyElemArray (df,VGL_LINESTRIP,5,ixline,xs,
                             VGL_COLOR_4B,cline,0,NULL,0,NULL,0,NULL);

                   /* draw triangles */ 
   vgl_DrawFunBitmapSelect (df,1);
   vgl_DrawFunPolyElemArray (df,VGL_TRIANGLES,6,ixtri,xs,
                             VGL_COLOR_4B,ctri,0,NULL,0,NULL,0,NULL);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* now draw textured lines and triangles */
                   /* define texture */
                   /* built-in is index 1 */
   texture = vgl_TextureBegin ();
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_DrawFunClear (df);
   vgl_DrawFunText (df,xtext,"PolyElemArray");
   vgl_DrawFunText (df,xtext1,"Textured lines and polygons");

                   /* select texture and draw a base color of white */ 
   vgl_DrawFunTextureSelect (df,1);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* set current line type to solid */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_SOLID);
                   /* draw linestrip with 5 points */
   vgl_DrawFunPolyElemArray (df,VGL_LINESTRIP,5,ixline,xs,
                             0,NULL,0,NULL,VGL_1DTEXTURE,ts,0,NULL);

                   /* draw triangles */
   vgl_DrawFunBitmapSelect (df,0);
   vgl_DrawFunPolyElemArray (df,VGL_TRIANGLES,6,ixtri,xs,
                             0,NULL,0,NULL,VGL_1DTEXTURE,ts,0,NULL);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);
   vgl_DrawFunTextureSelect (df,0);

                   /* redraw first frame, restore from file */ 
   vgl_DListErase (dlist);
   vgl_DListRead (dlist,SYS_ASCII,"exam1d.asc");

   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext1,"Redraw first frame");
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* now redraw first frame with RendBuf */ 
   rendbuf = vgl_RendBufBegin();
   dfr = vgl_DrawFunBegin();
   vgl_RendBufDrawFun (rendbuf,dfr);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,dfr);
   vgl_DrawFunPositionWindow (dfr,200,200,400,400);
   vgl_DrawFunOpenWindow (dfr,"exam1d");
   vgl_DrawFunClear (dfr);
   vgl_DrawFunColor (dfr,ctext);
   vgl_DrawFunText (dfr,xtext1,"Redraw first frame with RendBuf");
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (dfr);
                   /* get image buffer and write to file */
   vgl_RendBufGetFBuffer (rendbuf,&fbuffer);
   vgl_FBufferWriteBMP (fbuffer,"exam1d.bmp");
   vgl_DrawFunCloseWindow (dfr);
   printf("Redraw first frame with RendBuf, write image to exam1d.bmp\n");

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (df);
   vgl_DrawFunEnd (dfl);
   vgl_DrawFunEnd (dfr);
   vgl_BitmapEnd (bitmap);
   vgl_TextureEnd (texture);
   vgl_RendBufEnd (rendbuf);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.6 Example 1e, Drawing Element Indexed Buffer Primitives

This example draws similar primitives as Example 1d except it uses element indexed vertex buffer based colors, normals and textures. A display list, DList, object is used to store the first scene. This display list is used to render the first scene. Then the display list is written to a file to be restored later. Note that when primitives that are stored in vertex buffers are written to a file they are converted to array style primitives. the drawing function connected to the underlying OpenGLDev object must be set in the DList so that it can read the OpenGLDev dependent vertext buffers to write them as array style primitive so the file.

Three unique scenes are drawn. After the third scene is drawn, the first scene is redrawn using RendBuf using the display list created of the first scene. The drawing function connected to the underlying OpenGLDev object must be set in the RendBuf so that it can read the OpenGLDev dependent vertext buffers.

The display list is restored from the file and now contains array style primitive versions of the vertex buffer primitives. It is redrawn using OpenGLDev.

#include "base/base.h"
#include "vgl/vgl.h"

static Vfloat xs[4][3] = {
   {-.5,-.5, 0.}, { .5,-.5, 0.},
   { .5, .5, 0.}, {-.5, .5, 0.} };
static Vfloat ts[4] = {
   0.,1.,1.,0. };
static Vfloat cs[4][3] = {
   {1., 0., 0.}, {0., 0., 1.},
   {0., 1., 0.}, {1., 1., 1.} };

static Vuint ix[6] = {0,1,2,3,0,2};

static Vfloat xtext[3] = {-.7,.8,0.};
static Vfloat xtext1[3] = {-.7,.7,0.};
static Vfloat ctext[3] = {1.,1.,1.};

/*----------------------------------------------------------------------
                      Drawing Element Indexed Buffer Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
   Vint vboid, evboid;
   Vint evboof;
   Vint vboof1, vboof2;
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DList  *dlist;
   vgl_DrawFun *df, *dfl, *dfr;
   vgl_Bitmap *bitmap;
   vgl_Texture *texture;
   vgl_RendBuf *rendbuf;
   vgl_FBuffer *fbuffer;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();
   dfl = vgl_DrawFunBegin();
                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* load dlist drawing functions */
   dlist = vgl_DListBegin();
   vgl_DListDrawFun (dlist,dfl);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,df);

                   /* assume a buffer object of 100K bytes is large enough */
   vgl_DrawFunInitBuffer (df,100000,&vboid);
                   /* elem index buffer */
   vgl_DrawFunInitBuffer (df,100000,&evboid);
                   /* check to see if vertex buffer is created */
   if(vboid == 0) {
      fprintf(stderr,"Can not create buffer\n");
      exit(0);
   }
                   /* copy four points, coordinates, color */
   vgl_DrawFunCopyBuffer (df,vboid,4,xs,VGL_COLOR_3F,cs,
                          0,NULL,0,NULL,0,NULL,&vboof1);
                   /* copy four points, coordinates, texture */
   vgl_DrawFunCopyBuffer (df,vboid,4,xs,0,NULL,
                          0,NULL,VGL_1DTEXTURE,ts,0,NULL,&vboof2);
   vgl_DrawFunCopyElemBuffer (df,evboid,6,ix,&evboof);

                   /* default projection limits are bi-unit cube */ 
   vgl_DrawFunColor (dfl,ctext);
   vgl_DrawFunText (dfl,xtext,"PolyElemBuffer");

                   /* set current point size to 8 pixels */
   vgl_DrawFunPointSize (dfl,8);
                   /* draw four corner points */ 
   vgl_DrawFunPolyElemBuffer (dfl,evboid,evboof,vboid,vboof1,
                                VGL_POINTS,4,VGL_COLOR_3F,0,0,0);

                   /* set current line width to 4 */
   vgl_DrawFunLineWidth (dfl,4);
                   /* draw lineloop */ 
   vgl_DrawFunPolyElemBuffer (dfl,evboid,evboof,vboid,vboof1,
                                VGL_LINELOOP,4,VGL_COLOR_3F,0,0,0);

                   /* draw triangles */
   vgl_DrawFunPolyElemBuffer (dfl,evboid,evboof,vboid,vboof1,
                                VGL_TRIANGLES,6,VGL_COLOR_3F,0,0,0);

                  /* write display list to file, render again later */
                  /* Buffer primitives written as Array primitives */
   vgl_DListWrite (dlist,SYS_ASCII,"exam1e.asc");
   printf("Write first frame object to exam1e.asc\n");

                   /* now render */
   vgl_DrawFunClear (df);
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (df);

                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* now draw dashed lines and stippled polygons */ 
                   /* define bitmap */
   bitmap = vgl_BitmapBegin ();
   vgl_BitmapLoad (bitmap,BITMAP_SQUARE4);
   vgl_DrawFunBitmapDefine (df,1,bitmap);
   vgl_DrawFunClear (df);

   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"PolyElemBuffer");
   vgl_DrawFunText (df,xtext1,"Dashed lines, stippled polygons");

                   /* set current line type to dashed */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_DASH);
                   /* draw linestrip with 5 points */ 
   vgl_DrawFunPolyElemBuffer (df,evboid,evboof,vboid,vboof1,
                                VGL_LINESTRIP,5,VGL_COLOR_3F,0,0,0);

                   /* draw triangles */ 
   vgl_DrawFunBitmapSelect (df,1);
   vgl_DrawFunPolyElemBuffer (df,evboid,evboof,vboid,vboof1,
                                VGL_TRIANGLES,6,VGL_COLOR_3F,0,0,0);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* now draw textured lines and triangles */
                   /* define texture */
                   /* built-in is index 1 */
   texture = vgl_TextureBegin ();
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_DrawFunClear (df);
   vgl_DrawFunText (df,xtext,"PolyElemBuffer");
   vgl_DrawFunText (df,xtext1,"Textured lines and polygons");

                   /* select texture and draw a base color of white */ 
                   /* use second CopyBuffer set of data */
   vgl_DrawFunTextureSelect (df,1);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* set current line type to solid */
   vgl_DrawFunLineStyle (df,VGL_LINESTYLE_SOLID);
                   /* draw linestrip with 5 points */
   vgl_DrawFunPolyElemBuffer (df,evboid,evboof,vboid,vboof2,
                                VGL_LINESTRIP,5,0,0,VGL_1DTEXTURE,0);

                   /* draw triangles */
   vgl_DrawFunBitmapSelect (df,0);
   vgl_DrawFunPolyElemBuffer (df,evboid,evboof,vboid,vboof2,
                                VGL_TRIANGLES,6,0,0,VGL_1DTEXTURE,0);

   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

   vgl_DrawFunTextureSelect (df,0);

                   /* now redraw first frame with RendBuf */
   rendbuf = vgl_RendBufBegin();
   dfr = vgl_DrawFunBegin();
   vgl_RendBufDrawFun (rendbuf,dfr);
                   /* install OpenGLDev drawing function to access buffers */ 
   vgl_RendBufSetObject (rendbuf,VGL_DRAWFUN,df);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,dfr);
   vgl_DrawFunPositionWindow (dfr,200,200,400,400);
   vgl_DrawFunOpenWindow (dfr,"exam1d");
   vgl_DrawFunClear (dfr);
   vgl_DrawFunColor (dfr,ctext);
   vgl_DrawFunText (dfr,xtext1,"Redraw first frame with RendBuf");
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (dfr);
                   /* get image buffer and write to file */
   vgl_RendBufGetFBuffer (rendbuf,&fbuffer);
   vgl_FBufferWriteBMP (fbuffer,"exam1e.bmp");
   vgl_DrawFunCloseWindow (dfr);
   printf("Redraw first frame with RendBuf, write image to exam1e.bmp\n");

                   /* redraw first frame, restore from file */
   vgl_DListErase (dlist);
   vgl_DListRead (dlist,SYS_ASCII,"exam1e.asc");
   vgl_DListSetObject (dlist,VGL_DRAWFUN,df);

   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext1,"Redraw first frame as PolyElemArray");
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (df);
   vgl_DrawFunEnd (dfl);
   vgl_DrawFunEnd (dfr);
   vgl_BitmapEnd (bitmap);
   vgl_TextureEnd (texture);
   vgl_RendBufEnd (rendbuf);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.7 Example 2, Drawing 3D, Lighted Point, Line and Polygon Primitives

This example illustrates drawing point, line and polygon primitives in 3D with lighting, zbuffering and transformation. The window in this example is sized 400 by 300 pixels. In order for the 3D objects to not be stretched in the x direction, the orthographic projection preserves the aspect ratio of the window pixel size. An ambient light and positional light are defined an lighting is enabled. Z-buffering is also enabled. Normals are defined on all primitives. The line primitives are assumed to represent a right face and the point primitives a back face. VglTools has an option to toggle the lighting of the point and line primitives. The scene is transformed for two complete rotations. The first rotation modulates the point and line vertex colors by the lighting equations, the second rotation disables the lighting effects. A Xfm object is used to compute 4 by 4 transformation matrices which are loaded to the graphics hardware using vgl_DrawFunXfmLoad.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data, back face */ 
static Vfloat xpoints[4][3] = {
   {-3.,-3.,-3.}, { 3.,-3.,-3.},
   {-3., 3.,-3.}, { 3., 3.,-3.} };
static Vfloat vpoints[4][3] = {
   {0.,0.,-1.}, {0.,0.,-1.},
   {0.,0.,-1.}, {0.,0.,-1.} };
                   /* line data, right face */ 
static Vfloat xlineloop[4][3] = {
   {4.,-4.,4.}, { 4.,-4.,-4.},
   {4., 4.,-4.}, {4., 4., 4.} };
static Vfloat vlineloop[4][3] = {
   {1.,0.,0.}, {1.,0.,0.},
   {1.,0.,0.}, {1.,0.,0.} };
                   /* triangle data, front face */ 
static Vfloat xtristrip[4][3] = {
   {-5.,-5.,5.}, { 5.,-5.,5.},
   {-5., 5.,5.}, { 5.,5.,5.} };
static Vfloat vtristrip[4][3] = {
   {0.,0.,1.}, {0.,0.,1.},
   {0.,0.,1.}, {0.,0.,1.} };

                   /* light properties */
static Vfloat camb[3] = {
   .3,.3,.3 };
static Vfloat cdis[3] = {
   .7,.7,.7 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Drawing 3D, Lighted Point, Line and Polygon Primitives
----------------------------------------------------------------------*/
int
main()
{
   Vint i;
   Vfloat c[3];
   Vfloat tm4[4][4];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;
   vgl_Xfm     *xfm;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,300);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-13.333,13.333,-10.,10.,-10.,10.);
                   /* set lights */
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
                   /* enable zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
                   /* create transform object */
   xfm = vgl_XfmBegin();

                   /* clear frame buffer and depth buffers */
   for(i = 0; i < 100; i++) {
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (df,tm4);
                   /* first rotation, points, lines in lighted vertex color */ 
      if(i == 0) {
         vgl_DrawFunSetMode (df,VGL_POINTARRAYLIGHTMODE,VGL_ON);
         vgl_DrawFunSetMode (df,VGL_LINEARRAYLIGHTMODE,VGL_ON);
                   /* second rotation, points, lines in vertex color */ 
      } else if(i == 50) {
         vgl_DrawFunSetMode (df,VGL_POINTARRAYLIGHTMODE,VGL_OFF);
         vgl_DrawFunSetMode (df,VGL_LINEARRAYLIGHTMODE,VGL_OFF);
      }
      vgl_DrawFunClear (df);
                   /* set current color to magenta */ 
      c[0] = 1.; c[1] = 0.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPointSize (df,4);
      vgl_DrawFunPolyArray (df,VGL_POINTS,4,xpoints,0,NULL,
                            VGL_NORMAL_3F,vpoints,0,NULL,0,NULL);
                   /* set current color to cyan */ 
      c[0] = 0.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunLineWidth (df,2);
      vgl_DrawFunPolyArray (df,VGL_LINELOOP,4,xlineloop,0,NULL,
                            VGL_NORMAL_3F,vlineloop,0,NULL,0,NULL);
                   /* set current color to yellow */ 
      c[0] = 1.; c[1] = 1.; c[2] = 0.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPolyArray (df,VGL_TRISTRIP,4,xtristrip,0,NULL,
                            VGL_NORMAL_3F,vtristrip,0,NULL,0,NULL);
                   /* swap buffers */
      vgl_DrawFunSwap (df);
      vgl_DrawFunDelay (df,.2);
   }
                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);
   vgl_XfmEnd (xfm);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.8 Example 2a, Drawing Mixed 3D and "DC" primitives

This example is an extension of Example 2 in which so-called "DC" primitives are added to the scene and a polygon is outlined with a polyline. The "DC" primitives use a single 3D anchor point and a set of pixel coordinates which define the shape of the primitive relative to the anchor point. Only the anchor point is affected by transformations. The result is a "billboard" effect in which the primitive is always in the plane of the screen.

The superposition of point and line primitives onto polygon primitives requires enabling polygon depth mode to distinctly draw point and line primitives in front of polygons so that no bleeding artifacts occur while rendering.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data, back face */ 
static Vfloat xpoints[4][3] = {
   {-3.,-3.,-3.}, { 3.,-3.,-3.},
   {-3., 3.,-3.}, { 3., 3.,-3.} };
static Vfloat vpoints[4][3] = {
   {0.,0.,-1.}, {0.,0.,-1.},
   {0.,0.,-1.}, {0.,0.,-1.} };
                   /* line data, right face */ 
static Vfloat xlineloop[4][3] = {
   {4.,-4.,4.}, { 4.,-4.,-4.},
   {4., 4.,-4.}, {4., 4., 4.} };
static Vfloat vlineloop[4][3] = {
   {1.,0.,0.}, {1.,0.,0.},
   {1.,0.,0.}, {1.,0.,0.} };
                   /* triangle data, front face */ 
static Vfloat xtristrip[4][3] = {
   {-5.,-5.,5.}, { 5.,-5.,5.},
   {-5., 5.,5.}, { 5.,5.,5.} };
static Vfloat vtristrip[4][3] = {
   {0.,0.,1.}, {0.,0.,1.},
   {0.,0.,1.}, {0.,0.,1.} };
static Vfloat xoutline[4][3] = {
   {-5.,-5.,5.}, { 5.,-5.,5.},
   { 5.,5.,5.}, {-5., 5.,5.} };

                   /* DC anchor */
static Vfloat xdc[3] =  {-3.,-3.,-3.};
                   /* DC rectangle */ 
Vint dcrect[4][3] = {
   {5,5,0}, {50,5,0},
   {50,30,0}, {5,30,0} };
Vint dctext[3] = {10,10,0};

                   /* light properties */
static Vfloat camb[3] = {
   .3,.3,.3 };
static Vfloat cdis[3] = {
   .7,.7,.7 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                    Drawing Mixed 3D and "DC" primitives
----------------------------------------------------------------------*/
int
main()
{
   Vint i;
   Vfloat c[3];
   Vfloat tm4[4][4];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;
   vgl_Xfm     *xfm;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,300);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-13.333,13.333,-10.,10.,-10.,10.);
                   /* set lights */
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
                   /* enable zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
                   /* enable polygon offset */ 
   vgl_DrawFunPolygonOffset (df,1.,2.);
   vgl_DrawFunSetMode (df,VGL_POLYGONDEPTHMODE,VGL_ON);

                   /* create transform object */
   xfm = vgl_XfmBegin();

                   /* clear frame buffer and depth buffers */
   for(i = 0; i < 50; i++) {
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (df,tm4);
      vgl_DrawFunClear (df);

                   /* draw points on corners of back face */
                   /* set current color to magenta */ 
      c[0] = 1.; c[1] = 0.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPointSize (df,4);
      vgl_DrawFunPolyArray (df,VGL_POINTS,4,xpoints,0,NULL,
                            VGL_NORMAL_3F,vpoints,0,NULL,0,NULL);

                   /* draw line loop for right face */
                   /* set current color to cyan */ 
      c[0] = 0.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunLineWidth (df,2);
      vgl_DrawFunPolyArray (df,VGL_LINELOOP,4,xlineloop,0,NULL,
                            VGL_NORMAL_3F,vlineloop,0,NULL,0,NULL);

                   /* draw outlined quadrilateral for front face */
                   /* set current color to white */ 
      c[0] = 1.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPolyLineArray (df,VGL_LINELOOP,4,xoutline,0,NULL,
                                0,NULL,0,NULL,0,NULL);
                   /* set current color to yellow */ 
      c[0] = 1.; c[1] = 1.; c[2] = 0.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPolyArray (df,VGL_TRISTRIP,4,xtristrip,0,NULL,
                            VGL_NORMAL_3F,vtristrip,0,NULL,0,NULL);

                   /* draw a "billboard" using DC primitives */
      c[0] = 1.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunLineWidth (df,1);
      vgl_DrawFunPolyLineDC (df,VGL_LINELOOP,4,xdc,dcrect);
      c[0] = 1.; c[1] = 0.; c[2] = 0.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunPolygonDC (df,VGL_QUADS,4,xdc,dcrect);
      c[0] = 1.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (df,c);
      vgl_DrawFunTextDC (df,xdc,dctext,"Text");
                   /* swap buffers */
      vgl_DrawFunSwap (df);
      vgl_DrawFunDelay (df,.2);
   }
                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);
   vgl_XfmEnd (xfm);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.9 Example 3, Drawing Hello World

This example is an extension of the "First Program" and illustrates the changes required to use the OpenGLDev module drawing to a Microsoft Windows window or an X Window.

#include "base/base.h"
#include "vgl/vgl.h"

/*----------------------------------------------------------------------
                      Hello World in OpenGLDev
----------------------------------------------------------------------*/
int
main()
{
   Vfloat x[3], c[3];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open windows */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"OpenGL X Windows");
#else
   vgl_DrawFunOpenWindow (df,"OpenGL Microsoft Windows");
#endif

                   /* draw hello world in raster font */ 
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World");
   vgl_DrawFunSwap (df);
                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.10 Example 3a, Drawing Hello World in Multiple Raster Fonts

This example is an extension of Example 3 and illustrates the use of multiple raster fonts. Raster fonts are loaded using the RasFont module. They are defined, selected and drawn using the drawing functions vgl_DrawFunRasFontDefine, vgl_DrawFunRasFontSelect and vgl_DrawFunText and vgl_DrawFunTextDC. The RasFont module supports a few built-in raster fonts and is also able to read and load any X windows or Microsoft Windows font. The X windows fonts available on an X server may be listed using the xlsfonts command. A RasFont object should be created for each user defined raster font.

In this example, three RasFont objects are created to hold two built-in fonts and one font loaded from the window system. The X windows font is loaded using vgl_RasFontLoadXFont. The Microsoft Windows font is loaded by first creating an HFONT object and using vgl_RasFontLoadWINFont with the HFONT object as an argument.

The RASFONT_NORMAL7X11 font is scaled by a factor of 2 using vgl_RasFontSetSize. The function vgl_DrawFunRasFontDefine is used to associate a raster font with a raster font index. The RasFont object is copied by this operation. Any subsequent changes to the RasFont object are not detected by the graphics device interface until vgl_DrawFunRasFontDefine is called again with the RasFont object as an argument. Once defined, a raster font may be selected as the current raster font for drawing using vgl_DrawFunRasFontSelect. The default raster font is always raster font index 0 and is predefined.

This example also illustrates drawing the strings to OpenGLDev and X11Dev or GDIDev modules. Set the variable dev to select a device, it is set to 1 (OpenGLDev) by default.

#include "base/base.h"
#include "vgl/vgl.h"

/*----------------------------------------------------------------------
                      Hello World
----------------------------------------------------------------------*/
int
main()
{
   Vint i;
   Vfloat x[3], c[3];
   Vint italic, weight, length;
   Vint width, height, offset, base;
   Vchar fontname[256];
   Vfloat path[3], plane[3];
   Vint dev;
   Vchar devname[256];
   Vint rasfontnumber, rasfontindices[10];
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#else
   HFONT hfont;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_SVGDev *svgdev;
#ifdef VKI_WIND_X11
   vgl_X11Dev    *x11dev;
#else
   vgl_GDIDev      *gdidev;
#endif
   vgl_RasFont *rasfont[4];
   vgl_DrawFun *df;

                   /* 1 = OpenGLDev, 2 = GDIDev or X11Dev */
                   /* 4 = SVGDev */
   dev = 2;
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
      display = XOpenDisplay (0);
      screen = DefaultScreen (display);
   if(dev == 1  ||  dev == 2) {
   }
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
      strcpy(devname,"OpenGL");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,df);
      strcpy(devname,"X11");
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,df);
      strcpy(devname,"GDI");
#endif
   } else if(dev == 4) {
      svgdev = vgl_SVGDevBegin();
      vgl_SVGDevDrawFun (svgdev,df);
      strcpy(devname,"exam3a.svg");
   }
                   /* open windows */
   vgl_DrawFunPositionWindow (df,200,300,600,450);
   vgl_DrawFunOpenWindow (df,devname);
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* create raster font object */ 
   rasfont[0] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[0],RASFONT_NORMAL7X11);
   vgl_RasFontSetSize (rasfont[0],2);
   vgl_DrawFunRasFontDefine (df,1,rasfont[0]);

   rasfont[1] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[1],RASFONT_NORMALBOLD8X14);
   vgl_DrawFunRasFontDefine (df,2,rasfont[1]);
   rasfont[2] = vgl_RasFontBegin();
#ifdef VKI_WIND_X11
   vgl_RasFontLoadXFont (rasfont[2],display,"9x15");
#else
   hfont = CreateFont(15,9,0,0,0,0,0,0,0,0,0,0,FIXED_PITCH|FF_DONTCARE,"Arial");
   vgl_RasFontSetParami (rasfont[2],RASFONT_ANTIALIAS,SYS_ON);
   vgl_RasFontLoadWINFont (rasfont[2],hfont);
#endif
                   /* query and print some inherent font properties */ 
   vgl_RasFontGetString (rasfont[2],RASFONT_FONTNAME,fontname);
   vgl_RasFontGetMetrics (rasfont[2],&width,&height,&offset,&base);
   vgl_RasFontGetInteger (rasfont[2],RASFONT_WEIGHT,&weight);
   vgl_RasFontGetInteger (rasfont[2],RASFONT_ITALIC,&italic);
   printf("Font name = %s\n",fontname);
   printf("width = %d, height= %d\n",width,height);
   printf("weight= %d\n",weight);
   printf("italic= %d\n",italic);

                   /* query length of string */ 
   vgl_RasFontLength (rasfont[2],"Hello World",&length);
   printf("length= %d\n",length);
   vgl_DrawFunRasFontDefine (df,3,rasfont[2]);

                   /* orientable raster font */ 
   rasfont[3] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[3],RASFONT_QUALITY9X13);
   vgl_RasFontSetParami (rasfont[3],RASFONT_TEXTPLANE,SYS_ON);
   vgl_RasFontSetParami (rasfont[3],RASFONT_DEVICESIZE,SYS_OFF);
   vgl_RasFontSetPixelSize (rasfont[3],.01);
   vgl_DrawFunRasFontDefine (df,4,rasfont[3]);

                   /* query number of raster fonts defined */ 
                   /* this query will include the default font index 0 */
   vgl_DrawFunGetInteger (df,VGL_RASFONTNUMBER,&rasfontnumber);
   printf("number of defined raster fonts= %d\n",rasfontnumber);
   vgl_DrawFunGetInteger (df,VGL_RASFONTINDICES,rasfontindices);
   printf("indices of defined raster fonts\n");
   for(i = 0; i < rasfontnumber; i++) {
      printf("index= %d\n",rasfontindices[i]);
   }
                   /* draw text in each raster font */ 
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   x[0] = -1.3; x[1] =  .8; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World, Default");
   vgl_DrawFunRasFontSelect (df,1);
   x[0] = -1.3; x[1] -= .2; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World, RASFONT_NORMAL7X11");
   vgl_DrawFunRasFontSelect (df,2);
   x[0] = -1.3; x[1] -= .2; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World, RASFONT_NORMALBOLD8X14");
   vgl_DrawFunRasFontSelect (df,3);
   x[0] = -1.3; x[1] -= .2; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World, 9x15");
   x[0] = -1.3; x[1] -= .15; x[2] = 0.;
   vgl_DrawFunText (df,x,"the quick brown fox jumps over the lazy dog");
   x[0] = -1.3; x[1] -= .15; x[2] = 0.;
   vgl_DrawFunText (df,x,"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG");
   x[0] = -1.3; x[1] -= .15; x[2] = 0.;
   vgl_DrawFunText (df,x,"0123456789 !\"#$%&\\'()*+,-./:;<=>?@[]^_`{|}~");
   vgl_DrawFunRasFontSelect (df,4);
   x[0] = -1.3; x[1] -= .25; x[2] = 0.;
   path[0] = 2.;
   path[1] = -.2;
   path[2] = 0.;
   plane[0] = 0.;
   plane[1] = 1.;
   plane[2] = 0.;
   vgl_DrawFunTextPlane (df,path,plane);
   vgl_DrawFunText (df,x,"Hello World, TextPlane");
                   /* vary anchor */ 
   vgl_DrawFunRasFontSelect (df,0);
   x[0] = -.5; x[1] -= .25; x[2] = 0.;
   vgl_DrawFunSetMode (df,VGL_TEXTANCHORMODE,VGL_LEFT);
   vgl_DrawFunText (df,x,"Hello World, Default");
   x[0] = -.5; x[1] -= .08; x[2] = 0.;
   vgl_DrawFunSetMode (df,VGL_TEXTANCHORMODE,VGL_CENTER);
   vgl_DrawFunText (df,x,"Hello World, Default");
   x[0] = -.5; x[1] -= .08; x[2] = 0.;
   vgl_DrawFunSetMode (df,VGL_TEXTANCHORMODE,VGL_RIGHT);
   vgl_DrawFunText (df,x,"Hello World, Default");
   vgl_DrawFunSetMode (df,VGL_TEXTANCHORMODE,VGL_BOTTOMLEFT);

                   /* now vertical text */ 
   vgl_DrawFunRasFontSelect (df,2);
   vgl_DrawFunSetMode (df,VGL_TEXTDIRECTIONMODE,VGL_TOP);
   x[0] = 1.; x[1] = -.8; x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World, vertical RASFONT_NORMALBOLD8X14");

   vgl_DrawFunSwap (df);
                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   } else if(dev == 4) {
      vgl_SVGDevEnd (svgdev);
   }
   vgl_DrawFunEnd (df);
   vgl_RasFontEnd (rasfont[0]);
   vgl_RasFontEnd (rasfont[1]);
   vgl_RasFontEnd (rasfont[2]);
   vgl_RasFontEnd (rasfont[3]);

                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }

                   /* clean up */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#else
   DeleteObject (hfont);
#endif
   return 0;
}
                                                                           


Table of Contents

13.11 Example 3b, Drawing Hello World in Wide Character Strings

This example is an extension of Example 3a and illustrates the use of drawing wide character strings to OpenGLDev, X11Dev and RendBuf devices. The C preprocessor symbol VKI_WIDECHAR must have been used to compile all of DevTools as well as this example. In this case the type Vtchar is typedef'ed to wchar_t in the calls to vgl_DrawFunText and vgl_RasFontLength. All string variables which are passed to these functions must be typed as Vtchar or explicitly as wchar_t. All string literals must be made wide strings by prepending the string or individual characters of the string with an "L".

The string variable euro contains the Euro symbol and is drawn in a wide character font which contains the symbol.

This example also illustrates drawing the strings to OpenGLDev, X11Dev and RendBuf modules. Set the variable dev to select a device, it is set to 1 (OpenGLDev) by default.

#include "base/base.h"
#include "vgl/vgl.h"
#include <stdio.h>
#include <wchar.h>

/*----------------------------------------------------------------------
                      Hello World, Wide Characters
----------------------------------------------------------------------*/
int
main()
{
   Vfloat x[3], c[3];
   Vint italic, weight, length;
   Vfloat path[3], plane[3];
   static wchar_t euro[] = 
      { L'U',L'n',L'i',L'c',L'o',L'd',L'e',L' ',L'E',L'u',L'r',L'o',L'=',L' ',
        0x20ac,L'\0'};
   Vint dev;
   Vchar ftfile[256];
   Vint scalableflag, ierr;
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
   vgl_X11Dev  *x11dev;
#else
   HFONT hfont;
   vgl_GDIDev  *gdidev;
#endif
   vgl_OpenGLDev *ogldev;
   vgl_RendBuf *rendbuf;
   vgl_FBuffer *fbuffer;
   vgl_RasFont *rasfont[4], *rasft;
   vgl_DrawFun *df;

                   /* 0= RendBuf, 1= OpenGLDev, 2= X11Dev or GDIDev */ 
   dev = 1;
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,df);
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,df);
#endif
   } else if(dev == 0) {
      rendbuf = vgl_RendBufBegin();
      vgl_RendBufDrawFun (rendbuf,df);
   }
                   /* open windows */
   vgl_DrawFunPositionWindow (df,400,400,480,360);
   if(dev == 1) {
      vgl_DrawFunOpenWindow (df,"OpenGL Window");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_DrawFunOpenWindow (df,"X11 Window");
#else
      vgl_DrawFunOpenWindow (df,"GDI Window");
#endif
   } else if(dev == 0) {
      vgl_DrawFunOpenWindow (df,"RendBuf Window");
   }
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* create raster font object */ 
   rasfont[0] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[0],RASFONT_NORMAL7X11);
   vgl_DrawFunRasFontDefine (df,1,rasfont[0]);
   rasfont[1] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[1],RASFONT_NORMALBOLD8X14);
   vgl_DrawFunRasFontDefine (df,2,rasfont[1]);
   rasfont[2] = vgl_RasFontBegin();
#ifdef VKI_WIND_X11
   vgl_RasFontLoadXFont (rasfont[2],display,
      "-adobe-courier-bold-o-normal--14-100-100-100-m-90-iso10646-1");
                   /* if can not find font, try another */ 
   if(vgl_RasFontError(rasfont[2])) {
      vgl_RasFontLoadXFont (rasfont[2],display,
         "-bitstream-bitstream charter-bold-i-normal--0-0-0-0-p-0-iso10646-1");
   }
#else
   hfont = CreateFont(15,9,0,0,0,0,0,0,0,0,0,0,FIXED_PITCH|FF_DONTCARE,
                      TEXT("Arial"));
   vgl_RasFontLoadWINFont (rasfont[2],hfont);
#endif
                   /* query and print some inherent font properties */ 
   vgl_RasFontGetInteger (rasfont[2],RASFONT_WEIGHT,&weight);
   vgl_RasFontGetInteger (rasfont[2],RASFONT_ITALIC,&italic);
   printf("weight= %d\n",weight);
   printf("italic= %d\n",italic);

                   /* set size */ 
   vgl_RasFontSetSize (rasfont[2],2);
   vgl_DrawFunRasFontDefine (df,3,rasfont[2]);

                   /* orientable raster font */ 
   rasfont[3] = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont[3],RASFONT_QUALITY9X13);
   vgl_RasFontSetParami (rasfont[3],RASFONT_TEXTPLANE,SYS_ON);
   vgl_RasFontSetParami (rasfont[3],RASFONT_DEVICESIZE,SYS_OFF);
   vgl_RasFontSetPixelSize (rasfont[3],.01);
   vgl_DrawFunRasFontDefine (df,4,rasfont[3]);

                   /* draw hello world in each raster font */ 
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   x[0] = -.8; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunText (df,x,L"Hello World, Default");
   vgl_DrawFunRasFontSelect (df,1);
   x[0] = -.8; x[1] = -.1; x[2] = 0.;
   vgl_DrawFunText (df,x,L"Hello World, RASFONT_NORMAL7X11");
   vgl_DrawFunRasFontSelect (df,2);
   x[0] = -.8; x[1] = -.2; x[2] = 0.;
   vgl_DrawFunText (df,x,L"Hello World, RASFONT_NORMALBOLD8X14");
   vgl_DrawFunRasFontSelect (df,3);
   x[0] = -.8; x[1] = -.4; x[2] = 0.;
                   /* query length of string */ 
   vgl_RasFontLength (rasfont[2],euro,&length);
   printf("length= %d\n",length);
   vgl_DrawFunText (df,x,euro);
   vgl_DrawFunRasFontSelect (df,4);
   x[0] = -.8; x[1] = -.6; x[2] = 0.;
   path[0] = 2.;
   path[1] = -.2;
   path[2] = 0.;
   plane[0] = 0.;
   plane[1] = 1.;
   plane[2] = 0.;
   vgl_DrawFunTextPlane (df,path,plane);
   vgl_DrawFunText (df,x,L"Hello World, TextPlane");
   vgl_DrawFunRasFontSelect (df,0);
   x[0] = -.8; x[1] = -.8; x[2] = 0.;
   vgl_DrawFunText (df,x,L"Hello World, Default");
                   /* create freetype raster font */
   rasft = vgl_RasFontBegin();
   strcpy(ftfile,"../fonts/DejaVuSerif-Bold.ttf");
   strcpy(ftfile,"../fonts/OpenSans-Regular.ttf");
   strcpy(ftfile,"/tmp/arial.ttf");
   vgl_RasFontFreeTypeParam (rasft,ftfile,RASFONT_FREETYPE_SCALABLE,
                             &scalableflag);
   ierr = vgl_RasFontError (rasfont[0]);
   if(ierr) {
      printf("Error loading FreeType file, %s\n",ftfile);
      scalableflag = 0;
   }
   c[0] = 0.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   if(scalableflag) {
      vgl_RasFontLoadFreeType (rasft,14,ftfile);
      vgl_DrawFunRasFontDefine (df,1,rasft);
      vgl_DrawFunRasFontSelect (df,1);
      x[0] = -.8; x[1] = .6; x[2] = 0.;
      vgl_DrawFunText (df,x,L"FreeType scalable");
      x[0] = -.8; x[1] = .5; x[2] = 0.;
      vgl_DrawFunText (df,x,euro);
   }
   vgl_RasFontEnd (rasft);
   vgl_DrawFunSwap (df);
                   /* write out image */ 
   if(dev == 0) {
      fbuffer = vgl_FBufferBegin ();
      vgl_DrawFunFBufferRead (df,0,0,0,0,fbuffer);
      vgl_FBufferWriteGIF (fbuffer,"exam3b.gif");
      vgl_FBufferEnd (fbuffer);
   }
                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   } else if(dev == 0) {
      vgl_RendBufEnd (rendbuf);
   }
   vgl_DrawFunEnd (df);
   vgl_RasFontEnd (rasfont[0]);
   vgl_RasFontEnd (rasfont[1]);
   vgl_RasFontEnd (rasfont[2]);
   vgl_RasFontEnd (rasfont[3]);

                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }
                   /* clean up */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#else
   DeleteObject (hfont);
#endif
   return 0;
}


Table of Contents

13.12 Example 3c, Drawing Hello World in OpenGL and GDI to a Pixmap

This example illustrates drawing to a Microsoft Windows device context, hDC, using OpenGL and GDI. A window is opened and the hDC is obtained using GetDC. The OpenGLDev object is prepared for drawing to a hDC by calling vgl_OpenGLDevVisualWindow with flags for a generic pixmap. The size of the device must be set using vgl_OpenGLDevConfigureWindow. The size is usually the same as the associated window but it need not be. Drawing using OpenGL will be affected by the normal OpenGL viewing transformations, drawing using GDI is independent of these OpenGL viewing transformations. A simple loop is entered which draws Hello World OpenGL using OpenGL and Hello World GDI using GDI. The drawing in OpenGL is done first using a call to vgl_DrawFunFlush to flush OpenGL drawing. The drawing using GDI is done second using a call to ShowWindow is flush the GDI drawing to the window. Hit the ESC key to terminate the loop.
#include <windows.h>
#include "base/base.h"
#include "vgl/vgl.h"

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

/*----------------------------------------------------------------------
                      Drawing Hello World in OpenGL and GDI to a Pixmap
----------------------------------------------------------------------*/
int
main()
{
   WNDCLASS wc;
   HWND hWnd;
   HDC hDC;
   MSG msg;
   BOOL quit = FALSE;
   HINSTANCE hInstance;
   vgl_OpenGLDev *opengldev;
   vgl_DrawFun *df;
   Vfloat c[3], x[3];
   Vint iparams[4];
   char stg[33];
   int len, iref;
   COLORREF textcolor, backcolor;

   hInstance = GetModuleHandle (NULL);
                   /* register window class */
   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = WndProc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
   wc.hInstance = hInstance;
   wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
   wc.hCursor = LoadCursor(NULL,IDC_ARROW);
   wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
   wc.lpszMenuName = NULL;
   wc.lpszClassName = "exam3c";
   RegisterClass( &wc );

                   /* create window */
   hWnd = CreateWindow ("exam17","exam17", 
                        WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS|WS_CLIPCHILDREN,
                        0,0,400,400,
                        NULL,NULL,hInstance,NULL);
   ShowWindow (hWnd,SW_SHOWDEFAULT);
                   /* get window device context */
   hDC = GetDC (hWnd);

   vgl_OpenGLDevConnectWIN ();
                   /* create drawing functions */
   df = vgl_DrawFunBegin();
                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);
                   /* set visual for generic bitmap */
   vgl_OpenGLDevVisualWindow (opengldev,VGL_VISUAL_PIXMAP|VGL_VISUAL_GENERIC);
                   /* configure origin and size */
   iparams[0] = 0;
   iparams[1] = 0;
   iparams[2] = 400;
   iparams[3] = 400;
   vgl_OpenGLDevConfigureWindow (opengldev,VGL_WINDOWORIGINSIZE,iparams);
   vgl_OpenGLDevConnectWindow (opengldev,(Vword)hDC);

   vgl_DrawFunProjOrtho (df,-1.,1.,-1.,1.,-1.,1.);

                   /* count number of updates */
   iref = 0;
                   /* program loop */
   while(!quit) {
                   /* check for messages */
      if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
                   /* handle or dispatch messages */
         if(msg.message == WM_QUIT) {
            quit = TRUE;
         } else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }
      } else {
         iref += 1;
         vgl_DrawFunClear (df);
                   /* draw text in white using OpenGL */
         c[0] = 1.; c[1] = 1.; c[2] = 1.;
         vgl_DrawFunColor (df,c);
         x[0] = 0.; x[1] = 0.; x[2] = 0.;
         vgl_DrawFunText (df,x,"Hello World OpenGL");
         vgl_DrawFunFlush (df);
                   /* draw text in red using GDI */
         sprintf(stg,"Hello World GDI %d",iref);
         len = (int)strlen(stg);
         backcolor = RGB(255,255,255);
         textcolor = RGB(255,0,0);
         SetBkColor (hDC,backcolor);
         SetTextColor (hDC,textcolor);
         TextOut (hDC,30,30,stg,len);
         ShowWindow (hWnd,SW_SHOWDEFAULT);
                   /* wait a second */
         vgl_DrawFunDelay (df,1.);
                   /* only let it go on for 100 iterations */ 
         if(iref == 100)  break;
      }
   }

   DestroyWindow (hWnd);

   return msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message) {
      case WM_CREATE:
         return 0;

      case WM_CLOSE:
         PostQuitMessage(0);
         return 0;

      case WM_DESTROY:
         return 0;

      case WM_KEYDOWN:
         switch (wParam) {
            case VK_ESCAPE:
               PostQuitMessage(0);
               return 0;
            }
            return 0;

      default:
         return DefWindowProc( hWnd, message, wParam, lParam );
   }
}


Table of Contents

13.13 Example 3d, Drawing Hello World with FreeType

This example is an extension of Example 3a and illustrates the use of drawing FreeType character strings to OpenGLDev, X11Dev and RendBuf devices. The C preprocessor symbol VKI_LIBAPI_FREETYPE must have been used to compile the RasFont object. FreeType font files can contain fixed and or scaleable fonts. Query for the number of fixed fonts or whether a scaleable font exists using vgl_RasFontFreeTypeParam. Use vgl_RasFontFixedFreeType to query for the size of each fixed point font. Use vgl_RasFontLoadFixedFreeType to load a particular fixed point font. Use vgl_RasFontLoadFreeType to load a scaleable font with a requested size.

This example also illustrates drawing the strings to OpenGLDev, X11Dev and RendBuf modules. Set the variable dev to select a device, it is set to 1 (OpenGLDev) by default.

#include "base/base.h"
#include "vgl/vgl.h"

/*----------------------------------------------------------------------
                      Drawing Hello World with FreeType
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   Vint i;
   Vfloat x[3], c[3];
   Vint dev;
   Vchar devname[256];
   Vint numfixed, scalableflag, (*fixed)[2];
   Vchar fontfile[256];
   Vint ierr;
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#else
   HFONT hfont;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_SVGDev *svgdev;
   vgl_RendBuf *rendbuf;
#ifdef VKI_WIND_X11
   vgl_X11Dev    *x11dev;
#else
   vgl_GDIDev      *gdidev;
#endif
   vgl_RasFont *rasfont[4];
   vgl_DrawFun *df;
   vgl_FBuffer *fbuffer;

                   /* check input arguments */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s fontfile\n",argv[0]);
      fprintf(stderr," fontfile is blank, '../fonts/DejaVuSerif-Bold.ttf' is assumed\n");
      strcpy(fontfile,"../fonts/DejaVuSerif-Bold.ttf");
   } else {
      strcpy(fontfile,argv[1]);
   }
                   /* 0 = RendBuf, 1 = OpenGLDev, 2 = GDIDev or X11Dev,
                      4 = SVGDev */
   dev = 0;
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   if(dev == 1  ||  dev == 2) {
      display = XOpenDisplay (0);
      screen = DefaultScreen (display);
   }
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 0) {
      rendbuf = vgl_RendBufBegin();
      vgl_RendBufDrawFun (rendbuf,df);
      strcpy(devname,"exam3d.bmp");
   } else if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
      strcpy(devname,"OpenGL");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,df);
      strcpy(devname,"X11");
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,df);
      strcpy(devname,"GDI");
#endif
   } else if(dev == 4) {
      svgdev = vgl_SVGDevBegin();
      vgl_SVGDevDrawFun (svgdev,df);
      strcpy(devname,"exam3d.svg");
   }
                   /* open windows */
   vgl_DrawFunPositionWindow (df,200,300,600,450);
   vgl_DrawFunOpenWindow (df,devname);
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* create raster font object */ 
   rasfont[0] = vgl_RasFontBegin();
                   /* query for font parameters */ 
   vgl_RasFontFreeTypeParam (rasfont[0],fontfile,RASFONT_FREETYPE_NUMFIXED,
                             &numfixed);
   ierr = vgl_RasFontError (rasfont[0]);
   if(ierr) {
      printf("Error loading FreeType file, %s\n",fontfile);
      return 1;
   }
   printf("numfixed= %d\n",numfixed);
   vgl_RasFontFreeTypeParam (rasfont[0],fontfile,RASFONT_FREETYPE_SCALABLE,
                             &scalableflag);
   printf("scalableflag= %d\n",scalableflag);
                   /* load fixed font */ 
   if(numfixed) {
      fixed = (Vint(*)[2])malloc(2*numfixed*sizeof(Vint));
      vgl_RasFontFixedFreeType (rasfont[0],fontfile,fixed);
      for(i = 0; i < numfixed; i++) {
         printf("width= %d, height= %d\n",fixed[i][0],fixed[i][1]);
      }
                   /* load first fixed font */ 
      vgl_RasFontLoadFixedFreeType (rasfont[0],fixed[0][1],fontfile);
      free(fixed);
                   /* load scalable font */ 
   } else {
      vgl_RasFontLoadFreeType (rasfont[0],16,fontfile);
   }
   vgl_DrawFunRasFontDefine (df,1,rasfont[0]);
   vgl_DrawFunRasFontSelect (df,1);

   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);

                   /* draw a pinwheel of strings */ 
   vgl_DrawFunSetMode (df,VGL_TEXTANCHORMODE,VGL_LEFT);
   x[0] = .0; x[1] =  0.; x[2] = 0.;
   vgl_DrawFunSetMode (df,VGL_TEXTDIRECTIONMODE,VGL_RIGHT);
   vgl_DrawFunText (df,x,"Hello World, FREETYPE");
   vgl_DrawFunSetMode (df,VGL_TEXTDIRECTIONMODE,VGL_LEFT);
   vgl_DrawFunText (df,x,"Hello World, FREETYPE");
   vgl_DrawFunSetMode (df,VGL_TEXTDIRECTIONMODE,VGL_TOP);
   vgl_DrawFunText (df,x,"Hello World, FREETYPE");
   vgl_DrawFunSetMode (df,VGL_TEXTDIRECTIONMODE,VGL_BOTTOM);
   vgl_DrawFunText (df,x,"Hello World, FREETYPE");

   vgl_DrawFunSwap (df);
   if(dev == 0) {
      fbuffer = vgl_FBufferBegin ();
      vgl_DrawFunFBufferRead (df,0,0,0,0,fbuffer);
      vgl_FBufferWriteBMP (fbuffer,devname);
      vgl_FBufferEnd (fbuffer);
   }
                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   if(dev == 0) {
      vgl_RendBufEnd (rendbuf);
   } else if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   } else if(dev == 4) {
      vgl_SVGDevEnd (svgdev);
   }
   vgl_DrawFunEnd (df);
   vgl_RasFontEnd (rasfont[0]);

                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }

                   /* clean up */
#ifdef VKI_WIND_X11
   if(dev == 1  ||  dev == 2) {
      XCloseDisplay (display);
   }
#else
   DeleteObject (hfont);
#endif
   return 0;
}


Table of Contents

13.14 Example 4, Drawing to a X or GDI Window and an OpenGL Window

The following example illustrates the use of drawing functions to manage the drawing to two graphics devices, a X or GDI window using X11Dev or GDIDev and an OpenGL window using OpenGLDev. Initially, in an X windows environment, the X display must be opened and a screen selected. The class functions vgl_X11DevConnectX and vgl_OpenGLDevConnectX are used to inform the graphics device modules of the display information. In Microsoft windows the class functions vgl_GDIDevConnectWIN and vgl_OpenGLDevConnectWIN are required.

A drawing function object and device object is created for each of the devices. The drawing function objects, dfxw and dfgl are loaded with function pointers by vgl_X11DevDrawFun or vgl_GDIDevDrawFun and vgl_OpenGLDevDrawFun respectively. At this point all further drawing and control of the devices are handled through the appropriate drawing function.

Window dimensions are requested and two windows are opened. A Gouraud shaded triangle is drawn to each device, the system waits 10 seconds, closes each window and terminates.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_triangle(vgl_DrawFun *df);

static Vfloat xtri[3][3] = {
   {0.,.5,0.}, {.5,-.5,0.}, {-.5,-.5,0.} };
static Vfloat ctri[3][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.} };

/*----------------------------------------------------------------------
                      Draw a Gouraud shaded triangle
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

#ifdef VKI_WIND_X11
   vgl_X11Dev *x11dev;
#else
   vgl_GDIDev *gdidev;
#endif
   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *dfgl, *dfxw;
   vgl_DrawFun *df;

                   /* connect to X or Windows*/
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_X11DevConnectX (display,screen);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_GDIDevConnectWIN ();
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   dfgl  = vgl_DrawFunBegin();
   dfxw = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
#ifdef VKI_WIND_X11
   x11dev = vgl_X11DevBegin();
   vgl_X11DevDrawFun (x11dev,dfxw);
#else
   gdidev = vgl_GDIDevBegin();
   vgl_GDIDevDrawFun (gdidev,dfxw);
#endif
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfgl);

                   /* open windows and file */
   vgl_DrawFunPositionWindow (dfxw,100,100,300,200);
   vgl_DrawFunOpenWindow (dfxw,"System window");
   vgl_DrawFunPositionWindow (dfgl,400,400,400,300);
   vgl_DrawFunOpenWindow (dfgl,"OpenGL window");

                   /* draw to X11 window first */
   df = dfxw;
   draw_triangle (df);

                   /* draw to OpenGL window second */
   df = dfgl;
   draw_triangle (df);

                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows and file */ 
   vgl_DrawFunCloseWindow (dfxw);
   vgl_DrawFunCloseWindow (dfgl);

                   /* disconnect and free objects */ 
#ifdef VKI_WIND_X11
   vgl_X11DevEnd (x11dev);
   vgl_X11DevDisconnect ();
#else
   vgl_GDIDevEnd (gdidev);
   vgl_GDIDevDisconnect ();
#endif
   vgl_OpenGLDevEnd (ogldev);
   vgl_OpenGLDevDisconnect ();
   vgl_DrawFunEnd (dfgl);
   vgl_DrawFunEnd (dfxw);

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

static void
draw_triangle(vgl_DrawFun *df)
{
   Vfloat c[3];
                   /* draw triangle */
   vgl_DrawFunSetWindow (df);
   vgl_DrawFunClear (df);

   vgl_DrawFunPolygonColor (df,VGL_POLYGON,3,xtri,ctri,VGL_NOSHADE,NULL);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,3,xtri);
   vgl_DrawFunSwap (df);
}


Table of Contents

13.15 Example 4a, Using a FBuffer Object with Example 4

This example illustrates using a FBuffer (Frame Buffer) object to read an image from a X or GDI window and write it to an OpenGL window and a This is a modification of Example 4 in that rather than re-rendering the Gouraud shaded triangle to the OpenGL window, the contents of the initial rendering in the X or GDI window are read into a FBuffer object and are written to a OpenGL window and directly to a .gif file named exam4a.gif. FBuffer objects provide a device independent way to read, store and write the contents of any graphics device frame buffer. The FBuffer object also has functions to write its contents directly to certain file formats (eg. window and generate hardcopy.

In this example, the FBuffer object is used to read and write the entire contents of the X window. In general however, a FBuffer object supports reading and writing of any sub-rectangle of a graphics device.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_triangle(vgl_DrawFun *df);

static Vfloat xtri[3][3] = {
   {0.,.5,0.}, {.5,-.5,0.}, {-.5,-.5,0.} };
static Vfloat ctri[3][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.} };

/*----------------------------------------------------------------------
                      Draw a Gouraud shaded triangle
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif
                                                                                
#ifdef VKI_WIND_X11
   vgl_X11Dev *x11dev;
#else
   vgl_GDIDev *gdidev;
#endif
   vgl_OpenGLDev *ogldev;
   vgl_FBuffer *fbuffer;
   vgl_DrawFun *dfgl, *dfxw;
   vgl_DrawFun *df;

                   /* connect to X or Windows*/
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_X11DevConnectX (display,screen);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_GDIDevConnectWIN ();
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   dfgl  = vgl_DrawFunBegin();
   dfxw = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
#ifdef VKI_WIND_X11
   x11dev = vgl_X11DevBegin();
   vgl_X11DevDrawFun (x11dev,dfxw);
#else
   gdidev = vgl_GDIDevBegin();
   vgl_GDIDevDrawFun (gdidev,dfxw);
#endif
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfgl);

                   /* create fbuffer object */ 
   fbuffer = vgl_FBufferBegin ();

                   /* open windows and file */
   vgl_DrawFunPositionWindow (dfxw,100,100,300,200);
   vgl_DrawFunOpenWindow (dfxw,"System window");
   vgl_DrawFunPositionWindow (dfgl,400,400,300,200);
   vgl_DrawFunOpenWindow (dfgl,"OpenGL window");

                   /* draw to System window */
   df = dfxw;
   draw_triangle (df);
   vgl_DrawFunFBufferRead (df,0,0,0,0,fbuffer);

                   /* write fbuffer to OpenGL window */
   df = dfgl;
   vgl_DrawFunSetWindow (df);
   vgl_DrawFunClear (df);
   vgl_DrawFunFBufferWrite (df,0,0,0,0,fbuffer);
   vgl_DrawFunSwap (df);

                   /* write fbuffer to a .gif file */
   vgl_FBufferWriteGIF (fbuffer,"exam4a.gif");

                   /* wait */
   vgl_DrawFunDelay (df,5.);

                   /* close windows and file */ 
   vgl_DrawFunCloseWindow (dfxw);
   vgl_DrawFunCloseWindow (dfgl);

                   /* disconnect and free objects */ 
#ifdef VKI_WIND_X11
   vgl_X11DevEnd (x11dev);
   vgl_X11DevDisconnect ();
#else
   vgl_GDIDevEnd (gdidev);
   vgl_GDIDevDisconnect ();
#endif
   vgl_OpenGLDevEnd (ogldev);
   vgl_OpenGLDevDisconnect ();
   vgl_DrawFunEnd (dfgl);
   vgl_DrawFunEnd (dfxw);
   vgl_FBufferEnd (fbuffer);

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

static void
draw_triangle(vgl_DrawFun *df)
{
   Vfloat c[3];
                   /* draw triangle */
   vgl_DrawFunSetWindow (df);
   vgl_DrawFunClear (df);

   vgl_DrawFunPolygonColor (df,VGL_POLYGON,3,xtri,ctri,VGL_NOSHADE,NULL);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,3,xtri);
   vgl_DrawFunSwap (df);
}

Table of Contents

13.16 Example 5, Drawing a Rotating, Light Source Shaded Cone

The following example illustrates transforming a cone which is lit by an ambient light and a single distant light located on the positive x axis. The viewer is assumed to be located at the origin. The cone reflects ambient light uniformly from the ambient light source and produces diffuse and specular reflections from the distant light source. For specular reflection calculations, the direction of the viewer is assumed to be along the positive z axis when a distant viewer is used.

The cone is first drawn with no lighting in its basic 50% gray color. After a 5 second wait, it begins rotating to the right. The normal to the cone is directed radially outward so that the right hand surface of the cone initially produces diffuse and specular reflections from the distant light source. The left side of the cone does not reflect light from the distant light since its normal vector is always pointing away from the light. Note that as the cone rotates through 90 degrees, the backside of the right hand surface only produces diffuse reflections. This is the result of the normal vector pointing away from the viewer. The cone is drawn using a Quadric object.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cone
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vfloat tm4[4][4];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_Quadric *qu;
   vgl_DrawFun *df;
   vgl_Xfm     *xfm;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df  = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
   vgl_DrawFunOpenWindow (df,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);

                   /* create transform object */ 
   xfm = vgl_XfmBegin();

                   /* draw without lighting */
   vgl_DrawFunClear (df);
   draw_cone (df,qu,.4,.6,17);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,1.);

                   /* set lights */ 
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);

                   /* rotate about y axis */
   for(i = 0; i <= 25; i++) {
      vgl_DrawFunClear (df);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (df,tm4);
      draw_cone (df,qu,.4,.6,17);
      vgl_DrawFunSwap (df);
      vgl_DrawFunDelay (df,1.);
   }
   vgl_DrawFunDelay (df,5.);

                   /* free transform object */ 
   vgl_XfmEnd (xfm);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}


Table of Contents

13.17 Example 5a, Drawing Example 5 Using a Display List

The following example illustrates using a display list to cache the cone drawn in Example 5. The cone is then rotated and rendered using the display list. At regular intervals during the rotation sequence, the rendering style, linewidth and color of the cone are changed using display list functions.
#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cone
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vfloat tm4[4][4];
   Vfloat c[3];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_DList   *dlist;
   vgl_OpenGLDev *ogldev;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL, *dfDL;
   vgl_Xfm     *xfm;

#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create GL device and drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   dfGL = vgl_DrawFunBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfGL);

                   /* create display list and drawing functions */
   dlist = vgl_DListBegin();
   dfDL = vgl_DrawFunBegin();
   vgl_DListDrawFun (dlist,dfDL);

                   /* set GL drawing functions in display list object */
   vgl_DListSetObject(dlist,VGL_DRAWFUN,dfGL);

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,400,300);
   vgl_DrawFunOpenWindow (dfGL,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,dfDL);

                   /* create transform object */ 
   xfm = vgl_XfmBegin();

                   /* draw without lighting */
   vgl_DrawFunClear (dfGL);
   draw_cone (dfDL,qu,.4,.6,17);
   vgl_DListCall (dlist);
   vgl_DrawFunSwap (dfGL);
   vgl_DrawFunDelay (dfGL,1.);

                   /* set lights */ 
   vgl_DrawFunLight (dfGL,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfGL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (dfGL,VGL_LIGHTMODE,VGL_ON);

                   /* rotate about y axis */
   for(i = 0; i <= 25; i++) {
      vgl_DrawFunClear (dfGL);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (dfGL,tm4);
      if(i == 7) {
         vgl_DListSetRendering (dlist,0,0,1);
      }
      if(i == 13) {
         vgl_DListSetLineWidth (dlist,VGL_ON,3);
      }
      if(i == 19) {
         vgl_DListSetRendering (dlist,0,0,0);
         vgl_DListSetLineWidth (dlist,VGL_OFF,1);
         c[0] = 1.; c[1] = 0.; c[2] = 0.;
         vgl_DListSetColor (dlist,VGL_ON,c);
      }
      vgl_DListCall (dlist);
      vgl_DrawFunSwap (dfGL);
      vgl_DrawFunDelay (dfGL,1.);
   }
   vgl_DrawFunDelay (dfGL,5.);

                   /* free transform object */ 
   vgl_XfmEnd (xfm);

                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGL);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (dfGL);
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (dfDL);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}


Table of Contents

13.18 Example 5b, Drawing Example 5 Using a Display File

The following example illustrates using a display file to cache the cone drawn in Example 5. A display file operates somewhat analogously to a display list in that drawing is cached in a host file rather than in a memory resident display list. The DFile file is set to an ASCII formatted file named exam.dfile. Once this example is executed you may view this file with a text editor. When the cone is initially drawn, the display file must first be opened with vgl_DFileOpen. As the cone is drawn all drawing functions are cached in the display file. The file is closed with vgl_DFileClose when the cone is complete. To obtain a rendering of the cone, vgl_DFileRead is called. The cone is then rotated and rendered using repeated calls to vgl_DFileRead.
#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cylinder
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vfloat tm4[4][4];
   Vfloat xamb[3];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_DFile   *dfile;
   vgl_OpenGLDev *ogldev;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL, *dfDF;
   vgl_Xfm     *xfm;

#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create GL device and drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   dfGL = vgl_DrawFunBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfGL);

                   /* create display file and drawing functions */
   dfile = vgl_DFileBegin();
   dfDF = vgl_DrawFunBegin();
   vgl_DFileDrawFun (dfile,dfDF);

                   /* set GL drawing functions in display file object */
   vgl_DFileSetObject(dfile,VGL_DRAWFUN,dfGL);

                   /* specify display file format and file name */ 
   vgl_DFileSetFileType (dfile,DFILE_ASCII);
   vgl_DFileSetFileType (dfile,DFILE_BINARY);
   vgl_DFileSetFileName (dfile,"exam.dfile");

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,400,300);
   vgl_DrawFunOpenWindow (dfGL,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,dfDF);

                   /* create transform object */ 
   xfm = vgl_XfmBegin();

                   /* draw without lighting */
   vgl_DrawFunClear (dfGL);
   vgl_DFileOpen (dfile);
   draw_cone (dfDF,qu,.4,.6,17);
   vgl_DFileClose (dfile);

   vgl_DFileRead (dfile);
   vgl_DrawFunSwap (dfGL);
   vgl_DrawFunDelay (dfGL,1.);

                   /* set lights */ 
   vgl_DrawFunLight (dfGL,0,VGL_LIGHT_AMBIENT,camb,xamb);
   vgl_DrawFunLight (dfGL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (dfGL,VGL_LIGHTMODE,VGL_ON);

                   /* rotate about y axis */
   for(i = 0; i <= 25; i++) {
      vgl_DrawFunClear (dfGL);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (dfGL,tm4);
      vgl_DFileRead (dfile);
      vgl_DrawFunSwap (dfGL);
      vgl_DrawFunDelay (dfGL,1.);
   }
   vgl_DrawFunDelay (dfGL,5.);

                   /* free transform object */ 
   vgl_XfmEnd (xfm);

                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGL);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (dfGL);
   vgl_DFileEnd (dfile);
   vgl_DrawFunEnd (dfDF);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}


Table of Contents

13.19 Example 5c, Using an IActor Object with Example 5.

This example illustrates using an IActor object to implement user object manipulation. This is a modification of Example 5 in which different "dragger" actions may be used to rotate, translate, scale, etc. a cone object in the graphics window using mouse movements, mouse buttons and the control key.

The IActor object is prepared for object manipulation by setting the drawing function object for the display device as an attribute object and registering a display callback function which is invoked by the IActor object whenever the graphics display must be redrawn. In this example the 3 mouse buttons and control key are used to implement a total of 6 dragger actions. If the control key is not depressed; the left, middle and right mouse buttons provide for trackball rotation, translation and scaling respectively. If the control key is depressed the same mouse buttons are used for "rate" rotation, windowing and an alternate form of windowing which uses a free-hand form. A simple polling scheme is used to manage graphics input. An important point to note is that the use of IActor module is independent of the graphics input management. This allows the module to be integrated into the central event or message loop of the host application in a straight forward way. It is only necessary to call vgl_IActorDrag with a user supplied action, drag stage and cursor location.

The function vgl_IActorFit is used to set the projection viewing volume so that the cone object comfortably fills the graphics window. The function vgl_IActorSpin is called repeatedly if no dragger action is in effect. This reapplies the last rotation each time it is called causing the cone to spin. Depressing the shift key exits the program.

#include "base/base.h"
#include "vgl/vgl.h"

static void
generate_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);
static void
draw_display(vgl_IActor *iactor, vgl_DList *dlist);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };
static Vfloat xopp[3] = {
   -1.,0.,0. };

static Vint butact[2][3] = {
   {IACTOR_TRACKBALL, IACTOR_TRANSLATE, IACTOR_SCALE},
   {IACTOR_ROTATE, IACTOR_WINDOW, IACTOR_SQUIGGLE} };

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cone
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vint ix, iy, but[3];
   Vint ibut, icnt;
   Vint shft, cntl;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_DList   *dlist;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL;
   vgl_DrawFun *dfDL;
   vgl_IActor  *iactor;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   dfGL = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfGL);

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,400,300);
   vgl_DrawFunOpenWindow (dfGL,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* set lights */ 
   vgl_DrawFunLight (dfGL,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfGL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunLight (dfGL,2,VGL_LIGHT_DISTANT,cdis,xopp);
   vgl_DrawFunSetMode (dfGL,VGL_LIGHTMODE,VGL_ON);

                   /* create display list and drawing functions */
   dlist = vgl_DListBegin();
   dfDL = vgl_DrawFunBegin();
   vgl_DListDrawFun (dlist,dfDL);

                   /* set GL drawing functions in display list object */
   vgl_DListSetObject(dlist,VGL_DRAWFUN,dfGL);

                   /* generate quadric for drawing cone */ 
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,dfDL);

                   /* instance IActor */
   iactor = vgl_IActorBegin ();
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,dfGL);

                   /* set display callback */ 
   vgl_IActorSetFunction (iactor,IACTOR_FUN_DISPLAY,
                 (void(*)(vgl_IActor*,Vobject*))draw_display,dlist);

                   /* generate display */ 
   generate_cone (dfDL, qu,.4,.6,17);

                   /* fit display to viewport */ 
   vgl_IActorFit (iactor,NULL);

                   /* implement a simple mouse polling loop */ 
   while (1) {
      ibut = -1;
      icnt = 0;
                   /* detect button press */ 
      while (ibut == -1) {
         vgl_DrawFunPollMouse (dfGL,&ix,&iy,&but[0],&but[1],&but[2]);
         for(i = 0; i < 3; i++) {
            if(but[i]) {
               ibut = i;
               vgl_IActorDrag (iactor,butact[icnt][ibut],VGL_DRAG_INIT,ix,iy);
               break;
            }
         }
                   /* jump out if shift key depressed */ 
         vgl_DrawFunPollModifiers (dfGL,&cntl,&shft);
         if(shft) {
            goto done;
         }
         if(cntl) {
            icnt = 1;
         } else {
            icnt = 0;
         }

                   /* spin while waiting */ 
         if(ibut == -1) {
            vgl_IActorSpin (iactor,NULL);
         }
      }
                   /* wait for button release */ 
      while (ibut != -1) {
         vgl_DrawFunPollMouse (dfGL,&ix,&iy,&but[0],&but[1],&but[2]);
         if(but[ibut]) {
            vgl_IActorDrag (iactor,butact[icnt][ibut],VGL_DRAG_MOVE,ix,iy);
         } else {
            vgl_IActorDrag (iactor,butact[icnt][ibut],VGL_DRAG_TERM,ix,iy);
            ibut = -1;
         }
      }
   }
                   /* jump point for exiting polling loop */ 
done:;
                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGL);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (dfGL);
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (dfDL);
   vgl_IActorEnd  (iactor);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      generate graphics primitive for cone 
----------------------------------------------------------------------*/
static void
generate_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];
                   /* color and specularity */ 
   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
                   /* polygons */ 
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}

/*----------------------------------------------------------------------
                      display callback
----------------------------------------------------------------------*/
static void
draw_display(vgl_IActor *iactor, vgl_DList *dlist)
{
   Vint iparams[2];
   Vint rflag;
   vgl_DrawFun *dfGL;
   Vfloat cbot[3] = {.4,.4,.4};
   Vfloat ctop[3] = {0.,0.,.12};

   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&dfGL);

                   /* get render mode */
   vgl_DrawFunGetInteger (dfGL,VGL_RENDERMODE,iparams);
   rflag = iparams[0];

                   /* clear graphics screen */ 
   vgl_DrawFunClear (dfGL);
                   /* do not include in "Fit" operation */ 
   if(rflag == 0) {
      vgl_IActorDrawBackground (iactor,cbot,ctop);
      vgl_IActorDrawTrackBall (iactor);
   }
                   /* draw contents of display list */ 
   vgl_DListCall (dlist);
                   /* swap graphics buffers */ 
   vgl_DrawFunSwap (dfGL);
}


Table of Contents

13.20 Example 5d, Using a Popup Object with Example 5.

This example illustrates using a Popup object to implement user popup menus in the graphics window. This is a modification of Example 5 in which a popup menu is used to allow the user to select a number of drawing options related to the cone object. The Popup module implements the selection of a menu item as a dragger action in a manner very similar to dragger actions associated with the IActor module. Also like the IActor module, the Popup module is independent of the graphics input management so that it may be easily implemented into the central event or message loop of the host application. The motivation for using the Popup module for popup menus is ease of use, performance, consistency and portability. The Popup module should be used only for popup menus drawn in the graphics window which are associated with the graphics object displayed in the window.

The popup menu generated in this example contains examples of a title, toggle items, radio box items and one-shot items. The Popup and IActor modules together allow the user to implement a set of user object manipulation and display styles.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);
static void
draw_display(vgl_IActor *iactor, vgl_Quadric *qu);
static void
popup_callback(vgl_Popup *popup, vgl_IActor *iactor);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

                   /* custom drop background from gray to dark blue */ 
static Vfloat cbot[3] = {
   .5,.5,.5 };
static Vfloat ctop[3] = {
   0.,0.,.16 };

static Vint butaction[3] = {
   IACTOR_TRACKBALL,
   IACTOR_TRANSLATE,
   IACTOR_SCALE };

static Vint trackballflag;
static Vint rotcenterflag = 1;
static Vint fancybackflag;
static Vint subdivisions = 17;

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cone
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vint ix, iy, but[3];
   Vint ibut;
   Vint shft, cntl;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_Quadric *qu;
   vgl_DrawFun *df;
   vgl_IActor  *iactor;
   vgl_Popup   *popup;

#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,400,400,480,360);
   vgl_DrawFunOpenWindow (df,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* set lights */ 
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);

                   /* instance IActor and set drawing functions */
   iactor = vgl_IActorBegin ();
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,df);

                   /* set display callback */ 
   vgl_IActorSetFunction (iactor,IACTOR_FUN_DISPLAY,
                 (void(*)(vgl_IActor*,Vobject*))draw_display,qu);

                   /* instance Popup and set drawing functions */
   popup = vgl_PopupBegin();
   vgl_PopupSetObject (popup,VGL_DRAWFUN,df);

                   /* title */ 
   vgl_PopupTitle (popup,"Display");

                   /* define contents of popup from top to bottom */ 
                   /* toggles */ 
   vgl_PopupAddToggle (popup,1,"Trackball",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddToggle (popup,2,"Rotation Center",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupSetToggle (popup,2,rotcenterflag);
   vgl_PopupAddToggle (popup,3,"Fancy Background",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddToggle (popup,4,"Divisions Inactive",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddLine (popup);

                   /* radio box */ 
   vgl_PopupAddRadio (popup,5,1,"17 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddRadio (popup,5,2,"37 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddRadio (popup,5,3,"77 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddLine (popup);

                   /* one-shot item */ 
   vgl_PopupAddItem (popup,6,"Fit",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);

                   /* fit display to viewport */ 
   vgl_IActorFit (iactor,NULL);

                   /* implement a simple mouse polling loop */ 
   while (1) {
      ibut = -1;
                   /* detect button press */ 
      while (ibut == -1) {
         vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
         for(i = 0; i < 3; i++) {
            if(but[i]) {
               ibut = i;
               vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_INIT,ix,iy);
               break;
            }
         }
                   /* detect modifiers */
         vgl_DrawFunPollModifiers (df,&cntl,&shft);
                   /* done */ 
         if(shft) {
             goto done;
         }
                   /* popup menu */ 
         if(cntl) {
            vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
            vgl_PopupDrag (popup,VGL_DRAG_INIT,ix,iy);
            while (1) {
               vgl_DrawFunPollModifiers (df,&cntl,&shft);
               vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
               if(cntl) {
                  vgl_PopupDrag (popup,VGL_DRAG_MOVE,ix,iy);
               } else {
                  vgl_PopupDrag (popup,VGL_DRAG_TERM,ix,iy);
                  break;
               }
            }
         }

                   /* spin while waiting */ 
         if(ibut == -1) {
            vgl_IActorSpin (iactor,NULL);
         }
      }

                   /* wait for button release */ 
      while (ibut != -1) {
         vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
         if(but[ibut]) {
            vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_MOVE,ix,iy);
         } else {
            vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_TERM,ix,iy);
            ibut = -1;
         }
      }
   }
                   /* jump point for exiting polling loop */ 
done:;
                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);
   vgl_IActorEnd  (iactor);
   vgl_PopupEnd   (popup);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}

/*----------------------------------------------------------------------
                      display callback
----------------------------------------------------------------------*/
static void
draw_display(vgl_IActor *iactor, vgl_Quadric *qu)
{
   vgl_DrawFun *df;

   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&df);

   vgl_DrawFunClear (df);
                   /* be sure to draw background first */ 
   if(fancybackflag) {
      vgl_IActorDrawBackground (iactor,cbot,ctop);
   }
   if(trackballflag) {
      vgl_IActorDrawTrackBall (iactor);
   }
   if(rotcenterflag) {
      vgl_IActorDrawRotCenter (iactor,50);
   }
   draw_cone (df,qu,.4,.6,subdivisions);
   vgl_DrawFunSwap (df);
}

/*----------------------------------------------------------------------
                      popup callback
----------------------------------------------------------------------*/
static void
popup_callback(vgl_Popup *popup, vgl_IActor *iactor)
{
   Vint index, value;

                   /* get item index */ 
   vgl_PopupGetIndex (popup,&index);

                   /* check item index */ 
   if(index == 1) {
      vgl_PopupGetToggle (popup,index,&trackballflag);
   } else if(index == 2) {
      vgl_PopupGetToggle (popup,index,&rotcenterflag);
   } else if(index == 3) {
      vgl_PopupGetToggle (popup,index,&fancybackflag);
   } else if(index == 4) {
      vgl_PopupGetToggle (popup,index,&value);
      vgl_PopupSetActive (popup,5,!value);
   } else if(index == 5) {
      vgl_PopupGetRadio (popup,index,&value);
      if(value == 1) {
         subdivisions = 17;
      } else if(value == 2) {
         subdivisions = 37;
      } else if(value == 3) {
         subdivisions = 77;
      }
   } else if(index == 6) {
      vgl_IActorFit (iactor,NULL);
   }
}


Table of Contents

13.21 Example 5e, Off-Screen Rendering with Example 5.

This example is a modification of Example 5 to illustrate performing off-screen rendering to generate an image file. There are two techniques available. One uses an OpenGL off-screen frame buffer, the other uses the software rendering object, RendBuf. In general, one would want to use the OpenGL off-screen frame buffer in an interactive environment. The RendBuf object is useful for those applications in which OpenGL may not be available or practical. In either case the image is accessed via a FBuffer object. Then the contents of the FBuffer can be written to any supported file format - in this case BMP format using vgl_FBufferWriteBMP.

Rendering to an off-screen frame buffer in OpenGL is implemented in the buffer_cone function and requires using vgl_DrawFunRender to set the rendering mode to VGL_BUFFER_COLOR. The window size is queried and doubled and the off-screen buffer size is set using vgl_DrawFunBufferSize. The scene is rendered by calling vgl_IActorDisplay. The image is then read into a FBuffer object using vgl_DrawFunFBufferRead and the render mode is returned to standard rendering to the hardware frame buffer using vgl_DrawFunRender.

Rendering to a software frame buffer using RendBuf is illustrated in the function rendbuf_cone. Current attributes of the OpenGL device are queried and then specified in the RendBuf object. The window size for this example is doubled in each direction. The current projection and modelview matrix are installed. The lighting which was specified to the OpenGL device is also specified to RendBuf. Any relevant modes are queried and set in RendBuf. Then the drawing function to RendBuf is set in the IActor object and the display callback is invoked with vgl_IActorDisplay. The graphics will then be drawn to the RendBuf device rather than the OpenGL device. The internal FBuffer in RendBuf is queried using vgl_RendBufGetFBuffer. Finally the original drawing function to the OpenGL window is reset in IActor.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);
static void
draw_display(vgl_IActor *iactor, vgl_Quadric *qu);
static void
popup_callback(vgl_Popup *popup, vgl_IActor *iactor);
static void
rendbuf_cone(vgl_IActor *iactor);
static void
buffer_cone(vgl_IActor *iactor);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

                   /* custom drop background from gray to dark blue */ 
static Vfloat cbot[3] = {
   .5,.5,.5 };
static Vfloat ctop[3] = {
   0.,0.,.16 };

static Vint butaction[3] = {
   IACTOR_TRACKBALL,
   IACTOR_TRANSLATE,
   IACTOR_WINDOW };

static Vint trackballflag;
static Vint rotcenterflag = 1;
static Vint fancybackflag;
static Vint subdivisions = 17;
static Vint exitflag = 0;

/*----------------------------------------------------------------------
                      Off-Screen Rendering
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vint ix, iy, but[3];
   Vint ibut;
   Vint shft, cntl;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_Quadric *qu;
   vgl_DrawFun *df;
   vgl_IActor  *iactor;
   vgl_Popup   *popup;

#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,400,400,480,360);
   vgl_DrawFunOpenWindow (df,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* set lights */ 
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();

                   /* instance IActor and set drawing functions */
   iactor = vgl_IActorBegin ();
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,df);

                   /* set display callback */ 
   vgl_IActorSetFunction (iactor,IACTOR_FUN_DISPLAY,
                 (void(*)(vgl_IActor*,Vobject*))draw_display,qu);

                   /* instance Popup and set drawing functions */
   popup = vgl_PopupBegin();
   vgl_PopupSetObject (popup,VGL_DRAWFUN,df);

                   /* title */ 
   vgl_PopupTitle (popup,"Display");

                   /* define contents of popup from top to bottom */ 
                   /* toggles */ 
   vgl_PopupAddToggle (popup,1,"Trackball",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddToggle (popup,2,"Rotation Center",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupSetToggle (popup,2,rotcenterflag);
   vgl_PopupAddToggle (popup,3,"Fancy Background",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddToggle (popup,4,"Divisions Inactive",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddLine (popup);

                   /* radio box */ 
   vgl_PopupAddRadio (popup,5,1,"17 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddRadio (popup,5,2,"37 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddRadio (popup,5,3,"77 divisions",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddLine (popup);

                   /* one-shot item */ 
   vgl_PopupAddItem (popup,6,"Fit",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddItem (popup,7,"RendBuf",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddItem (popup,8,"Buffer",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);
   vgl_PopupAddLine (popup);
   vgl_PopupAddItem (popup,9,"Exit",
                  (void(*)(vgl_Popup*,Vobject*))popup_callback,iactor);

                   /* fit display to viewport */ 
   vgl_IActorFit (iactor,NULL);

                   /* implement a simple mouse polling loop */ 
   while (1) {
      ibut = -1;
                   /* detect button press */ 
      while (ibut == -1) {
         vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
         for(i = 0; i < 3; i++) {
            if(but[i]) {
               ibut = i;
               vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_INIT,ix,iy);
               break;
            }
         }
                   /* detect modifiers */
         vgl_DrawFunPollModifiers (df,&cntl,&shft);
                   /* done */ 
         if(shft) {
            goto done;
         }
                   /* popup menu */ 
         if(cntl) {
            vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
            vgl_PopupDrag (popup,VGL_DRAG_INIT,ix,iy);
            while (1) {
               vgl_DrawFunPollModifiers (df,&cntl,&shft);
               vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
               if(cntl) {
                  vgl_PopupDrag (popup,VGL_DRAG_MOVE,ix,iy);
               } else {
                  vgl_PopupDrag (popup,VGL_DRAG_TERM,ix,iy);
                  break;
               }
            }
            if(exitflag) {
               goto done;
            }
         }

                   /* spin while waiting */ 
         if(ibut == -1) {
            vgl_IActorSpin (iactor,NULL);
         }
      }

                   /* wait for button release */ 
      while (ibut != -1) {
         vgl_DrawFunPollMouse (df,&ix,&iy,&but[0],&but[1],&but[2]);
         if(but[ibut]) {
            vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_MOVE,ix,iy);
         } else {
            vgl_IActorDrag (iactor,butaction[ibut],VGL_DRAG_TERM,ix,iy);
            ibut = -1;
         }
      }
   }
                   /* jump point for exiting polling loop */ 
done:;
                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);
   vgl_IActorEnd  (iactor);
   vgl_PopupEnd   (popup);
   vgl_QuadricEnd (qu);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);
   vgl_QuadricSetParami (qu,QUADRIC_LINE,VGL_ON);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}

/*----------------------------------------------------------------------
                      display callback
----------------------------------------------------------------------*/
static void
draw_display(vgl_IActor *iactor, vgl_Quadric *qu)
{
   vgl_DrawFun *df;

   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&df);
   vgl_DrawFunClear (df);
                   /* be sure to draw background first */ 
   if(fancybackflag) {
      vgl_IActorDrawBackground (iactor,cbot,ctop);
   }
   if(trackballflag) {
      vgl_IActorDrawTrackBall (iactor);
   }
   if(rotcenterflag) {
      vgl_IActorDrawRotCenter (iactor,50);
   }
   draw_cone (df,qu,.4,.6,subdivisions);

   vgl_DrawFunSwap (df);
}

/*----------------------------------------------------------------------
                      popup callback
----------------------------------------------------------------------*/
static void
popup_callback(vgl_Popup *popup, vgl_IActor *iactor)
{
   Vint index, value;
   vgl_DrawFun *df;

   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&df);
                   /* get item index */ 
   vgl_PopupGetIndex (popup,&index);

                   /* check item index */ 
   if(index == 1) {
      vgl_PopupGetToggle (popup,index,&trackballflag);
   } else if(index == 2) {
      vgl_PopupGetToggle (popup,index,&rotcenterflag);
   } else if(index == 3) {
      vgl_PopupGetToggle (popup,index,&fancybackflag);
   } else if(index == 4) {
      vgl_PopupGetToggle (popup,index,&value);
      vgl_PopupSetActive (popup,5,!value);
   } else if(index == 5) {
      vgl_PopupGetRadio (popup,index,&value);
      if(value == 1) {
         subdivisions = 17;
      } else if(value == 2) {
         subdivisions = 37;
      } else if(value == 3) {
         subdivisions = 77;
      }
   } else if(index == 6) {
      vgl_IActorFit (iactor,NULL);
   } else if(index == 7) {
      rendbuf_cone (iactor);
   } else if(index == 8) {
      buffer_cone (iactor);
   } else if(index == 9) {
      exitflag = 1;
   }
}

/*----------------------------------------------------------------------
                      draw to RendBuf
----------------------------------------------------------------------*/
static void
rendbuf_cone(vgl_IActor *iactor)
{
   vgl_RendBuf *rendbuf;
   vgl_DrawFun *dfrb;
   vgl_FBuffer *fbuffer;
   vgl_DrawFun *df;
   Vint ip[4];
   Vint projtype;
   Vfloat fp[6], tm[16];
   Vint mode;

                   /* get device drawing function */ 
   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&df);

                   /* create software rendering objects */ 
   dfrb = vgl_DrawFunBegin ();
   rendbuf = vgl_RendBufBegin ();

                   /* install drawing functions */ 
   vgl_RendBufDrawFun (rendbuf,dfrb);

                   /* open software window twice as large as device window */ 
   vgl_DrawFunGetInteger (df,VGL_WINDOWSIZE,ip);
   vgl_DrawFunPositionWindow (dfrb,0,0,2*ip[0],2*ip[1]);
   vgl_DrawFunOpenWindow (dfrb,"RendBuf");

                   /* set lights */
   vgl_DrawFunLight (dfrb,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfrb,1,VGL_LIGHT_DISTANT,cdis,xdis);

                   /* set modes */ 
   vgl_DrawFunGetMode (df,VGL_ZBUFFERMODE,&mode);
   vgl_DrawFunSetMode (dfrb,VGL_ZBUFFERMODE,mode);
   vgl_DrawFunGetMode (df,VGL_LIGHTMODE,&mode);
   vgl_DrawFunSetMode (dfrb,VGL_LIGHTMODE,mode);

                   /* get depth range */ 
   vgl_DrawFunGetFloat (df,VGL_DEPTHRANGE,fp);
   vgl_DrawFunDepthRange (dfrb,fp[0],fp[1]);

                   /* get modelview matrix */ 
   vgl_DrawFunGetFloat (df,VGL_MODELVIEWMATRIX,tm);
   vgl_DrawFunXfmLoad (dfrb,(Vfloat(*)[4])tm);

                   /* get projection */ 
   vgl_DrawFunGetInteger (df,VGL_PROJECTIONTYPE,&projtype);
   vgl_DrawFunGetFloat (df,VGL_PROJECTIONLIMITS,fp);
   if(projtype == VGL_PROJORTHO) {
      vgl_DrawFunProjOrtho (dfrb,fp[0],fp[1],fp[2],fp[3],fp[4],fp[5]);
   } else {
      vgl_DrawFunProjFrustum (dfrb,fp[0],fp[1],fp[2],fp[3],fp[4],fp[5]);
   }
                   /* set software drawing functions in IActor */ 
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,dfrb);

                   /* invoke display callback */ 
   vgl_IActorDisplay (iactor,NULL);

                   /* get image buffer */
   vgl_RendBufGetFBuffer (rendbuf,&fbuffer);

                   /* write image in gif format to file */
   vgl_FBufferWriteBMP (fbuffer,"exam5eRendBuf.bmp");
   printf("exam5eRendBuf.bmp written\n");

                   /* destroy software rendering objects */ 
   vgl_DrawFunEnd (dfrb);
   vgl_RendBufEnd (rendbuf);

                   /* restore device drawing function */ 
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,df);
}

/*----------------------------------------------------------------------
                      draw to color buffer
----------------------------------------------------------------------*/
static void
buffer_cone(vgl_IActor *iactor)
{
   vgl_FBuffer *fbuffer;
   vgl_DrawFun *df;
   Vint ip[2];
                   /* get device drawing function */
   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&df);

                   /* allocate FBuffer to hold final image */ 
   fbuffer = vgl_FBufferBegin();
                   /* turn on off-screen rendering to color buffer */ 
   vgl_DrawFunRender (df,VGL_BUFFER_COLOR);
                   /* get window size and double it */ 
   vgl_DrawFunGetInteger (df,VGL_WINDOWSIZE,ip);
   vgl_DrawFunBufferSize (df,2*ip[0],2*ip[1]);
                   /* invoke display callback */ 
   vgl_IActorDisplay (iactor,NULL);
                   /* read off-screen frame buffer into FBuffer */
   vgl_DrawFunFBufferRead (df,0,0,0,0,fbuffer);
                   /* turn on normal rendering */
   vgl_DrawFunRender (df,VGL_RENDER);

   vgl_FBufferWriteBMP (fbuffer,"exam5eBuffer.bmp");
   printf("exam5eBuffer.bmp written\n");
   vgl_FBufferEnd (fbuffer);
}


Table of Contents

13.22 Example 5f, Using an IActor Object Clipping Planes with Example 5.

This example illustrates using an IActor object to control the movement of clipping planes. This is a modification of Example 5c in which different "dragger" actions have been added to detect and control clipping plane movement.

In this example the left mouse button and control key are used to implement control of the clipping plane movement. The function vgl_IActorDrawClipCenter is used to draw a clipping plane icon and optionally detect the specific type of clipping plane movement to be performed. Initially the clipping plane location is defined and set in IActor using vgl_IActorSetParamfv. The function vgl_IActorDrawClipCenter is called repeatedly with action IACTOR_CLIPPLANEDETECT and the current mouse location. The icon is drawn differently depending upon the mouse location with respect to the center sphere and concentric circles which constitute the basic icon. When the control key and left mouse button are depressed, the current specific action returned by vgl_IActorDrawClipCenter is used as the input action to vgl_IActorDrag and if the specific action is a rotation, the rotation vector returned by vgl_IActorDrawClipCenter is specified using vgl_IActorSetParamfv. This specific action is also now input to all subsequent calls to vgl_IActorDrawClipCenter to draw the appropriate icon relative to the specific drag action being performed. The vgl_IActorDrag drag function does not call clipping plane graphics functions internally. The user must query for the current clipping plane center and normal using vgl_IActorGetFloat. These values will be continually changed during the vgl_IActorDrag movements. The center and normal must be converted to a clipping plane equation in the display callback function and specified to the graphics subsystem using vgl_DrawFunClipPlane. Note that the clipping plane associated with an icon should not be active while the icon is being drawn.

Depressing the shift key exits the program.

#include "base/base.h"
#include "vgl/vgl.h"

static void
generate_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);
static void
draw_display(vgl_IActor *iactor, Vobject *obj);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };
static Vfloat xopp[3] = {
   -1.,0.,0. };

static Vint butact[2][3] = {
   {IACTOR_TRACKBALL, IACTOR_TRANSLATE, IACTOR_SCALE},
   {IACTOR_CLIPPLANEDETECT, IACTOR_WINDOW, IACTOR_SQUIGGLE} };

typedef struct Tobj {
   vgl_DList *dlist;
   Vint clipplanedetect;
   Vint clipplaneaction;
   Vfloat rotvec[3];
} Tobj;

/*----------------------------------------------------------------------
                      Draw a rotating, light source shaded cone
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   int i;
   Vint ix, iy, but[3];
   Vint ibut, icnt, iact;
   Vint shft, cntl;
   Vchar devname[256];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

#ifdef VKI_WIND_X11
   vgl_X11Dev *x11dev;
#else
   vgl_GDIDev *gdidev;
#endif
   vgl_OpenGLDev *ogldev;

   vgl_DList   *dlist;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL;
   vgl_DrawFun *dfDL;
   vgl_IActor  *iactor;
   Vfloat nrm[3], cen[3];
   Tobj tobj;
   Vint dev;

                   /* dev=1 OpenGL, dev=2 X11 or GDI */
   dev = 1;
   if(argc > 1) {
       sscanf(argv[1],"%d",&dev);
   }
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   dfGL  = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,dfGL);
      strcpy(devname,"OpenGL");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,dfGL);
      strcpy(devname,"X11");
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,dfGL);
      strcpy(devname,"GDI");
#endif
   }

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,640,480);
   vgl_DrawFunOpenWindow (dfGL,devname);

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-1.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* set lights */ 
   vgl_DrawFunLight (dfGL,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfGL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunLight (dfGL,2,VGL_LIGHT_DISTANT,cdis,xopp);
   vgl_DrawFunSetMode (dfGL,VGL_LIGHTMODE,VGL_ON);

                   /* create display list and drawing functions */
   dlist = vgl_DListBegin();
   dfDL = vgl_DrawFunBegin();
   vgl_DListDrawFun (dlist,dfDL);

                   /* set GL drawing functions in display list object */
   vgl_DListSetObject(dlist,VGL_DRAWFUN,dfGL);

                   /* generate quadric for drawing cone */ 
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,dfDL);

                   /* instance IActor */
   iactor = vgl_IActorBegin ();
   vgl_IActorSetObject (iactor,VGL_DRAWFUN,dfGL);

   tobj.dlist = dlist;
   tobj.clipplanedetect = IACTOR_CLIPPLANEDETECT;
   tobj.clipplaneaction = IACTOR_NONE;
                   /* set display callback */ 
   vgl_IActorSetFunction (iactor,IACTOR_FUN_DISPLAY,
                 (void(*)(vgl_IActor*,Vobject*))draw_display,&tobj);

                   /* specify clipplane to manage */ 
   nrm[0] = 1.;
   nrm[1] = 0.;
   nrm[2] = 0.;
   cen[0] = 0.;
   cen[1] = 0.;
   cen[2] = 0.;
   vgl_IActorSetParamfv (iactor,IACTOR_CLIPPLANECENTER,cen);
   vgl_IActorSetParamfv (iactor,IACTOR_CLIPPLANENORMAL,nrm);
   vgl_IActorSetParami (iactor,IACTOR_CLIPPLANEICONRADIUS,80);

                   /* generate display list */ 
   generate_cone (dfDL, qu,.4,.6,17);

                   /* fit display to viewport */ 
   vgl_IActorFit (iactor,NULL);

                   /* implement a simple mouse polling loop */ 
   while (1) {
      ibut = -1;
      icnt = 0;
      iact = IACTOR_NONE;
                   /* detect button press */ 
      while (ibut == -1) {
         vgl_DrawFunPollMouse (dfGL,&ix,&iy,&but[0],&but[1],&but[2]);
         for(i = 0; i < 3; i++) {
            if(but[i]) {
               ibut = i;
               iact = butact[icnt][ibut];
               if(iact == IACTOR_CLIPPLANEDETECT) {
                  if(tobj.clipplaneaction != IACTOR_NONE) {
                     if(tobj.clipplaneaction == IACTOR_CLIPPLANEROTATE ||
                        tobj.clipplaneaction == IACTOR_CLIPPLANEROTATE_DEGEN) {
                        vgl_IActorSetParamfv (iactor,IACTOR_CLIPPLANEROTVEC,
                                              tobj.rotvec);
                     }
                     iact = tobj.clipplaneaction;
                     tobj.clipplanedetect = tobj.clipplaneaction;
                  } else {
                     iact = IACTOR_NONE;
                  }
               } else {
                  tobj.clipplanedetect = IACTOR_NONE;
               }
               vgl_IActorDrag (iactor,iact,VGL_DRAG_INIT,ix,iy);
               break;
            }
         }
                   /* jump out if shift key depressed */ 
         vgl_DrawFunPollModifiers (dfGL,&cntl,&shft);
         if(shft) {
            goto done;
         }
         if(cntl) {
            icnt = 1;
         } else {
            icnt = 0;
         }

                   /* spin while waiting */ 
         if(ibut == -1) {
            vgl_IActorSpin (iactor,NULL);
         }
      }
                   /* wait for button release */ 
      while (ibut != -1) {
         vgl_DrawFunPollMouse (dfGL,&ix,&iy,&but[0],&but[1],&but[2]);
         if(but[ibut]) {
            vgl_IActorDrag (iactor,iact,VGL_DRAG_MOVE,ix,iy);
         } else {
            vgl_IActorDrag (iactor,iact,VGL_DRAG_TERM,ix,iy);
            ibut = -1;
            tobj.clipplanedetect = IACTOR_CLIPPLANEDETECT;
         }
      }
   }
                   /* jump point for exiting polling loop */ 
done:;
                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGL);

                   /* free objects */ 
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   }
   vgl_DrawFunEnd (dfGL);
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (dfDL);
   vgl_IActorEnd  (iactor);
   vgl_QuadricEnd (qu);
                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }
                   /* clean up */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif

   return 0;
}

/*----------------------------------------------------------------------
                      generate graphics primitive for cone 
----------------------------------------------------------------------*/
static void
generate_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];
                   /* color and specularity */ 
   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
                   /* polygons */ 
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);
}

/*----------------------------------------------------------------------
                      display callback
----------------------------------------------------------------------*/
static void
draw_display(vgl_IActor *iactor, Vobject *obj)
{
   Vint iparams[2];
   Vint rflag;
   vgl_DrawFun *dfGL;
   Vfloat cbot[3] = {.4,.4,.4};
   Vfloat ctop[3] = {0.,0.,.12};
   Vint ix, iy, but[3];
   Tobj *tobj;

   tobj = (Tobj*)obj;

   vgl_IActorGetObject (iactor,VGL_DRAWFUN,(Vobject**)&dfGL);

                   /* get render mode */
   vgl_DrawFunGetInteger (dfGL,VGL_RENDERMODE,iparams);
   rflag = iparams[0];

                   /* clear graphics screen */ 
   vgl_DrawFunClear (dfGL);
                   /* do not include in "Fit" operation */ 
   if(rflag == 0) {
      vgl_DrawFunPollMouse (dfGL,&ix,&iy,&but[0],&but[1],&but[2]);
      vgl_IActorDrawBackground (iactor,cbot,ctop);
      vgl_IActorDrawTrackBall (iactor);
      vgl_IActorDrawClipCenter (iactor,tobj->clipplanedetect,ix,iy,0,
                                &tobj->clipplaneaction,tobj->rotvec);
   }
                   /* draw contents of display list */ 
   vgl_DrawFunSetSwitch (dfGL,VGL_CLIPPLANE,0,VGL_ON);
   vgl_DListCall (tobj->dlist);
   vgl_DrawFunSetSwitch (dfGL,VGL_CLIPPLANE,0,VGL_OFF);
                   /* swap graphics buffers */ 
   vgl_DrawFunSwap (dfGL);
}


Table of Contents

13.23 Example 6, Performing Graphics Primitive Optimization Using DOpt

This example illustrates the use of the graphics primitive optimization module DOpt to speed the drawing rates for a light source shaded cone with 1000000 quadrilateral flat shaded polygons. First the cone is drawn to a DList object as a series of independent polygons. The contents of the display list are traversed and rendered 50 times as the object is rotated about the vertical axis for one full revolution. The cone is then regenerated with a DOpt in place to optimize the polygons before caching them in a display list. This optimized display list is then traversed 50 times for a visual comparison of the rendering rates achieved as compared to the first rendering.
#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Unoptimized and optimized light source shaded cone
----------------------------------------------------------------------*/
int
main()
{
   int i;
   Vfloat tm4[4][4];
   int usevbo;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_DList   *dlist;
   vgl_DOpt    *dopt;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL, *dfDL, *dfDO;
   vgl_Xfm     *xfm;
   vgl_OpenGLDev *ogldev;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create GL device and drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   dfGL = vgl_DrawFunBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfGL);

                   /* create display list and drawing functions */
   dlist = vgl_DListBegin();
   dfDL = vgl_DrawFunBegin();
   vgl_DListDrawFun (dlist,dfDL);
                   /* use VGL_ON to enable graphics buffer memory in DList */
   usevbo = VGL_OFF;
   vgl_DListSetParami (dlist,DLIST_USEBUFFERS,usevbo);

                   /* set GL drawing functions in display list object */
   vgl_DListSetObject (dlist,VGL_DRAWFUN,dfGL);

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,400,300);
   vgl_DrawFunOpenWindow (dfGL,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-2.,2.);
   vgl_DrawFunDepthRange (dfGL,0.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();

                   /* create transform object */ 
   xfm = vgl_XfmBegin();

                   /* first render drawing to display list */
                   /* set lights */ 
   vgl_DrawFunLight (dfDL,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfDL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (dfDL,VGL_LIGHTMODE,VGL_ON);

                   /* draw cone with 1,000,000 independent quads */
   draw_cone (dfDL,qu,.8,1.2,1001);

   vgl_DrawFunDelay (dfGL,1.);

                   /* rotate once about y axis */
   for(i = 0; i <= 50; i++) {
      vgl_DrawFunClear (dfGL);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (dfGL,tm4);
      vgl_DListCall (dlist);
      vgl_DrawFunSwap (dfGL);
   }
   vgl_DrawFunDelay (dfGL,1.);

                   /* erase contents of display list */ 
   vgl_DListErase (dlist);

                   /* instance optimizer and set input drawing functions */ 
   dopt = vgl_DOptBegin();
   dfDO = vgl_DrawFunBegin();
   vgl_DOptDrawFun (dopt,dfDO);

                   /* link optimizer output to display list */ 
   vgl_DOptSetObject (dopt,VGL_DRAWFUN,dfDL);

                   /* repeat rendering process drawing to optimizer */
                   /* explicitly reset */
   vgl_DOptReset (dopt);
                   /* draw cone */
   draw_cone (dfDO,qu,.8,1.2,1001);

                   /* explicitly flush so the optimizer empties its buffers */ 
   vgl_DOptFlush (dopt);

                   /* rotate about y axis */
   for(i = 0; i <= 50; i++) {
      vgl_DrawFunClear (dfGL);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (dfGL,tm4);
      vgl_DListCall (dlist);
      vgl_DrawFunSwap (dfGL);
   }
   vgl_DrawFunDelay (dfGL,1.);

                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGL);

                   /* free ogldev and dfGL AFTER freeing dlist.
                      dlist needs these objects to free VBO memory
                      if DListErase has not been previously called */
   vgl_DListEnd (dlist);
   vgl_DrawFunEnd (dfGL);
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (dfDL);
   vgl_DrawFunEnd (dfDO);
   vgl_QuadricEnd (qu);
   vgl_XfmEnd (xfm);
   vgl_DOptEnd (dopt);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,n);
   vgl_QuadricSetParami (qu,QUADRIC_SHADE,VGL_VERTEXSHADE);
   vgl_QuadricSetParami (qu,QUADRIC_FILL,SYS_ON);
   vgl_QuadricCylinder (qu,r,.5*r,h);
}


Table of Contents

13.24 Example 7, Drawing in XOR Mode, Rubber Banding

A useful technique in interactive graphics is the ability to do rubber band line drawing while leaving an underlying graphics image undamaged. This non destructive drawing is performed using either a XOR (exclusive or) raster operation or blending functions depending upon the nature of the graphics device. VglTools will ensure that XOR mode drawing is non destructive on arbitrary backgrounds only when drawing white graphics primitives.

The function vgl_DrawFunSetMode is used to enable and disable various modes which must be set in order for rubber band drawing to give the desired result. Initially, in addition to enabling XOR mode, front buffer mode should be enabled and z-buffering disabled.

This example illustrates using XOR with OpenGLDev with the associated window system 2D driver, in this case X11Dev on X Windows and GDIDev on Microsoft Windows. There are various advantages to using the window system drivers for immediate mode, front buffer drawing with respect to performance during desktop sharing, etc.

#include "base/base.h"
#include "vgl/vgl.h"

static Vfloat xpol[4][3] = {
   {-.4,-.4,0.}, {.4,-.4,0.},  {.4,.4,0.},  {-.4,.4,0.} };

static void
draw_rubberband(vgl_DrawFun *df, vgl_DrawFun *dfxor, Vint iws);

/*----------------------------------------------------------------------
                      Rubber banding
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   Vint xsize, ysize;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
   vgl_X11Dev *x11dev;
#else
   vgl_GDIDev *gdidev;
#endif
   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *df, *dfws;
   Vword window;
   Vint dev;
   Vchar devname[256];
                   /* dev=1 OpenGL */
   dev = 1;
   if(argc > 1) {
      sscanf(argv[1],"%d",&dev);
   }
                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
      strcpy(devname,"OpenGL");
   }
                   /* open window */
   xsize = 400;
   ysize = 300;
   vgl_DrawFunPositionWindow (df,400,400,xsize,ysize);
   vgl_DrawFunOpenWindow (df,devname);
   vgl_DrawFunQueryWindow (df,&window);

                   /* rubber band using 3D driver */ 
   draw_rubberband (df,df,0);

                   /* rubber band using window system driver */ 
   dfws = vgl_DrawFunBegin();
#ifdef VKI_WIND_X11
   vgl_X11DevConnectX (display,screen);
   x11dev = vgl_X11DevBegin();
   vgl_X11DevDrawFun (x11dev,dfws);
#else
   vgl_GDIDevConnectWIN ();
   gdidev = vgl_GDIDevBegin();
   vgl_GDIDevDrawFun (gdidev,dfws);
#endif
   vgl_DrawFunConnectWindow (dfws,window);
   draw_rubberband (df,dfws,1);
   vgl_DrawFunDisconnectWindow (dfws);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_DrawFunEnd (df);
#ifdef VKI_WIND_X11
   vgl_X11DevEnd (x11dev);
   vgl_X11DevDisconnect ();
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
      vgl_OpenGLDevDisconnect ();
   }
#else
   vgl_GDIDevEnd (gdidev);
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
      vgl_OpenGLDevDisconnect ();
   }
#endif
   vgl_DrawFunEnd (dfws);

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

static void
draw_rubberband(vgl_DrawFun *df, vgl_DrawFun *dfxor, Vint iws)
{
   Vint i;
   Vfloat x[3], c[3], xr[2][3];
   Vint ix, iy;
   Vint iold;
   Vint ipar[2], xsize, ysize;

                   /* get window size */
   vgl_DrawFunGetInteger (df,VGL_WINDOWSIZE,ipar);
   xsize = ipar[0];
   ysize = ipar[1];

                   /* clear and draw a magenta polygon and text */ 
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_POLYGON,4,xpol,VGL_NOSHADE,NULL);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   x[0] = -.9; x[1] = .9; x[2] = 0.;
   if(iws == 0) {
      vgl_DrawFunText (df,x,"XOR drawing, 3D driver");
   } else {
      vgl_DrawFunText (df,x,"XOR drawing, Window system driver");
   }
   vgl_DrawFunSwap (df);

                   /* now draw rubber band */
                   /* set drawing mode to front buffer */ 
   vgl_DrawFunSetMode (dfxor,VGL_FRONTBUFFERDRAWMODE,VGL_ON);
                   /* set z buffering off */ 
   vgl_DrawFunSetMode (dfxor,VGL_ZBUFFERMODE,VGL_OFF);

                   /* set projection matrix to match screen pixel size */ 
   vgl_DrawFunProjOrtho (dfxor,0.,(Vfloat)(xsize-1),
                               0.,(Vfloat)(ysize-1), -1.,1.);
                   /* set color of rubber banding line to white */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (dfxor,c);
                   /* turn on xor mode */ 
   vgl_DrawFunSetMode (dfxor,VGL_XORMODE,VGL_ON);

                   /* line anchor in lower left of window */
   ix = 20;
   iy = 20;
   xr[0][0] = ix; xr[0][1] = iy; xr[0][2] = 0.;

                   /* draw rubber band starting in upper right */ 
   ix = xsize-20;
   iy = ysize-20;
   iold = 0;
   for(i = 0; i < ysize-40; i+=4) {
      iy -= 4;
      if(iold) {
         vgl_DrawFunPolyLine (dfxor,VGL_LINESTRIP,2,xr);
         vgl_DrawFunFlush (dfxor);
      }
      iold = 1;
      xr[1][0] = ix; xr[1][1] = iy; xr[1][2] = 0.;
      vgl_DrawFunPolyLine (dfxor,VGL_LINESTRIP,2,xr);
      vgl_DrawFunFlush (dfxor);
      vgl_DrawFunDelay (dfxor,.1);
   }
                   /* return modes and projection to defaults */ 
   vgl_DrawFunSetMode (dfxor,VGL_XORMODE,VGL_OFF);
   vgl_DrawFunProjOrtho (dfxor,-1.,1.,-1.,1.,-1.,1.);
   vgl_DrawFunSetMode (dfxor,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (dfxor,VGL_FRONTBUFFERDRAWMODE,VGL_OFF);

                   /* clear and draw a blue polygon */ 
   vgl_DrawFunClear (df);
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_POLYGON,4,xpol,VGL_NOSHADE,NULL);
   vgl_DrawFunSwap (df);

                   /* wait */
   vgl_DrawFunDelay (df,1.);
}

Table of Contents

13.25 Example 7a, Using Update Mode for a Cursor Magnifier

The "update" mode is useful for doing very general drawing over an existing scene. This mode implements a form of non-destructive drawing. The update mode is enabled using the SetMode drawing function with type VGL_UPDATEMODE. There are two possible enabling values, VGL_UPDATEMODE_FBUFFER and VGL_UPDATEMODE_FZBUFFER. When enabled the current contents of the specified buffers are copied and held internally in the device interface. When the Clear drawing function is called the specified buffers are initialized to the saved contents. This operation is very fast. All subsequent drawing will then have the effect of "updating" the saved scene.

This example illustrates using the update mode to implement a pixel magnification tool under the cursor. This feature would be useful for picking operations which need precise selection. A scene of 4 quadrilaterals is drawn and then saved when the update mode is enabled. Only the frame (color) buffer is saved. The FBuffer object is then used to capture a 21x21 pixel square of the frame buffer using the FBufferRead drawing function and then magnify it by a factor of 4 using vgl_FBufferScale. A 2 pixel wide white border is added to the square using vgl_FBufferBorder. The scaled frame buffer is then drawn using the FBufferWrite drawing function. The CNTL key will toggle the magnification between 4 and 8.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

static Vfloat rquad[4][3] = {
   {0.,0.,0.}, {1.,0.,0.},  {1.,1.,0.}, {0.,1.,0.} };

static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };

static Vfloat xprompt[4][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.},
   {-4.5, -4.7, 0.} };

/*----------------------------------------------------------------------
                      Using Update Mode for a Cursor Magnifier
----------------------------------------------------------------------*/
int
main()
{
   vgl_DrawFun   *df;
   vgl_Xfm       *xfm;
   vgl_FBuffer   *fb, *fbm;

   Vint i;
   Vint xsize, ysize;
   Vint ix, iy, but1, but2, but3, cntl, shft;
   Vfloat c[3], x[3], tm[4][4];
   Vchar title[65];
   Vint test;
   Vint s, wx, sm;
                   /* create drawing function object */ 
   df = vgl_DrawFunBegin();

   strcpy(title,"Example 7a, ");
   VglDevCreate (df,VGLDEV_OPENGL,title,&test);

                   /* open window and set lighting, etc. */ 
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (df,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (df,title);
   vgl_DrawFunProjOrtho (df,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
   c[0] = .3; c[1] = .3; c[2] = .3;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .7;  c[1] =  .7;  c[2] =  .7;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (df,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();

                   /* draw basic scene */ 
   vgl_DrawFunClear (df);
                   /* draw prompt message */ 
   vgl_DrawFunColor (df,cwhite);
   vgl_DrawFunText (df,xprompt[0],"Left    button: Magnifier");
   vgl_DrawFunText (df,xprompt[1],"Middle  button: quit");
   vgl_DrawFunText (df,xprompt[2],"Right   button: quit");
   vgl_DrawFunText (df,xprompt[3],"Control button: double magnification");
                   /* draw rectangles */ 
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
   for(i = 0; i < 4; i++) {
      vgl_DrawFunColor (df,cquads[i]);
                   /* draw gray rectangle with 50% transparency */ 
      if(i == 3) {
         vgl_DrawFunTrans (df,.5);
      } else {
         vgl_DrawFunTrans (df,0.);
      }
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
      vgl_DrawFunPolygonData (df,VGL_POLYGON,4,xquads[i],
                              3,(Vfloat*)rquad,VGL_NOSHADE,NULL);
   }
   vgl_DrawFunSwap (df);
   vgl_DrawFunTrans (df,0.);

   vgl_DrawFunSetMode (df,VGL_UPDATEMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERREADMODE,VGL_OFF);
   fb = vgl_FBufferBegin ();
   fbm = vgl_FBufferBegin ();
                   /* sample dimension is 2*wz + 1 */
   wx = 10;
                   /* magnification factor */
   s = 4;
                   /* cursor magnifier loop */
   while (1) {
      vgl_DrawFunPollMouse (df,&ix,&iy,&but1,&but2,&but3);
      vgl_DrawFunPollModifiers (df,&cntl,&shft);
      vgl_DrawFunClear (df);
                   /* toggle magnification factor */ 
      if(cntl) {
         s = 8;
      } else {
         s = 4;
      }
                   /* draw magnifier */ 
      if(but1) {
         vgl_DrawFunFBufferRead (df, ix-wx,ix+wx, iy-wx,iy+wx, fb);
         vgl_FBufferScale (fb,s,fbm);
         vgl_FBufferColor (fbm,cwhite);
         vgl_FBufferBorder (fbm,2);
         sm = wx*s + s/2;
         vgl_DrawFunFBufferWrite (df, ix-sm,ix+sm, iy-sm,iy+sm,  fbm);
                   /* break out */ 
      } else if(but2) {
         break;
      } else if(but3) {
         break;
      }
      vgl_DrawFunSwap (df);
   }
   vgl_FBufferEnd (fb);
   vgl_FBufferEnd (fbm);

   vgl_DrawFunSetMode (df,VGL_UPDATEMODE,VGL_OFF);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free all objects */ 
   vgl_DrawFunEnd  (df);
   vgl_XfmEnd      (xfm);

   VglDevDestroy ();
   return 0;
}

Table of Contents

13.26 Example 7b, Using Update Mode for a 3D Probe

This example is a modification of Example 7a. It illustrates using the update mode to implement a 3D probe under the cursor. In this case a Quadric object is used to draw a 3D probe. The update mode is VGL_UPDATE_FZBUFFER so that both the frame buffer and zbuffer are saved. In this way the 3D probe may be moved in the volume with destroying the saved color and depth values. Use the CNTL key to move the 3D probe into the scene and the SHFT key to move the 3D probe out of the scene.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

static Vfloat rquad[4][3] = {
   {0.,0.,0.}, {1.,0.,0.},  {1.,1.,0.}, {0.,1.,0.} };

static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };
static Vfloat cyellow[3] = {
   1.,1.,.5 };

static Vfloat xprompt[4][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.},
   {-4.5, -4.7, 0.} };
static Vfloat xcursor[3][3] = {
   {-4.5, 4.3, 0.},
   {-4.5, 3.9, 0.},
   {-4.5, 3.5, 0.} };

static void
xfmstack_init(vgl_DrawFun *df, vgl_Xfmstack *xfmstack);

/*----------------------------------------------------------------------
                      Using Update Mode for a 3D Probe
----------------------------------------------------------------------*/
int
main()
{
   vgl_DrawFun   *df;
   vgl_Xfm       *xfm;
   vgl_Xfmstack  *xfmstack;
   vgl_Quadric   *qu;

   Vint i;
   Vint xsize, ysize;
   Vint ix, iy, but1, but2, but3, cntl, shft;
   Vfloat c[3], x[3], tm[4][4];
   Vfloat xi[3], z;
   Vchar stg[33], title[65];
   Vint test;
   Vint s, wx, sm;

   wx = 10;
   s = 4;
   sm = wx*s+s/2;
                   /* create drawing function object */ 
   df = vgl_DrawFunBegin();

   strcpy(title,"Example 7a, ");
   VglDevCreate (df,VGLDEV_OPENGL,title,&test);

                   /* open window and set lighting, etc. */ 
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (df,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (df,title);
   vgl_DrawFunProjOrtho (df,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
   c[0] = .4; c[1] = .4; c[2] = .4;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .6;  c[1] =  .6;  c[2] =  .6;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (df,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();

                   /* draw basic scene */ 
   vgl_DrawFunClear (df);
                   /* draw prompt message */ 
   vgl_DrawFunColor (df,cwhite);
   vgl_DrawFunText (df,xprompt[0],"Left         button: 3D Cursor");
   vgl_DrawFunText (df,xprompt[1],"Middle/Right button: quit");
   vgl_DrawFunText (df,xprompt[2],"Control      button: z farer");
   vgl_DrawFunText (df,xprompt[3],"Shift        button: z nearer");
                   /* draw rectangles */ 
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
   for(i = 0; i < 4; i++) {
      vgl_DrawFunColor (df,cquads[i]);
                   /* draw gray rectangle with 50% transparency */ 
      if(i == 3) {
         vgl_DrawFunTrans (df,.5);
      } else {
         vgl_DrawFunTrans (df,0.);
      }
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
      vgl_DrawFunPolygonData (df,VGL_POLYGON,4,xquads[i],
                              3,(Vfloat*)rquad,VGL_NOSHADE,NULL);
   }
   vgl_DrawFunSwap (df);
   vgl_DrawFunTrans (df,0.);

   vgl_DrawFunSetMode (df,VGL_UPDATEMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERREADMODE,VGL_OFF);

   xfmstack = vgl_XfmstackBegin ();
   xfmstack_init (df,xfmstack);

   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);
                   /* starting z screen coordinate in middle */ 
   z = .5;
                   /* cursor 3D sphere probe loop */
   while (1) {
      vgl_DrawFunPollMouse (df,&ix,&iy,&but1,&but2,&but3);
      vgl_DrawFunPollModifiers (df,&cntl,&shft);
      vgl_DrawFunClear (df);
      if(cntl) {
         z += .001;
         if(z > 1.)  z = 1.;
      }
      if(shft) {
         z -= .001;
         if(z < 0.)  z = 0.;
      }
                   /* sphere */
      if(but1) {
         xi[0] = ix;
         xi[1] = iy;
         xi[2] = z;
         vgl_XfmstackUnproject (xfmstack,xi[0],xi[1],xi[2],&x[0],&x[1],&x[2]);
         vgl_DrawFunColor (df,cyellow);
         vgl_QuadricSetParamfv (qu,QUADRIC_ORIGIN,x);
         vgl_QuadricSphere (qu,.2);
                   /* draw cursor location in screen coordinates */ 
         vgl_DrawFunXfmPush (df);
         vgl_XfmIdentity (xfm);
         vgl_XfmGetMatrix (xfm,tm);
         vgl_DrawFunXfmLoad (df,tm);
         vgl_DrawFunColor (df,cwhite);
         sprintf(stg,"ix = %d",ix);
         vgl_DrawFunText (df,xcursor[0],stg);
         sprintf(stg,"iy = %d",iy);
         vgl_DrawFunText (df,xcursor[1],stg);
         sprintf(stg,"z  = %f",z);
         vgl_DrawFunText (df,xcursor[2],stg);
         vgl_DrawFunXfmPop (df);
                   /* break out */
      } else if(but2) {
         break;
      } else if(but3) {
         break;
      }
      vgl_DrawFunSwap (df);
   }
   vgl_QuadricEnd (qu);
   vgl_XfmstackEnd (xfmstack);

   vgl_DrawFunSetMode (df,VGL_UPDATEMODE,VGL_OFF);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free all objects */ 
   vgl_DrawFunEnd  (df);
   vgl_XfmEnd      (xfm);

   VglDevDestroy ();
   return 0;
}

static void
xfmstack_init(vgl_DrawFun *df, vgl_Xfmstack *xfmstack)
{
   Vfloat tm[4][4];
   Vint iparam[4];
   vgl_Xfm *xfm;
                   /* query and load complete viewing transformation 
                      into transformation stack object */
   xfm = vgl_XfmBegin();
   vgl_DrawFunGetFloat (df,VGL_MODELVIEWMATRIX,(Vfloat*)tm);
   vgl_XfmSetMatrix (xfm,tm);
   vgl_XfmstackLoad (xfmstack,xfm);
   vgl_DrawFunGetFloat (df,VGL_PROJECTIONMATRIX,(Vfloat*)tm);
   vgl_XfmSetMatrix (xfm,tm);
   vgl_XfmstackProj (xfmstack,xfm);
   vgl_DrawFunGetInteger (df,VGL_VIEWPORT,iparam);
   vgl_XfmstackSetViewport (xfmstack,iparam[0],iparam[1],iparam[2],iparam[3]);
   vgl_XfmEnd (xfm);
}

Table of Contents

13.27 Example 8, Reading and Writing Image Files

This example illustrates the use of the FBuffer module to read a user specified image file, display it in an OpenGL window and optionally write the image file another image file format. The example accepts two command line arguments, the first is an input image file and the second is an output image file. The format of the image file is determined from the file extension as follows: .tga Targa, .gif GIF, .bmp BMP, .rgb SGI RGB, .png PNG, .tif TIFF and .jpg JPEG. Note that writing PNG files and reading PNG, TIFF and PNG files depends on external library support. If the first argument is omitted earth.gif is assumed. If the second argument is omitted no image file is written.
#include <stdlib.h>
#include <string.h>
#include "base/base.h"
#include "vgl/vgl.h"

static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile);

/*----------------------------------------------------------------------
                      FBuffer file interfaces
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   char inputfile[256], outputfile[256];
   char infile[256], outfile[256];
   vgl_FBuffer *fbuffer;

                   /* check for proper number of arguments */ 
   if(argc < 2) {
      fprintf(stderr,"Usage: %s inputfile [outputfile]\n",argv[0]);
      fprintf(stderr," inputfile is blank, 'earth.gif' is assumed\n");
      strcpy(inputfile,"earth.gif");
   } else {
      strcpy(inputfile,argv[1]);
   }
   strcpy(infile,inputfile);

                   /* create FBuffer object */
   fbuffer = vgl_FBufferBegin();

                   /* decode input display file format and file name */ 
   if(strstr(infile,".tga")) {
      vgl_FBufferReadTarga (fbuffer,infile);
   } else if(strstr(infile,".gif")) {
      vgl_FBufferReadGIF (fbuffer,infile);
   } else if(strstr(infile,".rgb")) {
      vgl_FBufferReadSGI (fbuffer,infile);
   } else if(strstr(infile,".bmp")) {
      vgl_FBufferReadBMP (fbuffer,infile);
   } else if(strstr(infile,".png")) {
      vgl_FBufferReadPNG (fbuffer,infile);
   } else if(strstr(infile,".tif")) {
      vgl_FBufferReadTIFF (fbuffer,infile);
   } else if(strstr(infile,".jpg")) {
      vgl_FBufferReadJPEG (fbuffer,infile);
   } else {
      fprintf(stderr,"Error: Unsupported input file format %s\n",infile);
      exit(1);
   }                
   if(vgl_FBufferError(fbuffer)) {
      fprintf(stderr,"Error: Can not read image file %s\n",infile);
      exit(1);
   }
                   /* display input image */ 
   displayFBuffer (fbuffer, infile);
   
                   /* write output file if requested */
   if(argc == 3) {
      strcpy(outputfile,argv[2]);
      strcpy(outfile,outputfile);
                   /* write to proper output file format */ 
      if(strstr(outfile,".tga")) {
         vgl_FBufferWriteTarga (fbuffer,outfile);
      } else if(strstr(outfile,".gif")) {
         vgl_FBufferSetParami (fbuffer,FBUFFER_GIFCOMPTYPE,
                                       FBUFFER_GIFCOMP_RLE);
         vgl_FBufferWriteGIF (fbuffer,outfile);
      } else if(strstr(outfile,".rgb")) {
         vgl_FBufferWriteSGI (fbuffer,outfile);
      } else if(strstr(outfile,".bmp")) {
         vgl_FBufferWriteBMP (fbuffer,outfile);
      } else if(strstr(outfile,".png")) {
         vgl_FBufferWritePNG (fbuffer,outfile);
      } else if(strstr(outfile,".tif")) {
         vgl_FBufferWriteTIFF (fbuffer,outfile);
      } else if(strstr(outfile,".jpg")) {
         vgl_FBufferWriteJPEG (fbuffer,outfile);
      } else if(strstr(outfile,".svg")) {
         vgl_FBufferWriteSVG (fbuffer,outfile);
      } else {
         fprintf(stderr,"Error: Unsupported output file format %s\n",outfile);
         exit(1);
      } 
                  
      if(vgl_FBufferError(fbuffer)) {
         fprintf(stderr,"Error: Can not write image file %s\n",outfile);
         exit(1);
      }
   }
                   /* free objects */ 
   vgl_FBufferEnd (fbuffer);
   return 0;
}

/*----------------------------------------------------------------------
                      display contents of FBuffer object
----------------------------------------------------------------------*/
static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile)
{
   Vint params[2];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *df;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window to size of FBuffer */
   vgl_FBufferInq (fbuffer,¶ms[0],¶ms[1]);
   vgl_DrawFunConfigureWindow (df,VGL_WINDOWSIZE,params);

                   /* Write FBuffer */
   vgl_DrawFunOpenWindow (df,inputfile);
   vgl_DrawFunFBufferWrite (df,0,0,0,0,fbuffer);
   vgl_DrawFunSwap (df);

                   /* wait */
   vgl_DrawFunDelay (df,20.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();
                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
}


Table of Contents

13.28 Example 8a, Writing a Microsoft Windows AVI file

This example is an extension of Example 8 and illustrates the use of the FBuffer module to read a user specified image file, display it and write a series of AVI files with compression options. The compression options are added as two additional command line arguments to the two already present. The third argument is the compression type and must be one of the values NONE, INTELINDEO, CINEPAK or MSVIDEO. The fourth argument is the compression factor. The input image is "animated" by adding an increasingly thicker border to the image using the vgl_FBufferBorder function.
#include <stdlib.h>
#include <string.h>
#include "base/base.h"
#include "vgl/vgl.h"
#include <vfw.h>

static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile);

/*----------------------------------------------------------------------
                      FBuffer write AVI file
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   int i;
   char inputfile[256], outputfile[256];
   char infile[256], outfile[256];
   char *inputext, *outputext;
   char *token;
   vgl_FBuffer *fbuffer;
   PAVIFILE avifile;
   Vfloat c[3];
   Vint compressFlag;
   Vint compressFactor;

                   /* check for proper number of arguments */ 
   if(argc < 2) {
      fprintf(stderr,"Usage: %s inputfile [outputfile [compressionFlag [compressionFactor] ] ]\n",argv[0]);
      fprintf(stderr," inputfile is blank, 'earth.gif' is assumed\n");
      strcpy(inputfile,"earth.gif");
   } else {
      strcpy(inputfile,argv[1]);
   }
   strcpy(infile,inputfile);
   token = strtok(inputfile,".");
   if(!token) {
      fprintf(stderr,"Error: Bad input file %s\n",infile);
      exit(1);
   }
   inputext = strtok(NULL," ");
   if(!inputext) {
      fprintf(stderr,"Error: Bad input file %s\n",infile);
      exit(1);
   }
   if(argc > 2) {
      strcpy(outfile,argv[2]);
   } else {
      strcpy(outfile,"exam8a.avi");
   }
   if(argc > 3) {
      if(!strcmp(argv[3],"NONE")) {
          compressFlag = FBUFFER_AVICOMP_NONE;
      } else if (!strcmp(argv[3],"INTELINDEO")) {
          compressFlag = FBUFFER_AVICOMP_INTELINDEO;
      } else if (!strcmp(argv[3],"CINEPAK")) {
          compressFlag = FBUFFER_AVICOMP_CINEPAK;
      } else if (!strcmp(argv[3],"MSVIDEO")) {
          compressFlag = FBUFFER_AVICOMP_MSVIDEO;
      } else {
         fprintf(stderr,"Error: Unidentifiable compression type (%s)\n"
                       " Will create uncompressed AVI file.\n",argv[3]);
         compressFlag = FBUFFER_AVICOMP_NONE;
      }
   } else {
      compressFlag = FBUFFER_AVICOMP_NONE;
   }
   if(argc > 4) {
      compressFactor = atoi(argv[4]);
      if(compressFactor <= 0) {
         fprintf(stderr,"Error: Bad compression factor %s\n"
                        " Setting compression factor to 80\n",argv[4]);
         compressFactor = 80;
      }
   } else {
      compressFactor = 80;
   }

                   /* create FBuffer object */
   fbuffer = vgl_FBufferBegin();
                   /* decode input display file format and file name */ 
   if(!strncmp(inputext,"tga",3)) {
      vgl_FBufferReadTarga (fbuffer,infile);
   } else if(!strncmp(inputext,"gif",3)) {
      vgl_FBufferReadGIF (fbuffer,infile);
   } else if(!strncmp(inputext,"rgb",3)) {
      vgl_FBufferReadSGI (fbuffer,infile);
   } else if(!strncmp(inputext,"bmp",3)) {
      vgl_FBufferReadBMP (fbuffer,infile);
   } else {
      fprintf(stderr,"Error: Unsupported input file format %s\n",infile);
      exit(1);
   }                
   if(vgl_FBufferError(fbuffer)) {
      fprintf(stderr,"Error: Can not read image file %s\n",infile);
      exit(1);
   }
                   /* display input image */ 
   displayFBuffer (fbuffer, infile);
   
   AVIFileInit ();
   AVIFileOpen (&avifile,outfile,OF_CREATE|OF_WRITE,NULL);
   
                   /* set compression information */ 
   vgl_FBufferSetParami (fbuffer,FBUFFER_AVICOMPTYPE,compressFlag);
   vgl_FBufferSetParami (fbuffer,FBUFFER_AVICOMPFACT,compressFactor);
   
                   /* set border color */ 
   c[0] = 0.;
   c[1] = .5;
   c[2] = .75;
   vgl_FBufferColor (fbuffer,c);

                   /* write 30 images animating the border size */ 
   for(i = 1; i <= 30; i++) {
      vgl_FBufferBorder (fbuffer,2*i);
      vgl_FBufferWriteWINAVI (fbuffer,&avifile);
   }
                   /* close AVI */ 
   vgl_FBufferCloseWINAVI (fbuffer);

   AVIFileRelease (avifile);
   AVIFileExit ();

                   /* free objects */ 
   vgl_FBufferEnd (fbuffer);
   return 0;
}

/*----------------------------------------------------------------------
                      display contents of FBuffer object
----------------------------------------------------------------------*/
static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile)
{
   Vint params[2];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *df;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window to size of FBuffer */
   vgl_FBufferInq (fbuffer,¶ms[0],¶ms[1]);
   vgl_DrawFunConfigureWindow (df,VGL_WINDOWSIZE,params);

                   /* Write FBuffer */
   vgl_DrawFunOpenWindow (df,inputfile);
   vgl_DrawFunFBufferWrite (df,0,0,0,0,fbuffer);
   vgl_DrawFunSwap (df);

                   /* wait */
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();
                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
}


Table of Contents

13.29 Example 8b, FBuffer Image Operations

This example is an extension of Example 8 and illustrates the use of the FBuffer module to read a user specified image file and perform a number of image processing operations on it. The gamma warp operation, using vgl_FBufferGammaWarp is sometimes used to correct color balance for a particular computer monitor. A 4 pixel wide red border is added using vgl_FBufferBorder. Finally the image size is reduced by 60 percent in each direction using vgl_FBufferZoom.
#include <stdlib.h>
#include <string.h>
#include "base/base.h"
#include "vgl/vgl.h"

static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *text);

/*----------------------------------------------------------------------
                      FBuffer Image Operations
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   char infile[256];
   vgl_FBuffer *fbuffer;
   vgl_FBuffer *fbufferi;
   Vint xsize, ysize;
   Vfloat cb[3];

                   /* check for proper number of arguments */ 
   if(argc < 2) {
      fprintf(stderr,"Usage: %s inputfile\n",argv[0]);
      fprintf(stderr," inputfile is blank, 'earth.gif' is assumed\n");
      strcpy(infile,"earth.gif");
   } else {
      strcpy(infile,argv[1]);
   }

                   /* create FBuffer object */
   fbuffer = vgl_FBufferBegin();

                   /* decode input display file format and file name */ 
   if(strstr(infile,".tga")) {
      vgl_FBufferReadTarga (fbuffer,infile);
   } else if(strstr(infile,".gif")) {
      vgl_FBufferReadGIF (fbuffer,infile);
   } else if(strstr(infile,".rgb")) {
      vgl_FBufferReadSGI (fbuffer,infile);
   } else if(strstr(infile,".bmp")) {
      vgl_FBufferReadBMP (fbuffer,infile);
   } else if(strstr(infile,".png")) {
      vgl_FBufferReadPNG (fbuffer,infile);
   } else if(strstr(infile,".tif")) {
      vgl_FBufferReadTIFF (fbuffer,infile);
   } else if(strstr(infile,".jpg")) {
      vgl_FBufferReadJPEG (fbuffer,infile);
   } else {
      fprintf(stderr,"Error: Unsupported input file format %s\n",infile);
      exit(1);
   }                
   if(vgl_FBufferError(fbuffer)) {
      fprintf(stderr,"Error: Can not read image file %s\n",infile);
      exit(1);
   }
   vgl_FBufferInq (fbuffer,&xsize,&ysize);
                   /* display original image */ 
   displayFBuffer (fbuffer,infile);

                   /* gamma warp */ 
   vgl_FBufferGammaWarp (fbuffer,1.2);
   displayFBuffer (fbuffer,"Gamma Warp");

                   /* add red border */ 
   cb[0] = 1.;
   cb[1] = 0.;
   cb[2] = 0.;
   vgl_FBufferColor (fbuffer,cb);
   vgl_FBufferBorder (fbuffer,4);
   displayFBuffer (fbuffer,"Border");

                   /* change image size */
   fbufferi = vgl_FBufferBegin();
   vgl_FBufferDef (fbufferi,.6*xsize,.6*ysize);
   vgl_FBufferZoom (fbufferi,fbuffer);

                   /* display processed image */ 
   displayFBuffer (fbufferi,"Zoom");
   
                   /* free objects */ 
   vgl_FBufferEnd (fbufferi);
   vgl_FBufferEnd (fbuffer);
   return 0;
}

/*----------------------------------------------------------------------
                      display contents of FBuffer object
----------------------------------------------------------------------*/
static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *text)
{
   Vint params[2];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *df;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window to size of FBuffer */
   vgl_FBufferInq (fbuffer,¶ms[0],¶ms[1]);
   vgl_DrawFunConfigureWindow (df,VGL_WINDOWSIZE,params);

                   /* Write FBuffer */
   vgl_DrawFunOpenWindow (df,text);
   vgl_DrawFunClear (df);
   vgl_DrawFunFBufferWrite (df,0,0,0,0,fbuffer);
   vgl_DrawFunSwap (df);

                   /* wait */
   vgl_DrawFunDelay (df,2.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();
}


Table of Contents

13.30 Example 8c, FBuffer Write MP4 or H264 File

This example is an extension of Example 8 and illustrates the use of the FBuffer module to read a user specified image file, display it and write a series of images to either a MP4 or H264 video file. The input image is "animated" by adding an increasingly thicker border to the image using the vgl_FBufferBorder function.
#include <stdlib.h>
#include <string.h>
#include "base/base.h"
#include "vgl/vgl.h"

static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile);

/*----------------------------------------------------------------------
                      FBuffer Write MP4 or H264 File
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   int i, h264flag, mp4flag;
   char inputfile[256], outputfile[256];
   vgl_FBuffer *fbuffer;
   Vfloat c[3];

                   /* check for proper number of arguments */ 
   if(argc < 2) {
      fprintf(stderr,"Usage: %s [inputfile] [outputfile]\n",argv[0]);
      fprintf(stderr," inputfile is blank, 'earth.gif' is assumed\n");
      fprintf(stderr," output is blank, 'earth_mpeg4.mp4' is assumed\n");
      strcpy(inputfile,"earth.gif");
      strcpy(outputfile,"earth_mpeg4.mp4");
   } else if(argc < 3) {
      fprintf(stderr,"Usage: %s [inputfile] [outputfile]\n",argv[0]);
      fprintf(stderr," output is blank, 'earth_mpeg4.mp4' is assumed\n");
      strcpy(inputfile,argv[1]);
      strcpy(outputfile,"earth_mpeg4.mp4");
   } else {
      strcpy(inputfile,argv[1]);
      strcpy(outputfile,argv[2]);
   }

                   /* create FBuffer object */
   fbuffer = vgl_FBufferBegin();
                   /* decode input display file format and file name */ 
   if(strstr(inputfile,".tga")) {
      vgl_FBufferReadTarga (fbuffer,inputfile);
   } else if(strstr(inputfile,".gif")) {
      vgl_FBufferReadGIF (fbuffer,inputfile);
   } else if(strstr(inputfile,".rgb")) {
      vgl_FBufferReadSGI (fbuffer,inputfile);
   } else if(strstr(inputfile,".bmp")) {
      vgl_FBufferReadBMP (fbuffer,inputfile);
   } else {
      fprintf(stderr,"Error: Unsupported input file format %s\n",inputfile);
      exit(1);
   }                
   if(vgl_FBufferError(fbuffer)) {
      fprintf(stderr,"Error: Can not read image file %s\n",inputfile);
      exit(1);
   }
                   /* decode output display file format and file name */ 
   h264flag = 0;
   if(strstr(outputfile,"h264")) {
      h264flag = 1;
   } else if(strstr(outputfile,"mpeg4")) {
      mp4flag = 1;
   } else {
      fprintf(stderr,"Error: Unsupported output file format %s\n",outputfile);
      exit(1);
   }

                   /* display input image */ 
   displayFBuffer (fbuffer, inputfile);
   
   vgl_FBufferSetParamf (fbuffer,FBUFFER_FRAMERATE,10.);
   if(h264flag) {
      vgl_FBufferOpenFFMPEG (fbuffer,FBUFFER_FFMPEG_H264,outputfile);
   } else if(mp4flag) {
      vgl_FBufferOpenFFMPEG (fbuffer,FBUFFER_FFMPEG_MPEG4,outputfile);
   }
   
                   /* set border color */ 
   c[0] = 0.;
   c[1] = .5;
   c[2] = .75;
   vgl_FBufferColor (fbuffer,c);

                   /* write 30 images animating the border size */ 
   for(i = 1; i <= 30; i++) {
      vgl_FBufferBorder (fbuffer,2*i);
      vgl_FBufferWriteFFMPEG (fbuffer);
   }
                   /* close file */ 
   vgl_FBufferCloseFFMPEG (fbuffer);
                   /* free objects */ 
   vgl_FBufferEnd (fbuffer);
   return 0;
}

/*----------------------------------------------------------------------
                      display contents of FBuffer object
----------------------------------------------------------------------*/
static void
displayFBuffer(vgl_FBuffer *fbuffer, Vchar *inputfile)
{
   Vint params[2];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_DrawFun *df;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);

                   /* open window to size of FBuffer */
   vgl_FBufferInq (fbuffer,¶ms[0],¶ms[1]);
   vgl_DrawFunConfigureWindow (df,VGL_WINDOWSIZE,params);

                   /* Write FBuffer */
   vgl_DrawFunOpenWindow (df,inputfile);
   vgl_DrawFunFBufferWrite (df,0,0,0,0,fbuffer);
   vgl_DrawFunSwap (df);

                   /* wait */
   vgl_DrawFunDelay (df,5.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();
                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
}


Table of Contents

13.31 Example 9, Framework for a Data Navigator Using DataBuf

This example illustrates the use of the DataBuf module to provide a framework for a "data navigation" facility. The goal is to create a system which will allow rapid query, on a pixel by pixel basis, of data associated with visible surfaces. In this example, four rectangular surfaces are drawn. Each rectangle is given an index from one to four, which could be interpreted as an element number in finite element analysis or a surface identifier in a solid model. The index is rendered as a DataIndex primitive to the DataBuf object. In addition, the surface parametric coordinates are rendered as floating point PolygonData across the rectangles. The DataBuf object renders these data primitives and provides for a rapid query of the index and parametric coordinates of the visible surface at any pixel.

The example uses a DTee object to split the drawing functions to a DataBuf object and to a device interface object for rendering the surfaces in color in a graphics window. A Pixelmap object is used to capture the frame buffer after the initial drawing. During the data navigation query loop, the Pixelmap object is written repeatedly to the frame buffer and queried information is drawn on it.

The index and parametric coordinates can be used within an application to retrieve any information concerning the entity associated with the index. The parametric coordinates may be used to interpolate application data associated with the entity to the precise parametric coordinate location at the pixel. Note that in this example only two parametric coordinates were used, three coordinates could be used, for example if the entity were a 3D solid finite element.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

static Vfloat rquad[4][3] = {
   {0.,0.,0.}, {1.,0.,0.},  {1.,1.,0.}, {0.,1.,0.} };

static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };

static Vfloat xprompt[3][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.} };

/*----------------------------------------------------------------------
                      Data Navigator
                      Drawing to a Graphics Window and a Data Buffer
----------------------------------------------------------------------*/
int
main()
{
   vgl_DataBuf   *databuf;
   vgl_DTee      *dtee;
   vgl_DrawFun   *df, *dfDB, *dfGD;
   vgl_Xfm       *xfm;
   vgl_Pixelmap  *pixelmap;

   Vint i;
   Vint xsize, ysize;
   Vint ix, iy, but1, but2, but3;
   Vfloat c[3], x[3], tm[4][4];
   Vint index, nrws;
   Vfloat d[3];
   Vfloat xi[3];
   Vint dc[3];
   Vchar stg[33], title[65];
   Vint test;

                   /* create drawing function object */ 
   dfGD = vgl_DrawFunBegin();

   strcpy(title,"DataBuf Example, ");
   VglDevCreate (dfGD,VGLDEV_OPENGL,title,&test);

                   /* create databuf */
   databuf = vgl_DataBufBegin();
   dfDB = vgl_DrawFunBegin ();
   vgl_DataBufDrawFun (databuf,dfDB);
   vgl_DataBufSetRender (databuf,VGL_OFF,VGL_OFF,VGL_OFF);
   vgl_DataBufSetBuffers (databuf,1,3);

                   /* create DTee object */
   dtee = vgl_DTeeBegin ();
   df = vgl_DrawFunBegin ();
   vgl_DTeeDrawFun (dtee,df);

                   /* link graphics device and data buffer to DTee */
   vgl_DTeeSetObject (dtee,VGL_DRAWFUN,dfGD);
   vgl_DTeeSetObject (dtee,VGL_DRAWFUN_TEE,dfDB);

                   /* open window and set lighting, etc. */ 
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (df,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (df,title);
   vgl_DrawFunProjOrtho (df,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
   c[0] = .3; c[1] = .3; c[2] = .3;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .7;  c[1] =  .7;  c[2] =  .7;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (df,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();

                   /* create pixelmap */ 
   pixelmap = vgl_PixelmapBegin ();

                   /* draw basic scene */ 
   vgl_DrawFunClear (df);
                   /* draw prompt message */ 
   vgl_DrawFunColor (dfGD,cwhite);
   vgl_DrawFunText (dfGD,xprompt[0],"Left   button: index");
   vgl_DrawFunText (dfGD,xprompt[1],"Middle button: data");
   vgl_DrawFunText (dfGD,xprompt[2],"Right  button: quit");
                   /* draw rectangles */ 
   vgl_DrawFunXfmPush (df);
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
   for(i = 0; i < 4; i++) {
      index = i+1;
      vgl_DrawFunDataIndex (df,1,1,&index);
      vgl_DrawFunColor (df,cquads[i]);
                   /* draw gray rectangle with 50% transparency */ 
      if(i == 3) {
         vgl_DrawFunTrans (df,.5);
      } else {
         vgl_DrawFunTrans (df,0.);
      }
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
      vgl_DrawFunPolygonData (df,VGL_POLYGON,4,xquads[i],
                              3,(Vfloat*)rquad,VGL_NOSHADE,NULL);
   }
   vgl_DrawFunXfmPop (df);
   vgl_DrawFunSwap (df);

                   /* read pixelmap */ 
   vgl_DrawFunPixelmapCreate (df,pixelmap);
   vgl_DrawFunPixelmapRead (df,pixelmap);

                   /* prepare graphics device for data navigation */ 
                   /* set projection matrix to match screen pixel size */
   vgl_DrawFunProjOrtho (dfGD, 0.,(Vfloat)(xsize-1), 0.,(Vfloat)(ysize-1),
                         -1.,1.);
                   /* set modelview matrix identity */
   vgl_DrawFunXfmPush (dfGD);
   vgl_XfmIdentity (xfm);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (dfGD,tm);

                   /* data navigation loop */
   while (1) {
      vgl_DrawFunPollMouse (dfGD,&ix,&iy,&but1,&but2,&but3);
      vgl_DrawFunClear (dfGD);
      vgl_DrawFunPixelmapWrite (dfGD,pixelmap);
      vgl_DrawFunColor (dfGD,cwhite);
      if(but1) {
         vgl_DataBufGetDataIndex (databuf,ix,iy,&index);
         xi[0] = ix; xi[1] = iy; xi[2] = 0.;
         sprintf(stg,"index = %d\n",index);
         vgl_DrawFunText (dfGD,xi,stg);
      } else if(but2) {
         vgl_DataBufGetDataIndex (databuf,ix,iy,&index);
         xi[0] = ix; xi[1] = iy; xi[2] = 0.;
         if(index) {
            vgl_DataBufGetData (databuf,ix,iy,&nrws,d);
            sprintf(stg,"data = %f",d[0]);
            vgl_DrawFunText (dfGD,xi,stg);
            sprintf(stg,"       %f",d[1]);
            dc[0] = 0;  dc[1] = -15;  dc[2] = 0;
            vgl_DrawFunTextDC (dfGD,xi,dc,stg);
            sprintf(stg,"       %f",d[2]);
            dc[0] = 0;  dc[1] = -30;  dc[2] = 0;
            vgl_DrawFunTextDC (dfGD,xi,dc,stg);
         } else {
            sprintf(stg,"data = NONE");
            vgl_DrawFunText (dfGD,xi,stg);
         }
      } else if(but3) {
         break;
      }
      vgl_DrawFunSwap (dfGD);
   }

   vgl_DrawFunXfmPop (dfGD);
   vgl_DrawFunPixelmapDestroy (dfGD,pixelmap);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free all objects */ 
   vgl_DrawFunEnd  (df);
   vgl_DrawFunEnd  (dfGD);
   vgl_DrawFunEnd  (dfDB);
   vgl_DTeeEnd     (dtee);
   vgl_DataBufEnd  (databuf);
   vgl_XfmEnd      (xfm);
   vgl_PixelmapEnd (pixelmap);

   VglDevDestroy ();
   return 0;
}


Table of Contents

13.32 Example 9a, Framework for a Data Navigator Using OpenGLDev

This example illustrates a reworking of Example 9, using an off screen rendering mode in OpenGL and the VGL_UPDATEMODE mode. Both of these features are recommended as a replacement for the methodology described in Example 9. The use of hardware assisted data index rendering in OpenGL rather than the software rendering in the DataBuf module results in a substantial performance increase.

Rendering of data indices is enabled using vgl_DrawFunSetMode with mode VGL_DATAINDEXMAXROWS set to maximum number of data indices to be rendered at any pixel. By default this mode is set to zero which disables data index rendering. Then the data indices are rendered to an off-screen frame buffer. The frame buffer containing the data indices are then read to a FBuffer object using an OpenGLDev specific function vgl_OpenGLDevFBufferDataIndex. The data index at any pixel can now be accessed very quickly from the FBuffer object using vgl_FBufferGetPixel.

Finally the data navigation loop in entered. This loop uses the VGL_UPDATEMODE to quickly refresh the scene while each pass of the navigation loop annotates or highlights the entities picked from the screen.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

                   /* red, green, blue, gray */ 
static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };

static Vfloat xprompt[3][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.} };

static Vint useoit = 1;
static Vint multisample = 0;

/*----------------------------------------------------------------------
                      Data Navigator
                      Framework for a Data Navigator Using OpenGLDev
----------------------------------------------------------------------*/
int
main()
{
   vgl_DrawFun   *df;
   vgl_Xfm       *xfm;
   vgl_OpenGLDev *ogldev;
   vgl_FBuffer   *fbuffer;
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif
   Vint i;
   Vint ix, iy, but1, but2, but3;
   Vfloat c[3], x[3], tm[4][4];
   Vint index;
   Vfloat xi[3];
   Vchar stg[33];
   Vint xsize, ysize;

                   /* create drawing function object */ 
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create GL device and drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   df = vgl_DrawFunBegin();
   vgl_OpenGLDevDrawFun (ogldev,df);
   if(multisample) {
      vgl_DrawFunVisualWindow (df,VGL_VISUAL_MULTISAMPLE);
   }
                   /* open window */
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (df,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (df,"OpenGL window");
   if(multisample) {
      vgl_DrawFunSetMode (df,VGL_MULTISAMPLEMODE,VGL_ON);
   }
                   /* enable data index */
   vgl_DrawFunSetMode (df,VGL_DATAINDEXMAXROWS,1);
   vgl_DrawFunSetMode (df,VGL_SHADERMODE,1);
   if(useoit) {
      vgl_DrawFunSetMode (df,VGL_OITMODE,1);
   }

   vgl_DrawFunProjOrtho (df,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
   c[0] = .3; c[1] = .3; c[2] = .3;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .7;  c[1] =  .7;  c[2] =  .7;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (df,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();
                   /* draw basic scene */ 

                   /* draw rectangles */ 
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);

   vgl_DrawFunClear (df);
                   /* draw prompt message */ 
   vgl_DrawFunColor (df,cwhite);
   vgl_DrawFunText (df,xprompt[0],"Left   button: index");
   vgl_DrawFunText (df,xprompt[1],"Middle button: currently inactive");
   vgl_DrawFunText (df,xprompt[2],"Right  button: quit");
   vgl_DrawFunXfmPush (df);
   vgl_DrawFunXfmLoad (df,tm);
                   /* draw rectangles and data indices */ 
   for(i = 0; i < 4; i++) {
      index = i-101;
      vgl_DrawFunDataIndex (df,1,1,&index);
      vgl_DrawFunColor (df,cquads[i]);
                   /* draw gray rectangle with 50% transparency */ 
      if(i == 3) {
         vgl_DrawFunTrans (df,.5);
      } else {
         vgl_DrawFunTrans (df,0.);
      }
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
   }
   vgl_DrawFunXfmPop (df);
   vgl_DrawFunSwap (df);
                   /* retrieve indices at all pixels */
   fbuffer = vgl_FBufferBegin ();
                   /* need to use OpenGLDev specific function */
   vgl_OpenGLDevFBufferDataIndex (ogldev,1,fbuffer);
   vgl_DrawFunSetMode (df,VGL_DATAINDEXMAXROWS,0);
   vgl_DrawFunSetMode (df,VGL_SHADERMODE,0);
   if(useoit) {
      vgl_DrawFunSetMode (df,VGL_OITMODE,0);
   }
                   /* prepare graphics device for data navigation */
                   /* grab current frame buffer and zbuffer */ 
   vgl_DrawFunSetMode (df,VGL_UPDATEMODE,VGL_ON);
                   /* turn zbuffer off so text always visible */
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);
                   /* set projection matrix to match screen pixel size */
   vgl_DrawFunProjOrtho (df,0.,(Vfloat)(xsize-1), 0.,(Vfloat)(ysize-1),-1.,1.);
                   /* set modelview matrix identity */
   vgl_DrawFunXfmPush (df);
   vgl_XfmIdentity (xfm);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
                   /* data navigation loop */
   while (1) {
      vgl_DrawFunPollMouse (df,&ix,&iy,&but1,&but2,&but3);
      vgl_DrawFunClear (df);
      vgl_DrawFunColor (df,cwhite);
      if(but1) {
         vgl_FBufferGetPixeli (fbuffer,ix,iy,&index);
         xi[0] = ix; xi[1] = iy; xi[2] = 0.;
         sprintf(stg,"index = %d\n",index);
         vgl_DrawFunText (df,xi,stg);
      } else if(but3) {
         break;
      }
      vgl_DrawFunSwap (df);
   }
                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free all objects */ 
   vgl_FBufferEnd (fbuffer);
   vgl_DrawFunEnd  (df);
   vgl_XfmEnd      (xfm);
   vgl_OpenGLDevEnd (ogldev);

   return 0;
}


Table of Contents

13.33 Example 10, Selection and Extent Modes

This example illustrates the use of the alternate selection and extent render modes for aiding in 3D object picking and extent box calculation. The example is a reworking of Example 9. Whereas Example 9 implemented visible surface picking, this example illustrates 3D object picking, ie. all objects within a region on the screen may be picked regardless of their visibility.

When performing object picking using selection mode, it is useful to be able to regenerate the 3D scene for rendering, selection and extent box calculation. The four rectangles of Example 9 are initially drawn to a display list object using the DList module for this purpose. During the polling loop, the scene is first drawn to the screen in normal render mode, then depending upon which mouse button is depressed, the device is placed into selection or extent mode using the function vgl_DrawFunRender.

If selection mode is specified, the selection region and hit buffers are defined and the scene is redrawn. The frame buffer is unchanged - instead hit detection in the selection region is performed. The number of DataIndex hits in the selection region under the cursor is queried using vgl_DrawFunSelectQuery. The actual DataIndex values and depth information are retrieved from the selection buffers and displayed.

If extent calculation is specified, the device is placed in extent mode and the scene is redrawn. As in selection mode, the frame buffer is unchanged. The extent box is queried using vgl_DrawFunExtentQuery and displayed.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static void
draw_scene(vgl_DrawFun *df, vgl_DList *dlist, vgl_Xfm *xfm);
static void
draw_select(vgl_DrawFun *df, Vint ix, Vint iy, Vint numhits,
            Vint indexlist[], Vfloat mindepth[]);
static void
draw_extent(vgl_DrawFun *df, Vfloat lft, Vfloat rgt, Vfloat btm, Vfloat top);

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

static Vfloat rquad[4][3] = {
   {0.,0.,0.}, {1.,0.,0.},  {1.,1.,0.}, {0.,1.,0.} };

static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };

static Vfloat xprompt[3][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.} };

/*----------------------------------------------------------------------
                      Select and Extent Example
----------------------------------------------------------------------*/
int
main()
{
   vgl_DList    *dlist;
   vgl_DrawFun  *dfGD, *dfDL;
   vgl_Xfm      *xfm;

   Vint i;
   Vint xsize, ysize;
   Vint ix, iy, but1, but2, but3;
   Vfloat c[3], x[3];
   Vint index;
   Vfloat lft, rgt, btm, top;
   Vfloat znear, zfar;
   Vint indexlist[2];
   Vfloat mindepth[2], maxdepth[2];
   Vint numhits;
   Vint iparam[4];
   Vchar title[65];
   Vint test;

                   /* create drawing function object */
   dfGD = vgl_DrawFunBegin();

   strcpy(title,"Selection Example, ");
   VglDevCreate (dfGD,VGLDEV_OPENGL,title,&test);

                   /* create DList device */
   dlist = vgl_DListBegin ();
   dfDL = vgl_DrawFunBegin ();
   vgl_DListDrawFun (dlist,dfDL);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,dfGD);

                   /* place quadrilaterals in display list */ 
   for(i = 0; i < 4; i++) {
      index = i+1;
      vgl_DrawFunDataIndex (dfDL,1,1,&index);
      vgl_DrawFunColor (dfDL,cquads[i]);
      vgl_DrawFunPolygon (dfDL,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
      vgl_DrawFunPolygonData (dfDL,VGL_POLYGON,4,xquads[i],
                              3,(Vfloat*)rquad,VGL_NOSHADE,NULL);
   }

                   /* open window and set lighting, etc. */ 
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (dfGD,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (dfGD,title);
   vgl_DrawFunProjOrtho (dfGD,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (dfGD,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (dfGD,VGL_LIGHTMODE,VGL_ON);
   c[0] = .3; c[1] = .3; c[2] = .3;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (dfGD,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .7;  c[1] =  .7;  c[2] =  .7;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (dfGD,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (dfGD,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();

                   /* draw loop */
   while (1) {
      vgl_DrawFunClear (dfGD);

                   /* draw prompt message */ 
      vgl_DrawFunColor (dfGD,cwhite);
      vgl_DrawFunText (dfGD,xprompt[0],"Left   button: select");
      vgl_DrawFunText (dfGD,xprompt[1],"Middle button: extent");
      vgl_DrawFunText (dfGD,xprompt[2],"Right  button: quit");

                   /* draw quads */ 
      draw_scene (dfGD,dlist,xfm);
      vgl_DrawFunSwap (dfGD);

                   /* poll mouse */ 
      vgl_DrawFunPollMouse (dfGD,&ix,&iy,&but1,&but2,&but3);
                   /* select */ 
      if(but1) {
         vgl_DrawFunSelectBuffer (dfGD,2,indexlist,mindepth,maxdepth);
         vgl_DrawFunRender (dfGD,VGL_SELECT);
         iparam[0] = ix;  iparam[1] = ix;
         iparam[2] = iy;  iparam[3] = iy;
         vgl_DrawFunSelectRegion (dfGD,VGL_REGION_RECTANGLE,iparam);
         draw_scene (dfGD,dlist,xfm);
         vgl_DrawFunRender (dfGD,VGL_RENDER);
         vgl_DrawFunSelectQuery (dfGD,&numhits);
         vgl_DrawFunProjOrtho (dfGD,0.,(Vfloat)(xsize-1),
                                    0.,(Vfloat)(ysize-1), -1.,1.);
         draw_select (dfGD,ix,iy,numhits,indexlist,mindepth);
         vgl_DrawFunProjOrtho (dfGD,-5.,5.,-5.,5.,-5.,5.);

                   /* extent */ 
      } else if(but2) {
         vgl_DrawFunRender (dfGD,VGL_EXTENT);
         draw_scene (dfGD,dlist,xfm);
         vgl_DrawFunRender (dfGD,VGL_RENDER);
         vgl_DrawFunExtentQuery (dfGD,&lft,&rgt,&btm,&top,&znear,&zfar);
         vgl_DrawFunProjOrtho (dfGD,0.,(Vfloat)(xsize-1),
                                    0.,(Vfloat)(ysize-1), -1.,1.);
         draw_extent (dfGD,lft,rgt,btm,top);
         vgl_DrawFunProjOrtho (dfGD,-5.,5.,-5.,5.,-5.,5.);

                   /* quit */ 
      } else if(but3) {
         break;
      }
   }

                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGD);

                   /* free all objects */ 
   vgl_DrawFunEnd  (dfGD);
   vgl_DrawFunEnd  (dfDL);
   vgl_DListEnd    (dlist);
   vgl_XfmEnd      (xfm);

   VglDevDestroy ();
   return 0;
}

static void
draw_scene(vgl_DrawFun *df, vgl_DList *dlist, vgl_Xfm *xfm)
{
   Vfloat tm[4][4];

                   /* draw scene in display list */ 
   vgl_DrawFunXfmPush (df);
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
   vgl_DListCall (dlist);
   vgl_DrawFunXfmPop (df);
}

static void
draw_select(vgl_DrawFun *df, Vint ix, Vint iy, Vint numhits,
            Vint indexlist[], Vfloat mindepth[])
{
   Vfloat xi[3];
   Vchar stg[33];

   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);
   vgl_DrawFunColor (df,cwhite);
   xi[0] = ix; xi[1] = iy; xi[2] = 0.;
   if(numhits == 0) {
      sprintf(stg,"no hits\n");
   } else if(numhits == 1) {
      sprintf(stg,"index = %d\n",indexlist[0]);
   } else if(numhits == 2) {
      if(mindepth[0] < mindepth[1]) {
         sprintf(stg,"index = %d,%d\n",indexlist[0],indexlist[1]);
      } else {
         sprintf(stg,"index = %d,%d\n",indexlist[1],indexlist[0]);
      }
   }
   vgl_DrawFunText (df,xi,stg);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_OFF);
   vgl_DrawFunFlush (df);
}

static void
draw_extent(vgl_DrawFun *df, Vfloat lft, Vfloat rgt, Vfloat btm, Vfloat top)
{
   Vfloat xrect[4][3];

                   /* draw white extent rectangle */ 
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_ON);
   vgl_DrawFunColor (df,cwhite);
   xrect[0][0] = lft;  xrect[0][1] = btm;  xrect[0][2] = 0.;  
   xrect[1][0] = rgt;  xrect[1][1] = btm;  xrect[1][2] = 0.;  
   xrect[2][0] = rgt;  xrect[2][1] = top;  xrect[2][2] = 0.;  
   xrect[3][0] = lft;  xrect[3][1] = top;  xrect[3][2] = 0.;  
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,4,xrect);
   vgl_DrawFunFlush (df);
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_OFF);
}


Table of Contents

13.34 Example 10a, Picking Using Unprojection

This example illustrates the use of "unprojection" in 3D object picking. The example is a reworking of Example 10. Whereas Example 10 implemented 3D object picking using the selection render mode, this example illustrates picking using the XfmstackUnproject function. The XfmstackUnproject function is used to find the endpoints of a line in world coordinates which represents the line of sight. This line must be intersected with the elements in the application data base by the user.

As opposed to picking with selection mode, it is not necessary to be able to regenerate the 3D scene explicitly for selection. Since the intersection of the line of sight with the appropriate 3D objects is performed by the application instead of the rendering software, the application can customize the intersection test to pick "hollow" objects or perform fast spatial searches to optimize the picking process.

The four rectangles of Example 9 are initially drawn to a display list object using the DList module. Note that the "index" does not need to be defined since selection mode will not used. During the polling loop, the scene is first drawn to the screen. A Xfmstack object is loaded with the current viewing transformation when the scene is drawn. A device coordinate (pixel) point is selected by the cursor in the plane of the window. Two points, dnear and dfar at depth device coordinates 0. and 1. respectively are then unprojected to world coordinates. The application must then intersect this line with the appropriate 3D geometric objects, in this example 4 rectangles, to determine which objects have been picked.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static void
draw_scene(vgl_DrawFun *df, vgl_DList *dlist, vgl_Xfm *xfm,
           vgl_Xfmstack *xfmstack);
static void
intersect_elem(Vint nelem, Vfloat xquads[][4][3],
                Vfloat wnear[3], Vfloat wfar[3],
                Vint *numints, Vint indexlist[]);
static void
draw_pick(vgl_DrawFun *df, Vint ix, Vint iy, Vint numints, Vint indexlist[]);

static Vfloat xquads[4][4][3] = {
   {{2.,-1.,2.}, {2.,-1.,-2.}, {2.,1.,-2.}, {2.,1.,2.}},
   {{2.,-1.,-2.}, {-2.,-1.,-2.}, {-2.,1.,-2.}, {2.,1.,-2.}},
   {{-2.,-1.,-2.}, {-2.,-1.,2.}, {-2.,1.,2.}, {-2.,1.,-2.}},
   {{-2.,-1.,2.}, {2.,-1.,2.}, {2.,1.,2.}, {-2.,1.,2.}} };

static Vfloat rquad[4][3] = {
   {0.,0.,0.}, {1.,0.,0.},  {1.,1.,0.}, {0.,1.,0.} };

static Vfloat cquads[4][3] = {
   {1.,0.,0.}, {0.,1.,0.}, {0.,0.,1.}, {.5,.5,.5} };

static Vfloat cwhite[3] = {
   1.,1.,1. };

static Vfloat xprompt[3][3] = {
   {-4.5, -3.5, 0.},
   {-4.5, -3.9, 0.},
   {-4.5, -4.3, 0.} };

/*----------------------------------------------------------------------
                      Project/Unproject Example
----------------------------------------------------------------------*/
int
main()
{
   vgl_DList    *dlist;
   vgl_DrawFun  *dfGD, *dfDL;
   vgl_Xfm      *xfm;
   vgl_Xfmstack *xfmstack;

   Vint i;
   Vint xsize, ysize;
   Vint ix, iy, but1, but2, but3;
   Vfloat c[3], x[3];
   Vfloat dnear[3], dfar[3];
   Vfloat wnear[3], wfar[3];
   Vchar title[65];
   Vint test;
   Vint numints, indexlist[4];

                   /* create drawing function object */
   dfGD = vgl_DrawFunBegin();

   strcpy(title,"Project/Unproject Example, ");
   VglDevCreate (dfGD,VGLDEV_OPENGL,title,&test);

                   /* create DList device */
   dlist = vgl_DListBegin ();
   dfDL = vgl_DrawFunBegin ();
   vgl_DListDrawFun (dlist,dfDL);
   vgl_DListSetObject (dlist,VGL_DRAWFUN,dfGD);

                   /* place quadrilaterals in display list */ 
   for(i = 0; i < 4; i++) {
      vgl_DrawFunColor (dfDL,cquads[i]);
      vgl_DrawFunPolygon (dfDL,VGL_POLYGON,4,xquads[i],VGL_NOSHADE,NULL);
      vgl_DrawFunPolygonData (dfDL,VGL_POLYGON,4,xquads[i],
                              3,(Vfloat*)rquad,VGL_NOSHADE,NULL);
   }

                   /* open window and set lighting, etc. */ 
   xsize = 400;
   ysize = 400;
   vgl_DrawFunPositionWindow (dfGD,200,200,xsize,ysize);
   vgl_DrawFunOpenWindow (dfGD,title);
   vgl_DrawFunProjOrtho (dfGD,-5.,5.,-5.,5.,-5.,5.);
   vgl_DrawFunSetMode (dfGD,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (dfGD,VGL_LIGHTMODE,VGL_ON);
   c[0] = .3; c[1] = .3; c[2] = .3;
   x[0] = 0.; x[1] = 0.; x[2] = 0.;
   vgl_DrawFunLight (dfGD,0,VGL_LIGHT_AMBIENT,c,x);
   c[0] =  .7;  c[1] =  .7;  c[2] =  .7;
   x[0] =  1.;  x[1] =  1.;  x[2] =  1.;
   vgl_DrawFunLight (dfGD,1,VGL_LIGHT_DISTANT,c,x);
   x[0] = -1.;  x[1] = -1.;  x[2] = -1.;
   vgl_DrawFunLight (dfGD,2,VGL_LIGHT_DISTANT,c,x);

                   /* create transformation object */
   xfm = vgl_XfmBegin ();

                   /* create transformation stack object */
   xfmstack = vgl_XfmstackBegin ();

                   /* draw loop */
   while (1) {
      vgl_DrawFunClear (dfGD);

                   /* draw prompt message */ 
      vgl_DrawFunColor (dfGD,cwhite);
      vgl_DrawFunText (dfGD,xprompt[0],"Left   button: pick");
      vgl_DrawFunText (dfGD,xprompt[1],"Middle button: refresh");
      vgl_DrawFunText (dfGD,xprompt[2],"Right  button: quit");

                   /* draw quads */ 
      draw_scene (dfGD,dlist,xfm,xfmstack);
      vgl_DrawFunSwap (dfGD);

                   /* poll mouse */ 
      vgl_DrawFunPollMouse (dfGD,&ix,&iy,&but1,&but2,&but3);

                   /* pick */ 
      if(but1) {
         dnear[0] = ix;  dnear[1] = iy;  dnear[2] = 0.;
         dfar[0]  = ix;  dfar[1]  = iy;  dfar[2]  = 1.;
                   /* unproject near and far points */ 
         vgl_XfmstackUnproject (xfmstack,dnear[0],dnear[1],dnear[2],
                                         &wnear[0],&wnear[1],&wnear[2]);
         vgl_XfmstackUnproject (xfmstack,dfar[0],dfar[1],dfar[2],
                                         &wfar[0],&wfar[1],&wfar[2]);

                   /* intersect line with elements */ 
         intersect_elem (4,xquads,wnear,wfar,&numints,indexlist);

         vgl_DrawFunProjOrtho (dfGD,0.,(Vfloat)(xsize-1),
                                    0.,(Vfloat)(ysize-1), -1.,1.);
         draw_pick (dfGD,ix,iy,numints,indexlist);
         vgl_DrawFunProjOrtho (dfGD,-5.,5.,-5.,5.,-5.,5.);

                   /* refresh */ 
      } else if(but2) {
         draw_scene (dfGD,dlist,xfm,xfmstack);

                   /* quit */ 
      } else if(but3) {
         break;
      }
   }

                   /* close window */ 
   vgl_DrawFunCloseWindow (dfGD);

                   /* free all objects */ 
   vgl_DrawFunEnd  (dfGD);
   vgl_DrawFunEnd  (dfDL);
   vgl_DListEnd    (dlist);
   vgl_XfmEnd      (xfm);
   vgl_XfmstackEnd (xfmstack);

   VglDevDestroy ();
   return 0;
}

static void
draw_scene(vgl_DrawFun *df, vgl_DList *dlist, vgl_Xfm *xfm,
           vgl_Xfmstack *xfmstack)
{
   Vfloat tm[4][4];
   Vint iparam[4];

                   /* draw scene in display list */ 
   vgl_DrawFunXfmPush (df);
   vgl_XfmRotateVector (xfm,48.*.017453,.75,1.,0.);
   vgl_XfmGetMatrix (xfm,tm);
   vgl_DrawFunXfmLoad (df,tm);
                   /* query and load complete viewing transformation 
                      into transformation stack object */ 
   vgl_DrawFunGetFloat (df,VGL_MODELVIEWMATRIX,(Vfloat*)tm);
   vgl_XfmSetMatrix (xfm,tm);
   vgl_XfmstackLoad (xfmstack,xfm);
   vgl_DrawFunGetFloat (df,VGL_PROJECTIONMATRIX,(Vfloat*)tm);
   vgl_XfmSetMatrix (xfm,tm);
   vgl_XfmstackProj (xfmstack,xfm);
   vgl_DrawFunGetInteger (df,VGL_VIEWPORT,iparam);
   vgl_XfmstackSetViewport (xfmstack,iparam[0],iparam[1],iparam[2],iparam[3]);

   vgl_DListCall (dlist);

   vgl_DrawFunXfmPop (df);
}

static void
intersect_elem(Vint nelem, Vfloat xquads[][4][3],
               Vfloat wnear[3], Vfloat wfar[3],
               Vint *numints, Vint indexlist[])
{
   Vint j, k;
   Vfloat v1[3], v2[3], nv[3];
   Vfloat wd[3], vp[3];
   Vfloat d, t;
   Vfloat a, b;

   *numints = 0;
                   /* loop through elements */ 
   for(j = 0; j < nelem; j++) {
      for(k = 0; k < 3; k++) {
         v1[k] = xquads[j][1][k] - xquads[j][0][k];
         v2[k] = xquads[j][3][k] - xquads[j][0][k];
         wd[k] = wnear[k] - wfar[k];
      }
      nv[0] = v1[1]*v2[2]-v1[2]*v2[1];
      nv[1] = v1[2]*v2[0]-v1[0]*v2[2];
      nv[2] = v1[0]*v2[1]-v1[1]*v2[0];
      d = -(xquads[j][0][0] * nv[0] +
            xquads[j][0][1] * nv[1] +
            xquads[j][0][2] * nv[2]);
      t = - (d + (nv[0]*wfar[0] + nv[1]*wfar[1] + nv[2]*wfar[2])) /
               (nv[0]*wd[0] + nv[1]*wd[1] + nv[2]*wd[2]);
      for(k = 0; k < 3; k++) {
         vp[k] = (wfar[k] + t*wd[k]) - xquads[j][0][k];
      }
                   /* project onto 4 by 2 rectangle squared base and height */ 
      a = (v1[0]*vp[0] + v1[1]*vp[1] + v1[2]*vp[2]) / 16.;
      b = (v2[0]*vp[0] + v2[1]*vp[1] + v2[2]*vp[2]) /  4.;
                   /* check for within rectangle limits */ 
      if(a >= 0.  &&  a <= 1. &&
         b >= 0.  &&  b <= 1.) {
         indexlist[*numints] = j+1;
         *numints += 1;
      }
   }
}

static void
draw_pick(vgl_DrawFun *df, Vint ix, Vint iy, Vint numints, Vint indexlist[])
{
   Vfloat xi[3];
   Vchar stg[33];

   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);
   vgl_DrawFunColor (df,cwhite);
   xi[0] = ix; xi[1] = iy; xi[2] = 0.;
   if(numints == 0) {
      sprintf(stg,"no intersections\n");
   } else if(numints == 1) {
      sprintf(stg,"index = %d\n",indexlist[0]);
   } else if(numints == 2) {
      sprintf(stg,"index = %d,%d\n",indexlist[0],indexlist[1]);
   }
   vgl_DrawFunText (df,xi,stg);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_FRONTBUFFERDRAWMODE,VGL_OFF);
   vgl_DrawFunFlush (df);
}

Table of Contents

13.35 Example 11, Drawing Texture Mapped Polygons

This example illustrates using a Texture object to apply one dimensional texture maps to a triangle and quadrilateral polygon. Two texture maps are defined. The first is a built-in texture map which represents a banded color spectrum of varying hue from magenta-red to magenta passing through blue, green, cyan, yellow, etc. This texture is defined as texture index 1 using vgl_DrawFunTextureDefine. Note that this function makes a copy of the Texture object. Subsequent changes to the Texture object do not affect the texture information associated with index 1. A second one-dimensional texture is algorithmically defined as a banded grayscale. This texture replaces the first texture in the Texture object and is loaded as texture index 2. The default texture parameters are not changed in either definition (see vgl_TextureBegin). The texture environment is modulation mode. This mode is often used to modify a lit polygon with the colors of a texture map. In practice the polygon is drawn with a base color of white. Lighting operations are performed on the base color which is then modulated by the texture map colors.

A triangle and quadrilateral polygon are drawn with each texture. A texture is enabled by calling vgl_DrawFunTextureSelect. Finally the same polygons are drawn with texture mapping disabled. In this case, the base color of white is unaltered by a texture map.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static void
draw_tri_and_quad(vgl_DrawFun *df, Vint index);

static Vfloat xtri[4][3] = {
   {0.,.5,0.}, {.5,-.5,0.}, {-.5,-.5,0.}, {-1.,.5,0.} };

static Vfloat ttri[4] = {
   0.,0.,1.,1. };

/*----------------------------------------------------------------------
                      Draw Textured Polygons
----------------------------------------------------------------------*/
int
main()
{
   vgl_DrawFun *df;
   vgl_Texture *texture;

   int i;
   Vchar title[65];
   Vint test;
   Vfloat cgray[64][4];
   Vfloat gray;

                   /* create drawing functions */
   df  = vgl_DrawFunBegin();

   strcpy(title,"Texture Example, ");
   VglDevCreate (df,VGLDEV_OPENGL,title,&test);

                   /* open windows and file */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
   vgl_DrawFunOpenWindow (df,title);

                   /* define textures */ 
   texture = vgl_TextureBegin ();

                   /* built-in is index 1 */ 
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_DrawFunTextureDefine (df,1,texture);

                   /* gray banded is index 2 */ 
   for(i = 0; i < 64; i++) {
      gray = i / 64.;
      gray = ((int)(gray*10)) / 10.;
      cgray[i][0] = gray;
      cgray[i][1] = gray;
      cgray[i][2] = gray;
      cgray[i][3] = 1.;
   }
   vgl_TextureDef (texture,4,64,1);
   vgl_TextureSetColors (texture,(Vfloat*)cgray);
   vgl_DrawFunTextureDefine (df,2,texture);

                   /* free texture object */ 
   vgl_TextureEnd (texture);

                   /* draw with texture 1 */
   draw_tri_and_quad (df,1);

                   /* draw with texture 2 */
   draw_tri_and_quad (df,2);

                   /* draw with no texturing */
   draw_tri_and_quad (df,0);

                   /* close windows */
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_DrawFunEnd (df);

   VglDevDestroy ();
   return 0;
}

/*----------------------------------------------------------------------
                      utility
----------------------------------------------------------------------*/
static void
draw_tri_and_quad(vgl_DrawFun *df, Vint index)
{
   Vfloat c[3];

                   /* draw triangle */
   vgl_DrawFunClear (df);

                   /* set white base color */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunTextureSelect (df,index);

                   /* draw triangle outlined in yellow */ 
   vgl_DrawFunPolygon (df,VGL_POLYGON,3,xtri,VGL_1DTEXTURE,(Vfloat*)ttri);

                   /* set outline color and turn off texturing */ 
   c[0] = 1.; c[1] = 1.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunTextureSelect (df,0);
   vgl_DrawFunLineWidth (df,4);

                   /* draw outline */ 
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,3,xtri);

                   /* set texturing back on */ 
   vgl_DrawFunTextureSelect (df,index);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* draw quadrilateral */ 
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_POLYGON,4,xtri,VGL_1DTEXTURE,(Vfloat*)ttri);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);
}


Table of Contents

13.36 Example 11a, Drawing Stippled Polygons Using Bitmap

This example illustrates using a Bitmap object to draw stippled polygons. First, 32 useful built-in bitmaps are used to stipple polygons. Then a user defined bitmap is drawn and then finally a polygon with no stippling is drawn. The 32 built-in bitmaps are loaded one at a time using vgl_BitmapLoad and assigned to identifier 1 using vgl_DrawFunBitmapDefine. The bitmap is then selected and used to draw a stippled polygon. A user defined 8 bit by 8 bit bitmap is generated using vgl_BitmapDef and vgl_BitmapSetRast and used to draw a polygon. Finally the polygon is drawn without stippling by disabling stippling. This is done by selecting bitmap 0 prior to drawing the polygon.
#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static void
draw_quad(vgl_DrawFun *df, Vchar *text);

static Vfloat xquad[4][3] = {
   {.5,-.5,0.}, {.5,.5,0.}, {-.5,.5,0.}, {-.5,-.5,0.} };

                   /* list of built-in bitmaps to display */ 
static Vint lbitmap[32] = {
     BITMAP_XES5,
     BITMAP_XES7,
     BITMAP_CIRCLES5,
     BITMAP_CIRCLES7,
     BITMAP_DIAMONDS5,
     BITMAP_DIAMONDS7,
     BITMAP_BOXES5,
     BITMAP_BOXES7,
     BITMAP_SQUARE4,
     BITMAP_SQUARE8,
     BITMAP_SQUARE8B,
     BITMAP_SQUARE16B,
     BITMAP_CROSS8,
     BITMAP_CROSS8B,
     BITMAP_CROSS16,
     BITMAP_CROSS16B,
     BITMAP_BDIAGONAL8,
     BITMAP_BDIAGONAL8B,
     BITMAP_BDIAGONAL16,
     BITMAP_BDIAGONAL16B,
     BITMAP_FDIAGONAL8,
     BITMAP_FDIAGONAL8B,
     BITMAP_FDIAGONAL16,
     BITMAP_FDIAGONAL16B,
     BITMAP_HORIZONTAL4,
     BITMAP_HORIZONTAL8,
     BITMAP_HORIZONTAL8B,
     BITMAP_HORIZONTAL16B,
     BITMAP_VERTICAL4,
     BITMAP_VERTICAL8,
     BITMAP_VERTICAL8B,
     BITMAP_VERTICAL16B };

                   /* character string name of built-in bitmaps */ 
static Vchar *cbitmap[32] = {
     "BITMAP_XES5",
     "BITMAP_XES7",
     "BITMAP_CIRCLES5",
     "BITMAP_CIRCLES7",
     "BITMAP_DIAMONDS5",
     "BITMAP_DIAMONDS7",
     "BITMAP_BOXES5",
     "BITMAP_BOXES7",
     "BITMAP_SQUARE4",
     "BITMAP_SQUARE8",
     "BITMAP_SQUARE8B",
     "BITMAP_SQUARE16B",
     "BITMAP_CROSS8",
     "BITMAP_CROSS8B",
     "BITMAP_CROSS16",
     "BITMAP_CROSS16B",
     "BITMAP_BDIAGONAL8",
     "BITMAP_BDIAGONAL8B",
     "BITMAP_BDIAGONAL16",
     "BITMAP_BDIAGONAL16B",
     "BITMAP_FDIAGONAL8",
     "BITMAP_FDIAGONAL8B",
     "BITMAP_FDIAGONAL16",
     "BITMAP_FDIAGONAL16B",
     "BITMAP_HORIZONTAL4",
     "BITMAP_HORIZONTAL8",
     "BITMAP_HORIZONTAL8B",
     "BITMAP_HORIZONTAL16B",
     "BITMAP_VERTICAL4",
     "BITMAP_VERTICAL8",
     "BITMAP_VERTICAL8B",
     "BITMAP_VERTICAL16B" };

                   /* user defined bitmap */ 
static unsigned char userpat[8] = {
   0x01, 0x01, 0x11, 0x39, 0x11, 0x01, 0x01, 0xff };

/* the user defined bitmap looks like this
   0000000x
   0000000x
   000x000x
   00xxx00x
   000x000x
   0000000x
   0000000x
   xxxxxxxx
*/

/*----------------------------------------------------------------------
                      Drawing Stippled Polygons Using Bitmap
----------------------------------------------------------------------*/
int
main()
{
   vgl_DrawFun *df;
   vgl_Bitmap *bitmap;

   int i;
   Vchar title[65];
   Vint test;

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

   strcpy(title,"Bitmap Example, ");
   VglDevCreate (df,VGLDEV_OPENGL,title,&test);

                   /* open windows and file */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
   vgl_DrawFunOpenWindow (df,title);

                   /* define bitmap */ 
   bitmap = vgl_BitmapBegin ();

                   /* loop through built-in bitmaps */ 
   for(i = 0; i < 32; i++) {
                   /* load and define */ 
      vgl_BitmapLoad (bitmap,lbitmap[i]);
      vgl_DrawFunBitmapDefine (df,1,bitmap);
                   /* now draw */ 
      vgl_DrawFunBitmapSelect (df,1);
      draw_quad (df,cbitmap[i]);
   }
                   /* draw user defined bitmap */ 
   vgl_BitmapDef (bitmap,8,8);
   vgl_BitmapSetRast (bitmap,userpat);
   vgl_DrawFunBitmapDefine (df,1,bitmap);
   vgl_DrawFunBitmapSelect (df,1);
   draw_quad (df,"User Bitmap");

                   /* free bitmap object */ 
   vgl_BitmapEnd (bitmap);

                   /* draw with no bitmap */
   vgl_DrawFunBitmapSelect (df,0);
   draw_quad (df,"No Bitmap");

                   /* close windows */
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_DrawFunEnd (df);

   VglDevDestroy ();
   return 0;
}

/*----------------------------------------------------------------------
                      utility
----------------------------------------------------------------------*/
static void
draw_quad(vgl_DrawFun *df, Vchar *text)
{
   Vfloat c[3];
   Vfloat xtext[3];

                   /* draw quad */
   vgl_DrawFunClear (df);

                   /* set white color */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);

                   /* draw text */ 
   xtext[0] = -.5;
   xtext[1] = .8;
   xtext[2] = 0.;
   vgl_DrawFunText (df,xtext,text);

                   /* draw quadrilateral outlined in red */ 
   vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquad,VGL_NOSHADE,NULL);

                   /* set outline color */ 
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunLineWidth (df,1);

                   /* draw outline */ 
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,4,xquad);

   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);
}


Table of Contents

13.37 Example 11b, Draw Image as 1D or 2D Textured Polygon

This example illustrates reading an image file and applying it as a 1D or 2D texture on a quadrilateral. The image file dimensions are checked to see if it can be applied as a 1D texture by testing for the ysize equaling unity. Then the image is scaled to the largest sizes in the x and y directions which are a power of two and less than the image sizes. The scaling of the image is then performed using vgl_FBufferZoom. If the image is not scaled to sizes which are powers of two, then the function vgl_TextureFBuffer which is used to convert the image to a texture will truncate the image to the largest sizes which are powers of two.
#include "base/base.h"
#include "vgl/vgl.h"
#include "vgldev.h"

static void
draw_quad(vgl_DrawFun *df, Vint index, Vint tdim);

                   /* coordinates of quadrilateral */ 
static Vfloat xquad[4][3] = {
   {-.5,-.5,0.}, 
   { .5,-.5,0.}, 
   { .5, .5,0.}, 
   {-.5, .5,0.} };
                   /* 2D texture coordinates */ 
static Vfloat tquad2[4][2] = {
   {0.,0.}, {1.,0.}, {1.,1.}, {0.,1.} };
                   /* 1D texture coordinates */ 
static Vfloat tquad1[4] = {
   0.,1.,1.,0. };

/*----------------------------------------------------------------------
                      Draw Image as 1D or 2D Textured Polygon
----------------------------------------------------------------------*/
int
main(int argc, char **argv)
{
   char infile[256];
   vgl_FBuffer *fbuffer, *fbuffert;
   vgl_Texture *texture;
   vgl_DrawFun *df;
   Vchar title[65];
   Vint test;
   Vint xsize, ysize, tdim, tsx, tsy;
                   /* read image file source for texture */ 
                   /* check for proper number of arguments */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s inputfile\n",argv[0]);
      fprintf(stderr," inputfile is blank, 'earth.gif' is assumed\n");
      strcpy(infile,"earth.gif");
   } else {
      strcpy(infile,argv[1]);
   }
                   /* create FBuffer object */
   fbuffer = vgl_FBufferBegin();
                   /* decode input display file format and file name */
   if(strstr(infile,"gif")) {
      vgl_FBufferReadGIF (fbuffer,infile);
   } else if(strstr(infile,"bmp")) {
      vgl_FBufferReadBMP (fbuffer,infile);
   } else if(strstr(infile,"jpg")) {
      vgl_FBufferReadJPEG (fbuffer,infile);
   } else {
      fprintf(stderr,"Error: Unsupported input file format %s\n",infile);
      exit(1);
   }
   vgl_FBufferInq (fbuffer,&xsize,&ysize);
   printf("xsize= %d, ysize= %d, file= %s\n",xsize,ysize,infile);
                   /* determine texture dimension */ 
   if(ysize == 1) {
      tdim = 1;
   } else {
      tdim = 2;
   }
                   /* find largest sizes which are a power of two */
   for(tsx = 1; tsx < 1024; tsx *= 2) {
      if(2*tsx > xsize)  break;
   }
   for(tsy = 1; tsy < 1024; tsy *= 2) {
      if(2*tsy > ysize)  break;
   }
                   /* scale image to texture friendly size */
   printf("texture dimension= %d\n",tdim);
   printf("texture scaled tsx= %d, tsy= %d\n",tsx,tsy);
   fbuffert = vgl_FBufferBegin();
   vgl_FBufferDef (fbuffert,tsx,tsy);
   vgl_FBufferZoom (fbuffert,fbuffer);
   vgl_FBufferAlpha (fbuffert,1.);

                   /* create drawing functions */
   df  = vgl_DrawFunBegin();

   strcpy(title,"1D or 2D Texture Example, ");
   VglDevCreate (df,VGLDEV_OPENGL,title,&test);

                   /* open windows and file */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
   vgl_DrawFunOpenWindow (df,title);

                   /* create texture from fbuffer */ 
   texture = vgl_TextureBegin ();
   vgl_TextureFBuffer (texture,fbuffert);

                   /* free fbuffer */ 
   vgl_FBufferEnd (fbuffer);
   vgl_FBufferEnd (fbuffert);

   vgl_TextureSetEnv (texture,TEXTURE_DECAL);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_TextureEnd (texture);

                   /* draw with texture 1 */
   draw_quad (df,1,tdim);

                   /* close windows */
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_DrawFunEnd (df);

   VglDevDestroy ();
   return 0;
}

/*----------------------------------------------------------------------
                      utility
----------------------------------------------------------------------*/
static void
draw_quad(vgl_DrawFun *df, Vint index, Vint tdim)
{
   Vfloat c[3];

   vgl_DrawFunTextureSelect (df,index);
                   /* draw quadrilateral */ 
   vgl_DrawFunClear (df);
                   /* set white base color */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* 1D texture */ 
   if(tdim == 1) {
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquad,VGL_1DTEXTURE,(Vfloat*)tquad1);
                   /* 2D texture */ 
   } else {
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xquad,VGL_2DTEXTURE,(Vfloat*)tquad2);
   }
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,5.);
}


Table of Contents

13.38 Example 12, 3D Object and 2D Image Animation

This example illustrates generating an animation using two different techniques. The two methods, which may be referred to as 3D object animation and 2D image animation, offer tradeoffs between user interaction and animation speed. 3D object animation using the DList module allows the user to interact with the frames of the animation since each DList object holds complete 3D geometry. However as the complexity of the 3D geometry increases the rendering speed suffers. 2D image animation using the Pixelmap module guarantees a certain animation speed regardless of the geometrical complexity of the scene. Since each Pixelmap object holds only 2D pixel information there is little opportunity for the user to interact with the animation to perform operations such as rotating the object being rendered.

For the 3D object animation a List object is used to hold a set of DList objects, each DList object holds a complete set of 3D graphics primitives for each frame in the animation. The animation in this case is the warping of a simple cone. In the case of 3D object animation the geometry is created for each frame without rendering it to the screen. In an actual application it is recommended to render each display list as it is generated as a visual cue to the user that the animation is being properly created. Once the DList objects are created, the animation is "played back" by rendering each DList object in turn.

The 2D image animation is generated by drawing each frame of the warping cone directly to the display device in "immediate mode". A Pixelmap object is instanced to hold the frame buffer contents for each frame. Pixelmap objects are device dependent and are designed for playback speed. A single "FBuffer object is instanced to hold a device independent image of each frame and write the data to an animated .gif file, exam12.gif.

Note the use of the vsy_ListForEach function to delete the DList and Pixelmap objects.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r1, Vfloat r2, Vfloat h);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

static Vfloat xtex[3] = {
    -1.2,.8,0. };

/*----------------------------------------------------------------------
                      3D Object and 2D Image Animation
----------------------------------------------------------------------*/
int
main()
{
   int i, j;
   Vfloat tm4[4][4];
   Vfloat c[3];

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vsy_List *list;

   vgl_DList    *dlist;
   vgl_Pixelmap *pixelmap;
   vgl_Quadric *qu;
   vgl_DrawFun *dfGL, *dfDL;
   vgl_Xfm     *xfm;
   vgl_FBuffer *fbuffer;
   vgl_OpenGLDev *ogldev;

                   /* open X display */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create GL device and drawing functions */
   ogldev = vgl_OpenGLDevBegin();
   dfGL = vgl_DrawFunBegin();
   vgl_OpenGLDevDrawFun (ogldev,dfGL);

   list = vsy_ListBegin();

                   /* open window */
   vgl_DrawFunPositionWindow (dfGL,400,400,400,300);
   vgl_DrawFunOpenWindow (dfGL,"OpenGL window");

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (dfGL,-1.3333,1.3333,-1.,1.,-2.,2.);
   vgl_DrawFunDepthRange (dfGL,0.,1.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (dfGL,VGL_ZBUFFERMODE,VGL_ON);

                   /* set lights */ 
   vgl_DrawFunLight (dfGL,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (dfGL,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (dfGL,VGL_LIGHTMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();

                   /* create transform object */ 
   xfm = vgl_XfmBegin();
   vgl_XfmRotate (xfm,-3.14159/4.,XFM_YAXIS);
   vgl_XfmGetMatrix (xfm,tm4);

                   /* create drawing functions */
   dfDL = vgl_DrawFunBegin();

                   /* 3D object animation using DList objects */
                   /* create 10 frames in the animation, warping the cone */
   for(i = 1; i <= 10; i++) {
      dlist = vgl_DListBegin();
      vgl_DListDrawFun (dlist,dfDL);
      vgl_DListSetObject (dlist,VGL_DRAWFUN,dfGL);
      vsy_ListInsert (list,i,(Vobject*)dlist);
      c[0] = 1.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (dfDL,c);
      vgl_DrawFunText (dfDL,xtex,"3D object DList");
      draw_cone (dfDL,qu,.4+.04*i,.8-.04*i,1.);
   }

                   /* animate 3D display lists 5 times */ 
   vgl_DrawFunXfmLoad (dfGL,tm4);
   for(j = 0; j < 5; j++) {
      for(i = 1; i <= 10; i++) {
         vgl_DrawFunClear (dfGL);
         vsy_ListRef (list,i,(Vobject**)&dlist);
         vgl_DListCall (dlist);
         vgl_DrawFunSwap (dfGL);
         vgl_DrawFunDelay (dfGL,.05);
      }
      for(i = 9; i >= 2; i--) {
         vgl_DrawFunClear (dfGL);
         vsy_ListRef (list,i,(Vobject**)&dlist);
         vgl_DListCall (dlist);
         vgl_DrawFunSwap (dfGL);
         vgl_DrawFunDelay (dfGL,.05);
      }
   }
                   /* delete display lists */ 
   vsy_ListForEach (list,(void(*)(Vobject*))vgl_DListEnd);
   vsy_ListClear (list);

   fbuffer = vgl_FBufferBegin ();

                   /* 2D image animation using Pixelmap objects */
                   /* create 10 frames in the animation, warping the cone */
                   /* create an animated .gif file */
   for(i = 1; i <= 10; i++) {
      vgl_DrawFunClear (dfGL);
      c[0] = 1.; c[1] = 1.; c[2] = 1.;
      vgl_DrawFunColor (dfGL,c);
      vgl_DrawFunText (dfGL,xtex,"2D image Pixelmap");
      draw_cone (dfGL,qu,.4+.04*i,.8-.04*i,1.);
      vgl_DrawFunSwap (dfGL);
      pixelmap = vgl_PixelmapBegin();
      vgl_DrawFunPixelmapCreate (dfGL,pixelmap);
      vgl_DrawFunPixelmapRead (dfGL,pixelmap);
      vsy_ListInsert (list,i,(Vobject*)pixelmap);
      vgl_DrawFunFBufferRead (dfGL,0,0,0,0,fbuffer);
      if(i == 1) {
         vgl_FBufferWriteGIF (fbuffer,"exam12.gif");
      } else {
         vgl_FBufferAppendGIF (fbuffer,"exam12.gif");
      }
   }
                   /* animate 2D pixelmaps 5 times */
                   /* 20 frames per second maximum */
   for(j = 0; j < 5; j++) {
      for(i = 1; i <= 10; i++) {
         vgl_DrawFunClear (dfGL);
         vsy_ListRef (list,i,(Vobject**)&pixelmap);
         vgl_DrawFunPixelmapWrite (dfGL,pixelmap);
         vgl_DrawFunSwap (dfGL);
         vgl_DrawFunDelay (dfGL,.05);
      }
      for(i = 9; i >= 2; i--) {
         vgl_DrawFunClear (dfGL);
         vsy_ListRef (list,i,(Vobject**)&pixelmap);
         vgl_DrawFunPixelmapWrite (dfGL,pixelmap);
         vgl_DrawFunSwap (dfGL);
         vgl_DrawFunDelay (dfGL,.05);
      }
   }
                   /* destory contents of pixelmaps */ 
   for(i = 1; i <= 10; i++) {
      vsy_ListRef (list,i,(Vobject**)&pixelmap);
      vgl_DrawFunPixelmapDestroy (dfGL,pixelmap);
   }
                   /* delete pixelmaps */ 
   vsy_ListForEach (list,(void(*)(Vobject*))vgl_PixelmapEnd);
   vsy_ListClear (list);

                   /* free objects */ 
   vgl_OpenGLDevEnd (ogldev);
   vgl_DrawFunEnd (dfGL);
   vgl_DrawFunEnd (dfDL);
   vgl_QuadricEnd (qu);
   vgl_XfmEnd (xfm);
   vgl_FBufferEnd (fbuffer);
   vsy_ListEnd (list);

                   /* disconnect from X */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone
----------------------------------------------------------------------*/
static void
draw_cone(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r1, Vfloat r2, Vfloat h)
{
   Vfloat c[3];

   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,21);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,21);
   vgl_QuadricCylinder (qu,r1,r2,h);
}

Table of Contents

13.39 Example 13, Software Rendered Image File of a 2D Diagram

This example illustrates rendering a simple 2D diagram to a software frame buffer and writing the resulting image to a GIF file. The software rendering is accomplished using a RendBuf object. A DrawFun object is instanced and loaded with the function pointers to the RendBuf object using vgl_RendBufDrawFun. The size is set to 400 by 300 pixels using vgl_DrawFunPositionWindow. The origin of the software frame buffer is ignored. For 2D drawings the projection should be orthographic and isometric. The limits of the orthographic projection should match the aspect ratio of the pixel dimension of the frame buffer. The z-buffer hidden surface removal is disabled. Consequently the visibility of drawn primitives will be determined by the "Painter's" algorithm.

The background is cleared to white and a variety of line, polygon and text primitives are drawn in constant color and interpolated color. The internal frame buffer, FBuffer, object is retrieved from the RendBuf object using vgl_RendBufGetFBuffer and a GIF file of the frame buffer contents are written using vgl_FBufferWriteGIF.

#include "base/base.h"
#include "vgl/vgl.h"
#include <math.h>


static void
draw_triangle(vgl_DrawFun *df);
static void
draw_circle(vgl_DrawFun *df, Vfloat x[3], Vfloat radius, Vint nedge);
static void
draw_ring(vgl_DrawFun *df, Vfloat x[3], Vfloat inner, Vfloat outer, Vint nedge);

static double twopi = 6.2831853;

/*----------------------------------------------------------------------
                      Software Rendered Image File of a 2D Diagram
----------------------------------------------------------------------*/
int
main()
{
   vgl_RendBuf *rendbuf;
   vgl_DrawFun *df;
   vgl_FBuffer *fbuffer;
   Vfloat x[3], c[3];
   Vfloat xl[2][3];
   vgl_RasFont *rasfont;
   Vfloat path[3], plane[3];

                   /* create drawing function */
   df = vgl_DrawFunBegin();

                   /* create software renderer object, load drawing functions */
   rendbuf = vgl_RendBufBegin();
   vgl_RendBufDrawFun (rendbuf,df);

                   /* open "software" window (400 x 300 pixels) */
   vgl_DrawFunPositionWindow (df,0,0,400,300);
   vgl_DrawFunOpenWindow (df,"Example 13");

                   /* set orthographic projection */
                   /* aspect ratio matches window dimensions */
   vgl_DrawFunProjOrtho (df,-1.,1.,-.75,.75,-1.,1.);
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);

                   /* clear to white background color */ 
   c[0] = 1.;  c[1] = 1.;  c[2] = 1.;
   vgl_DrawFunBackColor (df,c);
   vgl_DrawFunClear (df);

                   /* draw a color interpolated triangle */ 
   draw_triangle (df);

                   /* draw a red circle */
   x[0] = .5;
   x[1] = 0.;
   x[2] = 0.;
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   draw_circle (df,x,0.15,16);

                   /* draw a semi-transparent blue circle */
   x[0] = .7;
   x[1] = .2;
   x[2] = 0.1;
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunTrans (df,.5);
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_ON);
   draw_circle (df,x,0.25,16);
   vgl_DrawFunTrans (df,.0);
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_OFF);

                   /* draw a ring color interpolated from blue to green */
   x[0] = -.25;
   x[1] = .1;
   x[2] = 0.;
   draw_ring (df,x,0.3,0.5,64);

                   /* draw a double width black line */
   vgl_DrawFunLineWidth (df,2);
   xl[0][0] = -.6;  xl[0][1] = -.5;  xl[0][2] = 0.;
   xl[1][0] = 0.;   xl[1][1] = .6;   xl[1][2] = 0.;
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyLine (df,VGL_LINESTRIP,2,xl);

                   /* draw a multisampled (anti-aliased) line */ 
   vgl_DrawFunSetMode (df,VGL_MULTISAMPLEMODE,VGL_ON);
   xl[0][0] = -.7;  xl[0][1] = -.5;  xl[0][2] = 0.;
   xl[1][0] = -.1;   xl[1][1] = .6;   xl[1][2] = 0.;
   vgl_DrawFunPolyLine (df,VGL_LINESTRIP,2,xl);
   vgl_DrawFunSetMode (df,VGL_MULTISAMPLEMODE,VGL_OFF);

                   /* draw text in default font in upper left corner */
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   x[0] = -.9;  x[1] = .65;  x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World");

                   /* draw text plane text */ 
   rasfont = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont,RASFONT_QUALITY9X13);
   vgl_RasFontSetParami (rasfont,RASFONT_TEXTPLANE,SYS_ON);
   vgl_RasFontSetParami (rasfont,RASFONT_DEVICESIZE,SYS_OFF);
   vgl_RasFontSetPixelSize (rasfont,.01);
   vgl_DrawFunRasFontDefine (df,1,rasfont);
   vgl_RasFontEnd (rasfont);
   vgl_DrawFunRasFontSelect (df,1);
   path[0] = 2.;
   path[1] = 1.;
   path[2] = 0.;
   plane[0] = -1.;
   plane[1] = 0.;
   plane[2] = 0.;
   vgl_DrawFunTextPlane (df,path,plane);
   x[0] = -.9;  x[1] = -.65;  x[2] = 0.;
   vgl_DrawFunText (df,x,"Hello World");

                   /* get image buffer */ 
   vgl_RendBufGetFBuffer (rendbuf,&fbuffer);

                   /* write image in gif format to file */ 
   vgl_FBufferWriteGIF (fbuffer,"exam13.gif");
                   /* write image in bmp format to file */ 
   vgl_FBufferWriteBMP (fbuffer,"exam13.bmp");

                   /* close software window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_RendBufEnd (rendbuf);
   vgl_DrawFunEnd (df);
   return 0;
}

static void
draw_triangle(vgl_DrawFun *df)
{
   Vfloat xt[3][3] = {
      {0.,.5,0.}, {.5,-.5,0.}, {-.5,-.5,0.} };
   Vfloat ct[3][3] = {
      {1.,0.,0.},  {0.,1.,0.}, {0.,0.,1.} };
   Vfloat c[3];
   Vuint ixtri[3] = {0,1,2};
                   /* draw triangle */
   vgl_DrawFunPolyElemArray (df,VGL_POLYGON,3,ixtri,xt,
                             VGL_COLOR_3F,ct,0,NULL,0,NULL,0,NULL);
                   /* draw blue outline */ 
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyElemArray (df,VGL_LINELOOP,3,ixtri,xt,
                             0,NULL,0,NULL,0,NULL,0,NULL);
}

static void
draw_circle(vgl_DrawFun *df, Vfloat x[3], Vfloat radius, Vint nedge)
{
   Vint i;
   Vfloat xl[200][3];
   Vdouble angle,ainc;

   /* this check for hard-coded parameter can be removed for efficiency */
   if(nedge > 200) {
      printf("Internal error: max edges = 20\n");
      return;
   }

   ainc = twopi/nedge;
   for(i = 0; i < nedge; i++) {
      angle = ainc*i;
      xl[i][0] = radius*cos(angle) + x[0];
      xl[i][1] = radius*sin(angle) + x[1];
      xl[i][2] = x[2];
   }
   vgl_DrawFunPolygon (df,VGL_POLYGON,nedge,xl,VGL_NOSHADE,NULL);
}

static void
draw_ring(vgl_DrawFun *df, Vfloat x[3], Vfloat inner, Vfloat outer, Vint nedge)
{
   Vint i;
   Vfloat xt[3][3];
   static Vfloat c1[3][3] = { {0.,1.,0.}, {0.,1.,1.}, {0.,1.,1.} };
   static Vfloat c2[3][3] = { {0.,1.,0.}, {0.,1.,1.}, {0.,1.,0.} };
   Vdouble angle, ainc;

   xt[0][2] = x[2];
   xt[1][2] = x[2];
   xt[2][2] = x[2];

   ainc = twopi/nedge;
   for(i = 0; i < nedge; i++) {
      angle = ainc*i;
      xt[0][0] = inner*cos(angle) + x[0];
      xt[0][1] = inner*sin(angle) + x[1];
      xt[1][0] = outer*cos(angle) + x[0];
      xt[1][1] = outer*sin(angle) + x[1];
      xt[2][0] = outer*cos(angle+ainc) + x[0];
      xt[2][1] = outer*sin(angle+ainc) + x[1];
      vgl_DrawFunPolygonColor (df,VGL_POLYGON,3,xt,c1,VGL_NOSHADE,NULL);

      xt[1][0] = xt[2][0];
      xt[1][1] = xt[2][1];
      xt[2][0] = inner*cos(angle+ainc) + x[0];
      xt[2][1] = inner*sin(angle+ainc) + x[1];
      vgl_DrawFunPolygonColor (df,VGL_POLYGON,3,xt,c2,VGL_NOSHADE,NULL);
   }
}

Figure 13-1, Generated RendBuf Image

Table of Contents

13.40 Example 15, Using Clipping Planes

This example illustrates using clipping planes for rendering and selection. The example draws a cone and 7 points. A DataIndex value of 0 is associated with the cone, drawn using a Quadric object, and values 1 through 7 are associated with the 7 points. The example consists of two sections. The first section illustrates defining a clipping plane fixed in space while an object is rotated. The second section illustrates defining a rotating clipping plane while an object is fixed in space.

In the first section a clipping plane, index=0, at x = -.5 is defined using vgl_DrawFunClipPlane. Up to 6 clipping planes may be defined, each given an index from 0 to 5. The position of the clipping plane is fixed when it is defined by the call to vgl_DrawFunClipPlane. After the object is drawn then selection is enabled using the clipping planes. The region type, VGL_REGION_CLIPPLANE specifies that any vertex of a given graphics primitive must be within all the active clipping planes for a hit to be recorded. This means that any vertex of the cone must be within the clipping plane for a hit on it to be recorded. The object is rotated through 180 degrees and the recorded hits are printed.

In the second section, the clipping plane is rotated by the same set of modelview matrices as the object in the first section. Note the use of vgl_DrawFunXfmPush and vgl_DrawFunXfmPop to isolate the modelview matrix to affect the clipping plane position and not the graphics object position.

#include "base/base.h"
#include "vgl/vgl.h"

static void
draw_scene(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n);

                   /* light properties */ 
static Vfloat camb[3] = {
   .5,.5,.5 };
static Vfloat cdis[3] = {
   .5,.5,.5 };
static Vfloat xdis[3] = {
    1.,0.,0. };

                   /* points */ 
static Vfloat xpts[7][3] = {
    {0.,0.,0.},
    {1.,0.,0.},
    {0.,1.,0.},
    {0.,0.,1.},
    {-1.,0.,0.},
    {0.,-1.,0.},
    {0.,0.,-1.} };
    
/*----------------------------------------------------------------------
                      Using Clipping Planes
----------------------------------------------------------------------*/
int
main()
{
   int i, j;
   Vfloat tm4[4][4];
   Vfloat eqn[4];
   Vint numhits;
   Vint indexlist[8];
   Vfloat mindepth[8], maxdepth[8];
   Vint dev;
   Vchar devname[256];
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev *ogldev;
#ifdef VKI_WIND_X11
   vgl_X11Dev    *x11dev;
#else
   vgl_GDIDev      *gdidev;
#endif
   vgl_Quadric *qu;
   vgl_DrawFun *df;
   vgl_Xfm     *xfm;

                   /* 1 = OpenGLDev, 2 = GDIDev or X11Dev */
   dev = 1;
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df  = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
      strcpy(devname,"OpenGL");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,df);
      strcpy(devname,"X11");
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,df);
      strcpy(devname,"GDI");
#endif
   }
                   /* open window */
   vgl_DrawFunPositionWindow (df,400,400,400,300);
   vgl_DrawFunOpenWindow (df,devname);

                   /* set viewing volume to match window aspect ratio */
   vgl_DrawFunProjOrtho (df,-2.6667,2.6667,-2.,2.,-2.,2.);

                   /* turn on zbuffering */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* generate quadric for drawing cone */
   qu = vgl_QuadricBegin ();
   vgl_QuadricSetObject (qu,VGL_DRAWFUN,df);

                   /* create transform object */ 
   xfm = vgl_XfmBegin();

                   /* set lights */ 
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);

                   /* define clipping plane at x = -.5 */ 
   eqn[0] = 1.;
   eqn[1] = 0.;
   eqn[2] = 0.;
   eqn[3] = .5;
   vgl_DrawFunClipPlane (df,0,eqn);
   vgl_DrawFunSetSwitch (df,VGL_CLIPPLANE,0,VGL_ON);

   vgl_DrawFunXfmPush (df);
                   /* rotate model about y axis */
   for(i = 0; i <= 25; i++) {
      vgl_DrawFunClear (df);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (df,tm4);
                   /* render */ 
      draw_scene (df,qu,.6,.8,17);
      vgl_DrawFunSwap (df);
                   /* set select */ 
      vgl_DrawFunSelectBuffer (df,8,indexlist,mindepth,maxdepth);
      vgl_DrawFunRender (df,VGL_SELECT);
      vgl_DrawFunSelectRegion (df,VGL_REGION_CLIPPLANE,NULL);
      draw_scene (df,qu,.6,.8,17);
                   /* reset render */ 
      vgl_DrawFunRender (df,VGL_RENDER);
      vgl_DrawFunSelectQuery (df,&numhits);
                   /* print hits */ 
      printf("rotate model: hits=");
      for(j = 0; j < numhits; j++) {
         printf(" %d",indexlist[j]);
      }
      printf("\n");
      vgl_DrawFunDelay (df,1.);
   }
   vgl_DrawFunXfmPop (df);
   vgl_DrawFunDelay (df,5.);

                   /* rotate clipping plane about y axis */
   for(i = 0; i <= 25; i++) {
      vgl_DrawFunClear (df);
      vgl_DrawFunXfmPush (df);
      vgl_XfmRotate (xfm,(Vfloat)(3.14159/25.*i),XFM_YAXIS);
      vgl_XfmGetMatrix (xfm,tm4);
      vgl_DrawFunXfmLoad (df,tm4);
      vgl_DrawFunClipPlane (df,0,eqn);
      vgl_DrawFunXfmPop (df);
                   /* render */
      draw_scene (df,qu,.6,.8,17);
      vgl_DrawFunSwap (df);
                   /* set select */ 
      vgl_DrawFunSelectBuffer (df,8,indexlist,mindepth,maxdepth);
      vgl_DrawFunRender (df,VGL_SELECT);
      vgl_DrawFunSelectRegion (df,VGL_REGION_CLIPPLANE,NULL);
      draw_scene (df,qu,.6,.8,17);
                   /* reset render */
      vgl_DrawFunRender (df,VGL_RENDER);
      vgl_DrawFunSelectQuery (df,&numhits);
                   /* print hits */ 
      printf("rotate plane: hits=");
      for(j = 0; j < numhits; j++) {
         printf(" %d",indexlist[j]);
      }
      printf("\n");
      vgl_DrawFunDelay (df,1.);
   }
   vgl_DrawFunDelay (df,5.);

                   /* free transform object */ 
   vgl_XfmEnd (xfm);

                   /* close window */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */
   if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   }
   vgl_DrawFunEnd (df);
   vgl_QuadricEnd (qu);

                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }
                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

/*----------------------------------------------------------------------
                      draw cone and points
----------------------------------------------------------------------*/
static void
draw_scene(vgl_DrawFun *df, vgl_Quadric *qu, Vfloat r, Vfloat h, Vint n)
{
   Vint i;
   Vfloat c[3];
   Vint index;
   Vchar stg[9];
                   /* draw gray cone, index 0 */ 
   c[0] = .5; c[1] = .5; c[2] = .5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunSpecularity (df,.5,10.);
   vgl_DrawFunDataIndex (df,0,0,NULL);
   vgl_QuadricSetParami (qu,QUADRIC_SLICES,n);
   vgl_QuadricSetParami (qu,QUADRIC_STACKS,2);
   vgl_QuadricCylinder (qu,r,0.,h);

                   /* draw 7 red points, indices 1 to 7 */ 
   c[0] = 1.0; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPointSize (df,2);
   for(i = 0; i < 7; i++) {
      index = i+1;
      vgl_DrawFunDataIndex (df,1,1,&index);
      vgl_DrawFunPolyPoint (df,1,(Vfloat(*)[3])xpts[i]);
      sprintf(stg,"%d",index);
      vgl_DrawFunText (df,xpts[i],stg);
   }
}

Table of Contents

13.41 Example 16, Write External JT Open File Using DFile

This example illustrates using DFile to write a complete JT Open file. JT Open files consist of an assembly which in turn contain any number of parts. JT parts contain the point, line and polygon graphics primitives and their attributes. The DFile object is set to write JT Open files by calling vgl_DFileSetFileType with argument DFILE_JT. Specify the assembly name using vgl_DFileSetJTAssemblyName. The final JT Open file written is named AssemblyName.jt and placed in the directory specified by vgl_DFileSetFileName. A JT part is opened for drawing by calling vgl_DFileOpenJTPart. If the JT part object is set to NULL, then a JT part is generated internally and opened for drawing. The user may optionally instance a JT part and pass it as an argument. In this case the user part will be opened for drawing. See Example 16a for an example of creating user defined parts. A part must be closed using vgl_DFileCloseJTPart when drawing to it is completed. Two parts are generated in this example, both are internally generated parts. Flat shaded faces of a hexahedron are drawn to the first part. Points and vertex colored lines are drawn to the second part.

#include <stdio.h>
#include <stdlib.h>
#include "vgl/vgl.h"

                   /* face connectivity of unit cube */ 
static Vint faces[6][4] = {
   {3,2,1,0},{4,5,6,7},{0,1,5,4},{2,3,7,6},{3,0,4,7},{1,2,6,5} };

                   /* vertices coordinates of unit cube */ 
static Vfloat coords[8][3] = {
   {0.,0.,0.},{1.,0.,0.},{1.,1.,0.},{0.,1.,0.},
   {0.,0.,1.},{1.,0.,1.},{1.,1.,1.},{0.,1.,1.} };

                   /* face colors */ 
static Vfloat frgb[6][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},{1.,0.,1.},{0.,1.,1.} };

                   /* edge connectivity */ 
static Vint edges[12][2] = {
   {0,1},{1,2},{2,3},{3,0},
   {4,5},{5,6},{6,7},{7,4},
   {0,4},{1,5},{2,6},{3,7} };

                   /* vertex colors for edge drawing */ 
static Vfloat vrgb[8][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},
   {1.,0.,1.},{0.,1.,1.},{.5,.5,.5},{1.,1.,1.} };

                   /* face normals */ 
static Vfloat normals[6][3] = {
   {0.,0.,-1.},{0.,0.,1.},{0.,-1.,0.},{0.,1.,0.},{-1.,0.,0.},{1.,0.,0.} };

/*----------------------------------------------------------------------
                      Write External JT Open File Using DFile
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   Vint i, j, n;
   vgl_DFile *dfile;
   vgl_DrawFun *df;
   Vfloat xp[4][3], cp[2][3], c[3];
   Vchar outputroot[256];

                   /* specify assembly name */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s outputroot\n",argv[0]);
      fprintf(stderr," outputroot is blank, 'Assembly' is assumed\n");
      strcpy(outputroot,"Assembly");
   } else {
      strcpy(outputroot,argv[1]);
   }

                   /* instance vgl objects */
   dfile = vgl_DFileBegin ();
   df    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfile,df);

                   /* specify jt file format, name, path */
   vgl_DFileSetFileType (dfile,DFILE_JT);
   if(vgl_DFileError(dfile)) {
      fprintf(stderr,"JT file format not supported\n");
      return 0;
   }
   vgl_DFileSetJTAssemblyName (dfile,outputroot);
   vgl_DFileSetFileName (dfile,"./");
                   /* open JT */
   vgl_DFileOpen (dfile);

                   /* draw faces of a hex into internal part, Part_1 */
   vgl_DFileOpenJTPart (dfile,NULL);
   for(n = 0; n < 6; n++) {
      vgl_DrawFunColor (df,frgb[n]);
      for(i = 0; i < 4; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[faces[n][i]][j];
         }
      }
      vgl_DrawFunPolygon(df,VGL_POLYGON,4,xp,VGL_FLATSHADE,(Vfloat*)normals[n]);
   }
   vgl_DFileCloseJTPart (dfile);

                   /* draw vertices and face edges into internal part, Part_2 */
   vgl_DFileOpenJTPart (dfile,NULL);
                   /* draw vertices of a hex in white */
   c[0] = 1.;
   c[1] = 1.;
   c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyPoint (df,8,coords);

                   /* draw face edges of a hex */
   for(n = 0; n < 12; n++) {
      for(i = 0; i < 2; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[edges[n][i]][j];
            cp[i][j] = vrgb[edges[n][i]][j];
         }
      }
      vgl_DrawFunPolyLineColor (df,VGL_LINESTRIP,2,xp,cp);
   }
   vgl_DFileCloseJTPart (dfile);

                   /* this is actually when JT file is written */ 
   vgl_DFileClose (dfile);

                   /* delete objects */ 
   vgl_DrawFunEnd (df);
   vgl_DFileEnd (dfile);
   return 0;
}

Table of Contents

13.42 Example 16a, Fill JT Open Part Using DFile

This example illustrates using DFile to fill a JT Open Part. The example contains the required JT Open calls to write a JT Open file where DFile is only used to fill a user defined part. The DFile object is set to fill JT Open parts only by calling vgl_DFileSetFileType with argument DFILE_JTPART. The same graphics primitives as in Example 16 are drawn into two user defined parts. Since a file is not written by DFile, function calls to vgl_DFileSetFileName, vgl_DFileSetJTAssemblyName, vgl_DFileOpen and vgl_DFileClose should not be made.

#include <stdio.h>
#include <stdlib.h>
#include <JtTk/JtkEntityFactory.h>
#include <JtTk/JtkHierarchy.h>
#include <JtTk/JtkAttrib.h>
#include <JtTk/JtkCADExporter.h>
#include "vgl/vgl.h"

                   /* face connectivity of unit cube */ 
static Vint faces[6][4] = {
   {3,2,1,0},{4,5,6,7},{0,1,5,4},{2,3,7,6},{1,2,6,5},{3,0,4,7} };

                   /* vertices coordinates of unit cube */ 
static Vfloat coords[8][3] = {
   {0.,0.,0.},{1.,0.,0.},{1.,1.,0.},{0.,1.,0.},
   {0.,0.,1.},{1.,0.,1.},{1.,1.,1.},{0.,1.,1.} };

                   /* face colors */ 
static Vfloat frgb[6][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},{1.,0.,1.},{0.,1.,1.} };

                   /* edge connectivity */ 
static Vint edges[12][2] = {
   {0,1},{1,2},{2,3},{3,0},
   {4,5},{5,6},{6,7},{7,4},
   {0,4},{1,5},{2,6},{3,7} };

                   /* vertex colors for edge drawing */ 
static Vfloat vrgb[8][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},
   {1.,0.,1.},{0.,1.,1.},{.5,.5,.5},{1.,1.,1.} };

                   /* face normals */ 
static Vfloat normals[6][3] = {
   {0.,0.,-1.},{0.,0.,1.},{0.,-1.,0.},{0.,1.,0.},{-1.,0.,0.},{1.,0.,0.} };

/*----------------------------------------------------------------------
                      Fill JT Open Part Using DFile
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   JtkAssembly    *assembly;
   JtkPart        *part;
   JtkCADExporter *cadexporter;
   Vint        i, j, n;
   vgl_DFile   *dfile;
   vgl_DrawFun *df;
   Vfloat      xp[4][3], cp[2][3], c[3];
   Vchar       outputroot[256];

                   /* Initialize Jtk */
   JtkEntityFactory::init();

                   /* Create an assembly */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s outputroot\n",argv[0]);
      fprintf(stderr," outputroot is blank, 'Assembly' is assumed\n");
      strcpy(outputroot,"Assembly");
   } else {
      strcpy(outputroot,argv[1]);
   }

   assembly = JtkEntityFactory::createAssembly(outputroot);
   if(assembly == NULL) {
      printf("Unable to create JtkAssembly node\n");
      return 0;
   }
   assembly->ref();

                   /* instance vgl objects */
   dfile = vgl_DFileBegin ();
   df    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfile,df);

                   /* specify jt part only */
   vgl_DFileSetFileType (dfile,DFILE_JTPART);

                   /* Create a part for face polygons */
   part = JtkEntityFactory::createPart("Part1");
   if(part == NULL) {
      printf("Unable to create JtkPart node\n");
      return 0;
   }
   assembly->addChild(part);

                   /* open JtkPart */ 
   vgl_DFileOpenJTPart (dfile,(Vobject*)part);

                   /* draw faces of a hex */
   for(n = 0; n < 6; n++) {
      vgl_DrawFunColor (df,frgb[n]);
      for(i = 0; i < 4; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[faces[n][i]][j];
         }
      }
      vgl_DrawFunPolygon (df,VGL_POLYGON,4,xp,VGL_FLATSHADE,(Vfloat*)normals);
   }
                   /* close JtkPart */ 
   vgl_DFileCloseJTPart (dfile);

                   /* Create a part for vertices and face edges */
   part = JtkEntityFactory::createPart("Part2");
   if(part == NULL) {
      printf("Unable to create JtkPart node\n");
      return 0;
   }
   assembly->addChild(part);

                   /* open JtkPart */
   vgl_DFileOpenJTPart (dfile,(Vobject*)part);

                   /* draw vertices of a hex in white */
   c[0] = 1.;
   c[1] = 1.;
   c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyPoint (df,8,coords);

                   /* draw face edges of a hex */
   for(n = 0; n < 12; n++) {
      for(i = 0; i < 2; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[edges[n][i]][j];
            cp[i][j] = vrgb[edges[n][i]][j];
         }
      }
      vgl_DrawFunPolyLineColor (df,VGL_LINESTRIP,2,xp,cp);
   }
                   /* close JtkPart */
   vgl_DFileCloseJTPart (dfile);

                   /* export data */
   cadexporter = JtkEntityFactory::createCADExporter();
   if(cadexporter == NULL) {
      printf("Unable to create JtkCADExporter\n");
      return 0;
   }
   cadexporter->ref();
   cadexporter->setExportPath("./");
                   /* recommended by JT Open personnel to disable
                      tristripping and LOD generation */ 
   cadexporter->setFileFormat(JtkCADExporter::JtkMONOLITHIC);
   cadexporter->setExportOption(JtkCADExporter::JtkAUTO_LOW_LODS_OFF);
   cadexporter->setExportOption(JtkCADExporter::JtkSMART_LODS_OFF);
   cadexporter->setExportOption(JtkCADExporter::JtkPART_SIMPLIFY_OFF);
   cadexporter->setExportOption(JtkCADExporter::JtkRETRISTRIP_OFF);
   cadexporter->setExportOption(JtkCADExporter::JtkJT_VERSION_80);

   cadexporter->export(assembly);

                   /* clean up */
   assembly->unref();
   cadexporter->unref();
   vgl_DrawFunEnd (df);
   vgl_DFileEnd (dfile);
   JtkEntityFactory::fini();
   return 0;
}

Table of Contents

13.43 Example 16b, Read External JT Open File Using DFile

This example illustrates using DFile to read a JT Open file and write the contents to an STL file.

#include <stdio.h>
#include <stdlib.h>
#include "vgl/vgl.h"

/*----------------------------------------------------------------------
                      Read External JT Open File Using DFile
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   vgl_DFile *dfiler, *dfilew;
   vgl_DrawFun *dfr, *dfw;
   Vchar outputroot[256];

                   /* specify assembly name */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s outputroot\n",argv[0]);
      fprintf(stderr," outputroot is blank, 'Assembly' is assumed\n");
      strcpy(outputroot,"Assembly");
   } else {
      strcpy(outputroot,argv[1]);
   }

                   /* instance JT reader objects */
   dfiler = vgl_DFileBegin ();
   dfr    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfiler,dfr);

                   /* specify JT file format, name, path */
   vgl_DFileSetFileType (dfiler,DFILE_JT);
   vgl_DFileSetJTAssemblyName (dfiler,outputroot);
   vgl_DFileSetFileName (dfiler,"./");

                   /* instance STL writer objects */ 
   dfilew = vgl_DFileBegin ();
   dfw    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfilew,dfw);
   vgl_DFileSetFileType (dfilew,DFILE_STL_ASCII);
   vgl_DFileSetFileName (dfilew,"examjt.stl");

                   /* Output STL file must be opened first */ 
   vgl_DFileOpen (dfilew);

                   /* Read JT file and output to STL file */ 
   vgl_DFileSetObject (dfiler,VGL_DRAWFUN,dfw);
   vgl_DFileOpen (dfiler);
   vgl_DFileRead (dfiler);
   vgl_DFileClose (dfiler);

                   /* Output STL file must be closed last */ 
   vgl_DFileClose (dfilew);

                   /* clean up */
   vgl_DFileEnd (dfiler);
   vgl_DFileEnd (dfilew);
   vgl_DrawFunEnd (dfr);
   vgl_DrawFunEnd (dfw);
   return 0;
}

Table of Contents

13.44 Example 16d, Write VglTools Native ASCII File Using DFile

This example illustrates using DFile to write two "frames" to a native VglTools ASCII file. The DFile object is set to write native ASCII files by calling vgl_DFileSetFileType with argument DFILE_ASCII. Set the full file name of the generated file using vgl_DFileSetFileName. The function vgl_DFileOpen opens the specified file and will begin to write all subsequent graphics primitives, representing the first frame, to the file. The function vgl_DFileClose writes a terminating token and closes the file. The second "frame" is appended to the file by querying the current file position and then setting it using vgl_DFileSetPosition prior to opening the file. vgl_DFileOpen is called to begin writing the second frame. vgl_DFileClose is called when all graphics primitives have been issued. The Example 16e illustrates reading the two frame written in this example.

#include <stdio.h>
#include <stdlib.h>
#include "vgl/vgl.h"

                   /* face connectivity of unit cube */ 
static Vint faces[6][4] = {
   {3,2,1,0},{4,5,6,7},{0,1,5,4},{2,3,7,6},{3,0,4,7},{1,2,6,5} };

                   /* vertices coordinates of unit cube */ 
static Vfloat coords[8][3] = {
   {0.,0.,0.},{1.,0.,0.},{1.,1.,0.},{0.,1.,0.},
   {0.,0.,1.},{1.,0.,1.},{1.,1.,1.},{0.,1.,1.} };

                   /* face colors */ 
static Vfloat frgb[6][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},{1.,0.,1.},{0.,1.,1.} };

                   /* edge connectivity */ 
static Vint edges[12][2] = {
   {0,1},{1,2},{2,3},{3,0},
   {4,5},{5,6},{6,7},{7,4},
   {0,4},{1,5},{2,6},{3,7} };

                   /* vertex colors for edge drawing */ 
static Vfloat vrgb[8][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},
   {1.,0.,1.},{0.,1.,1.},{.5,.5,.5},{1.,1.,1.} };

                   /* face normals */ 
static Vfloat normals[6][3] = {
   {0.,0.,-1.},{0.,0.,1.},{0.,-1.,0.},{0.,1.,0.},{-1.,0.,0.},{1.,0.,0.} };

/*----------------------------------------------------------------------
                      Write VglTools Native ASCII File Using DFile
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   Vint i, j, n;
   vgl_DFile *dfile;
   vgl_DrawFun *df;
   Vfloat xp[4][3], cp[2][3], c[3];
   Vchar filename[256];
   long pos;
                   /* specify file name */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s filename\n",argv[0]);
      fprintf(stderr," filename is blank, 'exam16d.asc' is assumed\n");
      strcpy(filename,"exam16d.asc");
   } else {
      strcpy(filename,argv[1]);
   }
                   /* instance vgl objects */
   dfile = vgl_DFileBegin ();
   df    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfile,df);

                   /* specify file format, name, path */
   vgl_DFileSetFileType (dfile,DFILE_ASCII);
   vgl_DFileSetFileName (dfile,filename);
                   /* open to draw 1st frame */
   vgl_DFileOpen (dfile);

                   /* draw text */ 
   vgl_DrawFunText (df,coords[0],"Frame 1");

                   /* draw faces of a hex */
   for(n = 0; n < 6; n++) {
      vgl_DrawFunColor (df,frgb[n]);
      for(i = 0; i < 4; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[faces[n][i]][j];
         }
      }
      vgl_DrawFunPolygon(df,VGL_POLYGON,4,xp,VGL_FLATSHADE,(Vfloat*)normals[n]);
   }

                   /* draw vertices and face edges */
                   /* draw vertices of a hex in white */
   c[0] = 1.;
   c[1] = 1.;
   c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyPoint (df,8,coords);

                   /* draw face edges of a hex */
   for(n = 0; n < 12; n++) {
      for(i = 0; i < 2; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[edges[n][i]][j];
            cp[i][j] = vrgb[edges[n][i]][j];
         }
      }
      vgl_DrawFunPolyLineColor (df,VGL_LINESTRIP,2,xp,cp);
   }
   vgl_DFileClose (dfile);
                   /* query position to start writing 2nd frame */ 
   vgl_DFileCurPosition (dfile,&pos);

                   /* set position to start writing 2nd frame */ 
   vgl_DFileSetPosition (dfile,pos);
                   /* open to draw 2nd frame */
   vgl_DFileOpen (dfile);
   vgl_DrawFunColor (df,c);
   vgl_DrawFunText (df,coords[0],"Frame 2");
   vgl_DFileClose (dfile);

                   /* delete objects */ 
   vgl_DrawFunEnd (df);
   vgl_DFileEnd (dfile);
   return 0;
}

Table of Contents

13.45 Example 16e, Read VglTools Native File and Print

This example illustrates using DFile to read the two "frames" written to a native VglTools ASCII file in the previous example. A drawing function object is instanced and set to print graphics primitives. Set the full file name of the generated file using vgl_DFileSetFileName. Query for the file type using vgl_DFileReadFileType, then set the queried file type using vgl_DFileSetFileType.

The function vgl_DFileRead begins reading from the beginning of the file until it reads the token terminating the first frame. This token is written in the previous example by the vgl_DFileClose function. All graphics primitives read are issued to the drawing function object which has been registered with the DFile object using vgl_DFileSetObject.

The second frame is read by querying for the current file position using vgl_DFileCurPosition and setting it using vgl_DFileSetPosition prior to calling vgl_DFileRead.

#include <stdio.h>
#include <stdlib.h>
#include "vgl/vgl.h"

/*----------------------------------------------------------------------
                      Read Native DFile and Print
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   vgl_DFile *dfile;
   vgl_DrawFun *df;
   Vchar filename[256];
   Vint filetype;
   long pos;
                   /* specify filename */
   if(argc < 2) {
      fprintf(stderr,"Usage: %s filename\n",argv[0]);
      fprintf(stderr," filename is blank, 'exam16d.asc' is assumed\n");
      strcpy(filename,"exam16d.asc");
   } else {
      strcpy(filename,argv[1]);
   }

                   /* instance reader objects */
   dfile = vgl_DFileBegin ();
   df    = vgl_DrawFunBegin ();
   vgl_DFileSetObject (dfile,VGL_DRAWFUN,df);
   vgl_DrawFunAPI (df,DRAWFUN_APIPRINT);

                   /* set file name */
   vgl_DFileSetFileName (dfile,filename);
                   /* query and set file format */
   vgl_DFileReadFileType (dfile,&filetype);
   vgl_DFileSetFileType (dfile,filetype);

                   /* Read and print 1st frame */ 
   vgl_DFileRead (dfile);
                   /* Query position to start reading 2nd frame */
   vgl_DFileCurPosition (dfile,&pos);
                                                                                
                   /* Set position to start reading 2nd frame */
   vgl_DFileSetPosition (dfile,pos);
                   /* Read and print 2nd frame */
   vgl_DFileRead (dfile);

                   /* clean up */
   vgl_DFileEnd (dfile);
   vgl_DrawFunEnd (df);
   return 0;
}

Table of Contents

13.46 Example 16f, Write All ASCII File Types Using DFile

This example illustrates using DFile to write to all supported ASCII file types. A set of graphics primitives are first written to a DList object. The DFile object is instanced and successively set to each of the ASCII file types supported by DFile. Note that a single DFile object may be used. The file type and file name must be specified using vgl_DFileSetFileType and vgl_DFileSetFileName respectively.

#include <stdio.h>
#include <stdlib.h>
#include "vgl/vgl.h"

                   /* face connectivity of unit cube */ 
static Vint faces[6][4] = {
   {3,2,1,0},{4,5,6,7},{0,1,5,4},{2,3,7,6},{3,0,4,7},{1,2,6,5} };

                   /* vertices coordinates of unit cube */ 
static Vfloat coords[8][3] = {
   {0.,0.,0.},{1.,0.,0.},{1.,1.,0.},{0.,1.,0.},
   {0.,0.,1.},{1.,0.,1.},{1.,1.,1.},{0.,1.,1.} };

                   /* face colors */ 
static Vfloat frgb[6][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},{1.,0.,1.},{0.,1.,1.} };

                   /* edge connectivity */ 
static Vint edges[12][2] = {
   {0,1},{1,2},{2,3},{3,0},
   {4,5},{5,6},{6,7},{7,4},
   {0,4},{1,5},{2,6},{3,7} };

                   /* vertex colors for edge drawing */ 
static Vfloat vrgb[8][3] = {
   {1.,0.,0.},{0.,1.,0.},{0.,0.,1.},{1.,1.,0.},
   {1.,0.,1.},{0.,1.,1.},{.5,.5,.5},{1.,1.,1.} };

                   /* face normals */ 
static Vfloat normals[6][3] = {
   {0.,0.,-1.},{0.,0.,1.},{0.,-1.,0.},{0.,1.,0.},{-1.,0.,0.},{1.,0.,0.} };

/*----------------------------------------------------------------------
                      Write All ASCII File Types Using DFile
----------------------------------------------------------------------*/
int
main(int argc, char** argv) 
{
   Vint i, j, n;
   vgl_DList *dlist;
   vgl_DFile *dfile;
   vgl_DrawFun *dl, *df;
   Vfloat xp[4][3], cp[2][3], c[3];

                   /* instance vgl objects */
   dfile = vgl_DFileBegin ();
   df    = vgl_DrawFunBegin ();
   vgl_DFileDrawFun (dfile,df);
   dlist = vgl_DListBegin ();
   dl    = vgl_DrawFunBegin ();
   vgl_DListDrawFun (dlist,dl);
                   /* set DFile as output of DList */ 
   vgl_DListSetObject (dlist,VGL_DRAWFUN,df);

                   /* fill display list */
                   /* draw text */ 
   vgl_DrawFunText (dl,coords[0],"Frame 1");

                   /* draw faces of a hex */
   for(n = 0; n < 6; n++) {
      vgl_DrawFunColor (dl,frgb[n]);
      for(i = 0; i < 4; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[faces[n][i]][j];
         }
      }
      vgl_DrawFunPolygon(dl,VGL_POLYGON,4,xp,VGL_FLATSHADE,(Vfloat*)normals[n]);
   }
                   /* draw vertices and face edges */
                   /* draw vertices of a hex in white */
   c[0] = 1.;
   c[1] = 1.;
   c[2] = 1.;
   vgl_DrawFunColor (dl,c);
   vgl_DrawFunPolyPoint (dl,8,coords);

                   /* draw face edges of a hex */
   for(n = 0; n < 12; n++) {
      for(i = 0; i < 2; ++i) {
         for(j = 0; j < 3; ++j) {
            xp[i][j] = coords[edges[n][i]][j];
            cp[i][j] = vrgb[edges[n][i]][j];
         }
      }
      vgl_DrawFunPolyLineColor (dl,VGL_LINESTRIP,2,xp,cp);
   }
                   /* specify Native ascii file type */
   vgl_DFileSetFileType (dfile,DFILE_ASCII);
   vgl_DFileSetFileName (dfile,"exam16f.asc");
                   /* draw DList to DFile */
   vgl_DFileOpen (dfile);
   vgl_DListCall (dlist);
   vgl_DFileClose (dfile);

                   /* X3D file type */
   vgl_DFileSetFileType (dfile,DFILE_X3D);
   vgl_DFileSetFileName (dfile,"exam16f.x3d");
   vgl_DFileOpen (dfile);
   vgl_DListCall (dlist);
   vgl_DFileClose (dfile);

                   /* DAE file type */
   vgl_DFileSetFileType (dfile,DFILE_DAE);
   vgl_DFileSetFileName (dfile,"exam16f.dae");
   vgl_DFileOpen (dfile);
   vgl_DListCall (dlist);
   vgl_DFileClose (dfile);

                   /* VRML file type */
   vgl_DFileSetFileType (dfile,DFILE_VRML);
   vgl_DFileSetFileName (dfile,"exam16f.wrl");
   vgl_DFileOpen (dfile);
   vgl_DListCall (dlist);
   vgl_DFileClose (dfile);

                   /* OBJ file type */
   vgl_DFileSetFileType (dfile,DFILE_OBJ);
   vgl_DFileSetFileName (dfile,"exam16f.obj");
   vgl_DFileOpen (dfile);
   vgl_DListCall (dlist);
   vgl_DFileClose (dfile);

                   /* delete objects */ 
   vgl_DrawFunEnd (df);
   vgl_DrawFunEnd (dl);
   vgl_DListEnd (dlist);
   vgl_DFileEnd (dfile);
   return 0;
}

Table of Contents

13.47 Example 17, Draw Polygon with Hole using Stencil Buffer

This example illustrates using the stencil buffer to draw a rectangular white polygon with a triangular hole. This example is written to illustrate rendering using OpenGL and window system graphics functions X11 and GDI and software rendering using the RendBuf module. The stencil buffer is not allocated by default so it must be specifically requested using vgl_DrawFunVisualWindow before opening the window. All stencil buffer parameters are set using vgl_DrawFunSetMode. First the stencil test is enabled and cleared to all zeroes. The hole is "drawn" first with the goal of rendering 1's in the stencil buffer. The stencil test is set to always fail so that nothing is drawn in the color buffer. Then the rectangular polygon is drawn with the stencil function set to pass only when the stencil buffer is not equal to 1. In this way the holes are eliminated when drawing the polygon.

#include "base/base.h"
#include "vgl/vgl.h"

static Vfloat xq[4][3] = {
   {-.75,-.75,0.}, { .75,-.75,0.}, { .75, .75,0.}, {-.75, .75,0.} };
static Vfloat xt[3][3] = {
   {0.,0.,0.}, {.5,0.,0.}, {.5,.5,0.} };
  
/*----------------------------------------------------------------------
                      Draw Polygon with Hole using Stencil Buffer
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
   Vint dev;
   Vchar devname[256];
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#else
   HFONT hfont;
#endif

   vgl_OpenGLDev *ogldev;
   vgl_RendBuf *rendbuf;
   vgl_FBuffer *fbuffer;
#ifdef VKI_WIND_X11
   vgl_X11Dev    *x11dev;
#else
   vgl_GDIDev      *gdidev;
#endif
   vgl_DrawFun *df;
                   /* 0 = RendBuf, 1 = OpenGLDev, 2 = GDIDev or X11Dev */
   dev = 1;
                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   if(dev == 1) {
      vgl_OpenGLDevConnectX (display,screen);
   } else if(dev == 2) {
      vgl_X11DevConnectX (display,screen);
   }
#else
   if(dev == 1) {
      vgl_OpenGLDevConnectWIN ();
   } else if(dev == 2) {
      vgl_GDIDevConnectWIN ();
   }
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   if(dev == 0) {
      rendbuf = vgl_RendBufBegin();
      vgl_RendBufDrawFun (rendbuf,df);
      strcpy(devname,"RendBuf");
   } else if(dev == 1) {
      ogldev = vgl_OpenGLDevBegin();
      vgl_OpenGLDevDrawFun (ogldev,df);
      strcpy(devname,"OpenGL");
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      x11dev = vgl_X11DevBegin();
      vgl_X11DevDrawFun (x11dev,df);
      strcpy(devname,"X11");
#else
      gdidev = vgl_GDIDevBegin();
      vgl_GDIDevDrawFun (gdidev,df);
      strcpy(devname,"GDI");
#endif
   }
                   /* request a stencil buffer */ 
   vgl_DrawFunVisualWindow (df,VGL_VISUAL_STENCIL);
                   /* open windows */
   vgl_DrawFunPositionWindow (df,200,300,300,225);
   vgl_DrawFunOpenWindow (df,devname);
   vgl_DrawFunProjOrtho (df,-1.3333,1.3333,-1.,1.,-1.,1.);

   vgl_DrawFunSetMode (df,VGL_STENCILMODE,VGL_ON);
                   /* draw white square with triangular hole */
                   /* stencil cleared to 0 */
   vgl_DrawFunClear (df);
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
                   /* draw triangular hole, setting stencil to 1 */ 
   vgl_DrawFunSetMode (df,VGL_STENCILFUNCMODE,VGL_NEVER);
   vgl_DrawFunSetMode (df,VGL_STENCILFUNCREF,1);
   vgl_DrawFunSetMode (df,VGL_STENCILOPFAIL,VGL_OP_REPLACE);
   vgl_DrawFunPolygon (df,VGL_POLYGON,3,xt,VGL_NOSHADE,NULL);
                   /* draw enclosing quad, stencil value is not equal to 1 */ 
   vgl_DrawFunSetMode (df,VGL_STENCILFUNCMODE,VGL_NOTEQUAL);
   vgl_DrawFunSetMode (df,VGL_STENCILFUNCREF,1);
   vgl_DrawFunSetMode (df,VGL_STENCILOPFAIL,VGL_OP_KEEP);
   vgl_DrawFunPolygon (df,VGL_POLYGON,4,xq,VGL_NOSHADE,NULL);

   vgl_DrawFunSwap (df);
                   /* write out image if RendBuf used */
   if(dev == 0) {
      fbuffer = vgl_FBufferBegin ();
      vgl_DrawFunFBufferRead (df,0,0,0,0,fbuffer);
      vgl_FBufferWriteGIF (fbuffer,"exam17.gif");
      vgl_FBufferEnd (fbuffer);
   }
                   /* wait */
   vgl_DrawFunDelay (df,10.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   if(dev == 0) {
      vgl_RendBufEnd (rendbuf);
   } else if(dev == 1) {
      vgl_OpenGLDevEnd (ogldev);
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevEnd (x11dev);
#else
      vgl_GDIDevEnd (gdidev);
#endif
   }
   vgl_DrawFunEnd (df);

                   /* disconnect */
   if(dev == 1) {
      vgl_OpenGLDevDisconnect ();
   } else if(dev == 2) {
#ifdef VKI_WIND_X11
      vgl_X11DevDisconnect ();
#else
      vgl_GDIDevDisconnect ();
#endif
   }

                   /* clean up */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#else
   DeleteObject (hfont);
#endif
   return 0;
}

Table of Contents

13.48 Example 19, Transparency with Depth Peeling

This example illustrates using depth peeling to render transparent surfaces accurately. This feature is a multipass rendering method and as such requires that the transparent geometry be rendered multiple times (peels). Up to 4 peels may be performed. The more peels, the more accurate the transparency rendering. Opaque geometry only needs to be rendered once. This feature requires activating shaders. This must be done using vgl_DrawFunSetMode with the VGL_SHADERMODE mode enabled. The peeling process is controlled by vgl_DrawFunSetMode using the VGL_DEPTHPEELMODE. The peel mode should be disabled while drawing opaque objects. Then each peel is numbered 1,2,..,VGL_DEPTHPEELLAST. The last peel must be explicitly indicated as such. It is advised to disable depth peel mode after the last peel.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* triangle data */ 
static Vfloat xtris1[3][3] = {
   {-.5, -.6, 0.5}, { .3,-.6,0.5}, {-.1,  .4, 0.5} };
static Vfloat ttris1[3] = {
   0.,0.,1. };
static Vfloat xtris2[3][3] = {
   {-.3, -.7, 0.}, { .5,-.7,0.}, { .1, .3, 0.} };
static Vfloat xtris3[3][3] = {
   {-.1, -.5, 1.}, { .7,-.5,1.}, { .3, .6, 1.} };
static Vfloat xtris[3][3] = {
   {-.1, -.3, .75}, { .1,-.3,.75}, { .0, -.1, .75} };
                   /* text location */ 
static Vfloat xtext[3] = {-.9,.9,0.};

static void
draw_scene(vgl_DrawFun *df)
{
   Vfloat c[3];

   vgl_DrawFunTrans (df,.5);
                   /* white base color textured middle */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunTextureSelect (df,1);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris1,VGL_1DTEXTURE,(Vfloat*)ttris1);
   vgl_DrawFunTextureSelect (df,0);
                   /* blue farthest */ 
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris2,VGL_NOSHADE,NULL);
                   /* red nearest */ 
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris3,VGL_NOSHADE,NULL);
   return;
}

/*----------------------------------------------------------------------
                      Transparency with Depth Peeling
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
   Vint flag, peelpass, peelpix, peeltol;
   vgl_Texture *texture;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
                   /* default projection limits are bi-unit cube */ 
                   /* test for shader support */
   vgl_DrawFunGetInteger (df,VGL_SHADER_SUPPORTED,&flag);
   if(flag == 0)  goto labelcleanup;

                   /* define texture */
   texture = vgl_TextureBegin ();
                   /* built-in is index 1 */
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_TextureSetEnv (texture,TEXTURE_MODULATE);
   vgl_DrawFunTextureDefine (df,1,texture);
                   /* free texture object */
   vgl_TextureEnd (texture);

                   /* turn on shader mode */
   vgl_DrawFunSetMode (df,VGL_SHADERMODE,VGL_ON);
                   /* turn on blending */
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_ON);
                   /* white background */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunBackColor (df,c);
   vgl_DrawFunClear (df);
                   /* draw opaque objects first for optimization,
                      not necessary for correct rendering however */ 
                   /* opaque yellow just behiind red */ 
   vgl_DrawFunTrans (df,0.);
   c[0] = 1.; c[1] = 1.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris,VGL_NOSHADE,NULL);

                   /* set pixel threshold */ 
   peeltol = 20000;
   peeltol = 0;
                   /* depth peel loop */
   for(peelpass = 1; peelpass < 10; peelpass++) {
      vgl_DrawFunSetMode (df,VGL_DEPTHPEELMODE,peelpass);
      draw_scene (df);
      vgl_DrawFunGetInteger (df,VGL_DEPTHPEEL_PIXELS,&peelpix);
      printf("peelpass= %d, peelpix= %d\n",peelpass,peelpix);
      if(peelpix <= peeltol)  break;
   }
                   /* last pass */
   if(peelpix != 0) {
      vgl_DrawFunSetMode (df,VGL_DEPTHPEELMODE,VGL_DEPTHPEELLAST);
      draw_scene (df);
   }
                   /* turn depth peel off to write any annotation */ 
   vgl_DrawFunSetMode (df,VGL_DEPTHPEELMODE,0);
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunSetMode (df,VGL_BLENDTRANSMODE,VGL_OFF);
   vgl_DrawFunTrans (df,0.);
   vgl_DrawFunColor (df,c);
   vgl_DrawFunText (df,xtext,"Depth Peeling");

                   /* swap buffers */
   vgl_DrawFunSwap (df);

                   /* wait 10 seconds */
   vgl_DrawFunDelay (df,10.);

                   /* cleanup */ 
labelcleanup:;
                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.49 Example 20, Drawing Scalar Icons at Points

This example illustrates generating shader assisted icons at points. These features are currently available only in the vgl_DrawFunPolyPointArray and vgl_DrawFunPolyPointBuffer functions. A point icon style is selected using vgl_DrawFunPointStyle. Options include dot (the default), circle, sphere, various bitmaps and unsigned integers. The individual sphere and circle icons can be sized by providing scalar values as data for each point. Use the function vgl_DrawFunSetMode with mode type VGL_DATASIZEMODE to enable data sizing. The point icon size depends upon the type and a set of parameters which include the current integer device size set using vgl_DrawFunPointSize, a world coordinate size set using vgl_DrawFunSetFactors with type VGL_WORLDSIZE and per point data entered as vertex data to the vgl_DrawFunPolyPointArray and vgl_DrawFunPolyPointBuffer functions.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* point data */ 
static Vfloat xpoint[4][3] = {
   {-.5, .5, 0.}, {.5, .5, 0.},
   {-.5,-.5, 0.}, {-.4,-.4, 0.} };
                   /* colors */ 
static Vfloat cpoint[4][3] = {
   {1., 0., 0.}, {0., 0., 1.},
   {0., 1., 0.}, {1., 0., 1.} };
                   /* device size */ 
static Vfloat dpoint[4] = {
   1., 2., 3., 4.};
                   /* world size */ 
static Vfloat wpoint[4] = {
   .1, .2, .3, .4};
                   /* numbers */ 
static Vuint idpoint[4] = {
   101, 123456, 1234567890, 7091946};

static Vfloat xtext[3] = {-.7,.78,0.};
static Vfloat ctext[3] = {1.,1.,1.};

                   /* light properties */
static Vfloat camb[3] = {
   .3,.3,.3 };
static Vfloat cdis[3] = {
   .7,.7,.7 };
static Vfloat xdis[3] = {
    1.,0.,0. };

/*----------------------------------------------------------------------
                      Drawing Scalar Icons at Points
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;
   Vfloat fac;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif

                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif

                   /* set lights */
   vgl_DrawFunLight (df,0,VGL_LIGHT_AMBIENT,camb,NULL);
   vgl_DrawFunLight (df,1,VGL_LIGHT_DISTANT,cdis,xdis);
   vgl_DrawFunSetMode (df,VGL_LIGHTMODE,VGL_ON);
                   /* default projection limits are bi-unit cube */ 
                   /* turn on zbuffer mode */
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
                   /* turn on shader mode */
   vgl_DrawFunSetMode (df,VGL_SHADERMODE,VGL_ON);

                   /* draw four points as dot (pixel) icons, point size of 8 */ 
                   /* data size is ignored */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"DOT, size 8");
   vgl_DrawFunPointSize (df,8);
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_DOT);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,dpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* draw four points as sphere icons */ 
                   /* data size is ignored */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"SPHERE, size 16");
   vgl_DrawFunPointSize (df,16);
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_SPHERE);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,dpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* draw four points as sphere icons */ 
                   /* data size enabled */
   vgl_DrawFunSetMode (df,VGL_DATASIZEMODE,VGL_ON);
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"SPHERE, data sized");
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,dpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* draw four points as sphere world icons */
                   /* data size enabled */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"SPHEREWORLD, data sized");
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_SPHEREWORLD);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,wpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* double their size */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"SPHEREWORLD, doubled data sized");
   fac = 2.;
   vgl_DrawFunSetFactors (df,VGL_WORLDSIZE,&fac);
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_SPHEREWORLD);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,wpoint);
   fac = 1.;
   vgl_DrawFunSetFactors (df,VGL_WORLDSIZE,&fac);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

                   /* data size disabled */
   vgl_DrawFunSetMode (df,VGL_DATASIZEMODE,VGL_OFF);

                   /* draw four points as bitmaps */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"Bitmaps, constant 9x9");
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_PLUS9);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,0,NULL);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,2.);

   vgl_DrawFunPointSize (df,2);
                   /* draw four numbers */
   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"UINT, center");
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_DOT);
   vgl_DrawFunPolyPointArray (df,4,xpoint,0,NULL,0,NULL,0,NULL,0,NULL);
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_UINT);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,(Vfloat*)idpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,4.);

   vgl_DrawFunClear (df);
   vgl_DrawFunColor (df,ctext);
   vgl_DrawFunText (df,xtext,"UINT, lower left");
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_DOT);
   vgl_DrawFunPolyPointArray (df,4,xpoint,0,NULL,0,NULL,0,NULL,0,NULL);
   vgl_DrawFunPointStyle (df,VGL_POINTSTYLE_UINTLL);
   vgl_DrawFunPolyPointArray (df,4,xpoint,VGL_COLOR_3F,cpoint,
                              0,NULL,0,NULL,1,(Vfloat*)idpoint);
   vgl_DrawFunSwap (df);
   vgl_DrawFunDelay (df,4.);

                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Table of Contents

13.50 Example 21, Order Independent Transparency

This example illustrates using single-pass, order independent transparency, (OIT), to render transparent surfaces accurately. This feature requires activating shaders. This must be done using vgl_DrawFunSetMode with the VGL_SHADERMODE mode enabled. In addition, OIT must be enabled and disabled before vgl_DrawFunClear and after vgl_DrawFunSwap respectively. Z-buffering can be reliably turned off before and after rendering any z-buffered transparent objects. This is illustrated in this example by drawing non z-buffered "Background Text" and "Foreground Text" strings.

The OIT algorithm requires caching all generated transparent fragments in graphics memory and then compositing them with opaque pixels when vgl_DrawFunSwap is called. This memory is a limited resource and may not be sufficient for complex, multi-layered models on a large screen. The memory required in bytes is approximately 12 times the average transparent layer complexity per pixel times the number of screen pixels. This memory data structure is preallocated before rendering occurs. The average number of layers used for allocation is a value set using vgl_DrawFunSetMode with parameter VGL_OITAVERAGELAYERS. The user can query this value using vgl_DrawFunGetMode. The OIT rendering may fail if sufficient memory is not available. It may be incomplete if the number of fragments generated exceeds the allocated fragment memory. The user may query for these conditions before swap so that a problem rendering may be detected before swapping. Use vgl_DrawFunGetInteger with parameter VGL_OIT_MEMORYFAIL to query for memory failure. The user can also query for the fragment counters using vgl_DrawFunGetInteger with parameter VGL_OIT_COUNTERS. Two values are returned, the maximum number of fragments that can currently be stored and the number of fragments generated by the current rendering. If the number of fragments generated exceeds the maximum, the rendering will be incomplete. The user at this point can compute a new proportionately larger average layer value, set it using vgl_DrawFunSetMode and retry the rendering.

#include "base/base.h"
#include "vgl/vgl.h"

                   /* triangle data */ 
static Vfloat xtris1[3][3] = {
   {-.5, -.6, 0.5}, { .3,-.6,0.5}, {-.1,  .4, 0.5} };
static Vfloat ttris1[3] = {
   0.,0.,1. };
static Vfloat xtris2[3][3] = {
   {-.3, -.7, 0.}, { .5,-.7,0.}, { .1, .3, 0.} };
static Vfloat xtris3[3][3] = {
   {-.1, -.5, 1.}, { .7,-.5,1.}, { .3, .6, 1.} };
static Vfloat xtris[3][3] = {
   {-.1, -.3, .75}, { .1,-.3,.75}, { .0, -.1, .75} };
                   /* text location */ 
static Vfloat xfore[3] = {0.,0.1,0.};
static Vfloat xback[3] =  {0.,-.15,0.};
static Vfloat xplan[3] = {-.6,-.6,0.};
                   /* title box location */ 
static Vfloat xtbox[4][3] = {
   {-.75, .7, 0.}, { .75,.7,0.},
   { .75, .9, 0.}, {-.75,.9,0.}};
static Vfloat xtext[3] = {-.7,.78,0.};

static void
draw_scene(vgl_DrawFun *df)
{
   Vfloat c[3];
   Vfloat path[3], plane[3];
                   /* 50 percent transparent */ 
   vgl_DrawFunTrans (df,.5);
                   /* red nearest */ 
   c[0] = 1.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris3,VGL_NOSHADE,NULL);
                   /* white base color textured middle */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunTextureSelect (df,1);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris1,VGL_1DTEXTURE,(Vfloat*)ttris1);
   vgl_DrawFunTextureSelect (df,0);
                   /* blue farthest */ 
   c[0] = 0.; c[1] = 0.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris2,VGL_NOSHADE,NULL);
                   /* opaque text parallel to triangle edge */ 
   vgl_DrawFunTrans (df,0.);
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunRasFontSelect (df,1);
   path[0] = .4;
   path[1] = 1.;
   path[2] = 0.;
   plane[0] = -1.;
   plane[1] = 0.;
   plane[2] = 0.;
   vgl_DrawFunTextPlane (df,path,plane);
   vgl_DrawFunText (df,xplan,"Parallel to Triangle Edge");
   vgl_DrawFunRasFontSelect (df,0);

   return;
}

/*----------------------------------------------------------------------
                      Order Independent Transparency
----------------------------------------------------------------------*/
int
main()
{
   Vfloat c[3];
   Vint dc[3];
   Vint flag, oitcounters[2];
   vgl_Texture *texture;
   vgl_RasFont *rasfont;

#ifdef VKI_WIND_X11
   Display *display;
   int screen;
#endif

   vgl_OpenGLDev  *opengldev;
   vgl_DrawFun *df;

                   /* connect to X or Windows */
#ifdef VKI_WIND_X11
   display = XOpenDisplay (0);
   screen = DefaultScreen (display);
   vgl_OpenGLDevConnectX (display,screen);
#else
   vgl_OpenGLDevConnectWIN ();
#endif
                   /* create drawing functions */
   df = vgl_DrawFunBegin();

                   /* create device objects and load drawing functions */
   opengldev = vgl_OpenGLDevBegin();
   vgl_OpenGLDevDrawFun (opengldev,df);

                   /* open window */
   vgl_DrawFunPositionWindow (df,200,200,400,400);
#ifdef VKI_WIND_X11
   vgl_DrawFunOpenWindow (df,"X Windows");
#else
   vgl_DrawFunOpenWindow (df,"Microsoft Windows");
#endif
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);
                   /* default projection limits are bi-unit cube */ 
                   /* test for OIT support */
   vgl_DrawFunGetInteger (df,VGL_OIT_SUPPORTED,&flag);
   if(flag == 0) {
      printf("OIT not supported\n");
      goto labelcleanup;
   }
                   /* define texture, built-in is index 1 */
   texture = vgl_TextureBegin ();
   vgl_TextureLoad (texture,TEXTURE_HUE_BANDED);
   vgl_TextureSetEnv (texture,TEXTURE_MODULATE);
   vgl_DrawFunTextureDefine (df,1,texture);
   vgl_TextureEnd (texture);

                   /* define rasfont, textplane is index 1 */ 
   rasfont = vgl_RasFontBegin();
   vgl_RasFontLoad (rasfont,RASFONT_QUALITY9X13);
   vgl_RasFontSetParami (rasfont,RASFONT_TEXTPLANE,SYS_ON);
   vgl_RasFontSetParami (rasfont,RASFONT_DEVICESIZE,SYS_ON);
   vgl_DrawFunRasFontDefine (df,1,rasfont);
   vgl_RasFontEnd (rasfont);

                   /* turn on shader and OIT mode */
   vgl_DrawFunSetMode (df,VGL_SHADERMODE,VGL_ON);
   vgl_DrawFunSetMode (df,VGL_OITMODE,VGL_ON);
                   /* white background */ 
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunBackColor (df,c);
   vgl_DrawFunClear (df);
                   /* draw background text string */ 
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);
   vgl_DrawFunTrans (df,0.);
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunText (df,xback,"Background Text");
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* draw opaque objects first for potential optimization,
                      not necessary for correct rendering however */ 
                   /* opaque yellow just behiind red */ 
   vgl_DrawFunTrans (df,0.);
   c[0] = 1.; c[1] = 1.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_TRIANGLES,3,xtris,VGL_NOSHADE,NULL);

                   /* draw transparent triangles and textplane text */ 
   draw_scene (df);

   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_OFF);
                   /* draw opaque title */ 
   vgl_DrawFunTrans (df,0.);
   c[0] = 0.5; c[1] = 0.5; c[2] = 0.5;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolygon (df,VGL_QUADS,4,xtbox,VGL_NOSHADE,NULL);
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunPolyLine (df,VGL_LINELOOP,4,xtbox);
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   dc[0] = 1;
   dc[1] = 1;
   dc[2] = 0;
   vgl_DrawFunTextDC (df,xtext,dc,"Order Independent Transparency");
   c[0] = 1.; c[1] = 1.; c[2] = 1.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunText (df,xtext,"Order Independent Transparency");

                   /* draw foreground text string */ 
   c[0] = 0.; c[1] = 0.; c[2] = 0.;
   vgl_DrawFunColor (df,c);
   vgl_DrawFunText (df,xfore,"Foreground Text");
   vgl_DrawFunSetMode (df,VGL_ZBUFFERMODE,VGL_ON);

                   /* check for various failures */ 
   vgl_DrawFunGetInteger (df,VGL_OIT_COUNTERS,oitcounters);
   printf("maxnode= %d\n",oitcounters[0]);
   printf("numnode= %d\n",oitcounters[1]);
   if(oitcounters[1] > oitcounters[0]) {
      printf("counter overflow\n");
   }
   vgl_DrawFunGetInteger (df,VGL_OIT_MEMORYFAIL,&flag);
   if(flag) {
      printf("GPU memory allocation failure\n");
   }
                   /* swap buffers */
   vgl_DrawFunSwap (df);
   vgl_DrawFunGetInteger (df,VGL_DEV_ERROR,&flag);
   if(flag) {
      printf("Device error= %d\n",flag);
   }
   vgl_DrawFunSetMode (df,VGL_OITMODE,VGL_OFF);

                   /* wait 5 seconds */
   vgl_DrawFunDelay (df,5.);

                   /* cleanup */ 
labelcleanup:;
                   /* close windows */ 
   vgl_DrawFunCloseWindow (df);

                   /* free objects */ 
   vgl_OpenGLDevEnd (opengldev);
   vgl_DrawFunEnd (df);

                   /* disconnect from X or Windows */
   vgl_OpenGLDevDisconnect ();

                   /* close X display */
#ifdef VKI_WIND_X11
   XCloseDisplay (display);
#endif
   return 0;
}

Figure 21-1, Generated Image