Graphics.NewbieCubeDrawingWithOpenGL - lordmundi/wikidoctest GitHub Wiki

Newbie Cube Drawing with Open GL

« Texture Cube | NewbieIndex | NewbieCubeOverlays »

Goal
Using pure opengl calls, we'll draw a cube on the fly.

| Skeleton C-File for "Open GL Cube" Plugin: | || | #include "doug.h" #include "dsp_double.h"

static DSS_DOUBLE_DATA *pdouble = NULL;

void
DSP_UpdateCube()
{
        DSF_ExecuteCore();
        DSF_BgnSceneAccess( DSV_scene, DSD_READ_ACCESS );
                DSF_PushDrawingState();

                        //  Open GL Code

                DSF_PopDrawingState();
        DSF_EndSceneAccess();
}

DSP_InitializePlugin( DSS_PLUGIN *plugin )
{
        // Code to Verify Double Precision Used

        DSF_InstallPluginFunction( plugin->handle, DSP_UpdateCube,
                                    DSD_PLUGIN_DRAW_SCENE );

        return  1;
} |

| * * *

  • DSP_UpdateCube() is registered with DSF_InstallPluginFunction()
  • The Open GL Code is placed in the "DSP_UpdateCube()" function
  • In the full code below, notice that the "DSP_UpdateCube()" function calls another function called "DrawCube()" which contains more Open GL Code |

For example, here is a more complete set of code including the call to a function which draws the cube in openGL:

#include "doug.h"
#include "dsp_double.h"

static DSS_DOUBLE_DATA *pdouble = NULL;

static const GLdouble coordinateCorrection[16] = {0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0};

void DrawCube( float X, float Y, float Z )
{
	glScalef( X, Y, Z );
	glBegin(GL_QUADS);

	// face 1
	glNormal3f(0,0,1);
	glColor3f(1,1,1);
	glVertex3f(1,1,1);
	glColor3f(1,1,0);
	glVertex3f(-1,1,1);
	glColor3f(1,0,0);
	glVertex3f(-1,-1,1);
	glColor3f(1,0,1);
	glVertex3f(1,-1,1);

	// face 2
	glNormal3f(1,0,0);
	glColor3f(1,1,1);
	glVertex3f(1,1,1);
	glColor3f(1,0,1);
	glVertex3f(1,-1,1);
	glColor3f(0,0,1);
	glVertex3f(1,-1,-1);
	glColor3f(0,1,1);
	glVertex3f(1,1,-1);

	// face 3
	glNormal3f(0,1,0);
	glColor3f(1,1,1);
	glVertex3f(1,1,1);
	glColor3f(0,1,1);
	glVertex3f(1,1,-1);
	glColor3f(0,1,0);
	glVertex3f(-1,1,-1);
	glColor3f(1,1,0);
	glVertex3f(-1,1,1);

	// face  4
	glNormal3f(-1,0,0);
	glColor3f(1,1,0);
	glVertex3f(-1,1,1);
	glColor3f(0,1,0);
	glVertex3f(-1,1,-1);
	glColor3f(0,0,0);
	glVertex3f(-1,-1,-1);
	glColor3f(1,0,0);
	glVertex3f(-1,-1,1);

	// face 5
	glNormal3f(0,-1,0);
	glColor3f(0,0,0);
	glVertex3f(-1,-1,-1);
	glColor3f(0,0,1);
	glVertex3f(1,-1,-1);
	glColor3f(1,0,1);
	glVertex3f(1,-1,1);
	glColor3f(1,0,0);
	glVertex3f(-1,-1,1);

	// face 6
	glNormal3f(0,0,-1);
	glColor3f(0,0,1);
	glVertex3f(1,-1,-1);
	glColor3f(0,0,0);
	glVertex3f(-1,-1,-1);
	glColor3f(0,1,0);
	glVertex3f(-1,1,-1);
	glColor3f(0,1,1);
	glVertex3f(1,1,-1);

	glEnd();
}

void DSP_UpdateCube()
{
	DSF_ExecuteCore();
	DSF_BgnSceneAccess( DSV_scene, DSD_READ_ACCESS );
		DSF_PushDrawingState();

			// Start Open GL
			glDisable( GL_LIGHTING );
			glDisable( GL_TEXTURE_2D );
			glMatrixMode( GL_MODELVIEW );
			/*
			By loading the modelview matrix we retrieved we are essentially asking doug where we are in the world,
			rather than ignoring doug with glLoadIdentity.
			*/
			//glLoadMatrixd( pdouble->DSV_modelview_matrix[0] );
			//glMultMatrixd( coordinateCorrection ); //DOUG and OpenGL use different default coordinate reference frames 
			glLoadIdentity();
			glTranslatef( 0, 0, -20);
			glRotatef( 25, 1, 1, 0 );
			DrawCube( 3, 3, 3 );  //Call function DrawCube which contains more Open GL
			// End Open GL

		DSF_PopDrawingState();
	DSF_EndSceneAccess();
}


DSP_InitializePlugin( DSS_PLUGIN *plugin )
{
	// Verify Double Precision is Used
	pdouble = DSF_GetDataFromScene( DSV_scene, "DSS_DOUBLE_DATA" );
	if (!pdouble) {
		char msg[300];
		sprintf( msg, "\nWorking in single precision mode. Restart with double argument in command line: ./run_graphics -double\n");
		DSF_LogWarning( msg );
		return 0;
	}

	DSF_InstallPluginFunction( plugin->handle, DSP_UpdateCube,
                                    DSD_PLUGIN_DRAW_SCENE );

	return  1;
}

| Make the "Open GL Cube" Plugin: | || | To Build:

% cp [dsp_open_gl_cube.c][4] ${DOUG_HOME}/src/plugins
  % cd ${DOUG_HOME}/src/plugins
  % make ; # this will create a dsp_open_gl_cube.so |

| Modify Config File: | || | CUBE { plugins { cube dsp_open_gl_cube }

                channel1
                {

                      view.MAIN   NewbieCam perspective(...)...
                }
        }

To Run:
  % cd ${DOUG_HOME}/userdata
  % vi user.cfg; # Add plugin line as seen above (cube dsp_open_gl_cube)
  % cd ${DOUG_HOME}
  % ./run_graphics |

You should see your Open GL Cube in DOUG

You may have an object blocking your cube

For example - The Cube-Vangogh Cube Model:

In the DOUG Toolbar go to Edit → Nodes → Cameras

Select your camera and change your camera's position

Notice that our Open GL Cube moves with the camera.

To place the cube in a position relative to other nodes in the scene,

Uncomment the "glLoadMatrixd . . ." line and the "glMultMatrixd . . ." line. Finally comment out "glLoadIdentity()" in the c code:

"dsp_open_gl_cube.c"

// Start Open GL
			glDisable( GL_LIGHTING );
			glDisable( GL_TEXTURE_2D );
			glMatrixMode( GL_MODELVIEW );
			/*
			By loading the modelview matrix we retrieved we are essentially asking doug where we are in the world,
			rather than ignoring doug with glLoadIdentity.
			*/
			glLoadMatrixd( pdouble->DSV_modelview_matrix[0] );
			glMultMatrixd( coordinateCorrection ); //DOUG and OpenGL use different default coordinate reference frames 
			//glLoadIdentity();
			glTranslatef( 0, 0, -20);
			glRotatef( 25, 1, 1, 0 );
			DrawCube( 3, 3, 3 );  //Call function DrawCube which contains more Open GL
			// End Open GL

For now we're ignoring why we do this coordinate correction. It isn't necessary, but it makes things easier for the sake of the tutorial. For more detail: (soon to come)


Additional Plugin Hints and Tips

  • Plugin Naming

    • Historically, most plugins are named to be descriptive and use the format dsp_xxxx.c which compile to dsp_xxxx.so. Most plugins are in a single .c file but others are multiple files compiled into a single .so file.
  • Header files

    • Most header files you require should be in the src.dist/includes directory, but if something is missing, please let us know. The doug.h header should be used for any doug specific calls, which would include calls the involve DOUG's Tcl interface. dsp.h is used for lower level functionality. doug.h automatically includes dsp.h, so including it removes the need to also include dsp.h
  • Important functions

    • The DSP_InitializePlugin call is important in that it is the main function called when your plugin is loaded. It is mandatory. Similarly, the DSP_CleanupPlugin and DSP_ExitPlugin are called when a plugin is unloaded or when DOUG exits respectively. These are not mandatory.

    • In most cases, the DSP_InitializePlugin function of a plugin will call DSP_InstallPluginFunction at least once to install a callback in doug for a function in the plugin. For example, you may want to draw with openGL in the background of the scene, so you might have DSF_InstallPluginFunction( 0, MyDrawBackground, DSD_PLUGIN_DRAW_BACKGROUND ); in your code to tell DOUG to call your MyDrawBackground function every time it is in the DRAW_BACKGROUND pass of rendering. There are many different types of flags you can pass, which are specified here. Some of this can be confusing, but the main thing to remember is that the DRAW calls are mainly for elements which need to draw something in the scene/foreground/background and are all called if it is determined that something in the scene has moved! The UPDATE_SCENE flag is one which is called every frame no matter what and is typically for plugins which plan on moving nodes in the scene. Once DOUG sees that a node has moved (scene updated), the draw calls will fire. The most common callbacks are the DRAW_SCENE and UPDATE_SCENE callbacks.

    • In your function, if you need to either read or write to the scene (i.e., nodes), then you should use the DSF_BgnSceneAccess and DSF_EndSceneAccess calls. These provide semaphore protection in case DOUG is running in a shared memory context to keep other processes from reading in corrupted data. DOUG rarely runs this way anymore so most people will ignore these calls. _HOWEVER_, there is a similar call called "DSF_BgnModifyScene" and "DSF_EndModifyScene" which are very important any time you want to update nodes. These functions will trigger DOUG to know that the scene has been updated and for all of the DRAW calls to fire. Keep in mind this is if you are modifying nodes, not drawing your own geometry.

    • Your callback function will likely want to have "DSF_ExecuteCore();" somewhere near the top which will cause the rest of the plugin stack to execute such that you have a fresh state to draw on top of.

    • Be sure to checkout Graphics.DougPluginFunctionReference and Graphics.DOUGPluginAPIReference as they contain references to these functions.

« Texture Cube | NewbieIndex | NewbieCubeOverlays »