How to use and extend the modeler
The modeler project includes one executable file (modeler.exe), one loadable library for modeler primitives (modeler.dll) and the loadable library that defines the model itself (myModel.dll, or whatever). The executable and the library are provided, along with a few sample models. You build your own model in .dll format and invoke modeler.exe to view and manipulate it.The executable must be able to find the modeler library when it starts. The NT skeleton project always copies modeler.dll to the Debug folder when the modeler library is rebuilt. On Linux, you should rebuild libmodeler.so in the modeler directory (make), then add the directory containing libmodeler.so into the environment variable LD_LIBRARY_PATH using setenv. Also, the Linux executable needs to have the access permissions set to allow you to execute it: chmod ugo+x animator.
You must have the FLTK include and library files available. The lab machines now all have FLTK installed in D:\app\fltk-1.0.9, so that is where the sample projects point to. If you have set up your own machine, you can get the basic files or the full fltk distribution.
Setting up a new model project
After unzipping the skeleton code, you will get six subdirectories: Debug, LibModeler, MdlClassarm, MdlCylinder, MdlRobotarm, and MdlSphere. Debug contains the executable modeler.exe and the modeler.dll. Together they implement the framework for this project. The sources for the modeler library are included in the LibModeler directory in case you want to extend the set of primitives. The last four subdirectories contain the sample model projects. The sources for classarm, cylinder, robotarm, and sphere are included for your information. The project settings and basic structure of the code are a good beginning point for your own model.An easy way to build a new project is to copy the robotarm folder and start modifying that. This way all the project settings are established for you.
To start from scratch, do the following.
- In MSVC, select File > New.... Click the Projects tab and select "Win32 Dynamic-Link Library". Give your project a name in the Project name: entry box, for example, "sphere". Click OK, then Finish, then OK to create an empty DLL project.
- Use your favorite text editor to create the model source file - for example "sphere.cpp". Enter the following outline:
The argument to the MODEL macro on the third line will the name of your model. Remember to put this macro at the beginning of your file.#include ?modelerdll.h> #define SPHERE_RADIUS 1 MODEL("sphere"); bool init(void *args) { scale( SPHERE_RADIUS, "radius", 0.1f, 3.0f, 0.01f, 1.0f ); return true; } void redraw(int drawmode) { glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0, 0.0, -15.0 ); ambient_color( 0.0, 0.0, 0.2 ); diffuse_color( 0.0, 0.3, 0.8 ); sphere( get_control_d( SPHERE_RADIUS ) ); }
- Save the file. In MSVC, add the file to the project by selecting Project > Add To Project > Files....
- Now configure the project. Choose Project > Settings... to bring up the configuration dialog.
- At the upper left there is a dropdown labeled Settings For:. Select "All configurations."
- Under the General tab, set "Intermediate files" to c:\temp
- Under the C/C++ tab, select the "Preprocessor" category. In the "Additional include directories" box, enter:
The sample projects initially set this to: d:\app\fltk-1.0.9,..\LibModeler"<where to find fltk>", "<where to find modelerdll.h>"
- Under the Link tab, select the "General" category. In the "Object/library modules:" box, add (don't delete what's already there!) the following:
Select the "Input" category. In the "Additional Library Path" box, entermodeler.lib fltkd.lib wsock32.lib opengl32.lib glu32.libThe sample projects initially set this to d:\app\fltk-1.0.9\lib,..\Debug"<where to find fltk library>", "<where to find modeler.lib>"In the "Ignore Libraries" box, add 'libcmt'.
- Click OK.
- You can set the project settings so that when you select run application, it runs modeler.exe and loads your model automatically. One way to do this is to choose Project>Settings>General, and set executable for debug session to ..\Debug\modeler.exe, and working directory to ..\Debug. Then choose the Post-build Step (way at the end of the options tabs) and copy your dll to the ..\Debug directory every time you rebuild it using a command like "copy Debug\sphere.dll ..\Debug\myModel.dll"
- Now you can build the project. You'll get a "Debug" subdirectory with your model DLL in it ("sphere.dll" in this example). If you start the modeler and load the model in, you'll see a blue sphere in the center.
- If you copy the model dll to the main Debug directory and name it myModel.dll, then when you double click modeler.exe it will be loaded automatically. You can also load the model "by hand" from within the program, or you can specify it on the command line as the second parameter following the name of the modeler library modeler.dll.
Creating a model
Your model consists of 2 C functions. Let's look at what the two functions do.bool init(void *args) gets called once, when your model is first loaded. It should return true if the initialization is successful. The args parameter is not used in our implementation and will be NULL. Note: you cannot do OpenGL initialization in this function. See the occasionally asked questions or the robotarm project code for a suggestion on how to do OpenGL initialization.
void redraw(int drawmode) is where the action is. It gets called every time the window needs to be redrawn. The context in which it is called is established by the calling routine CGLView::draw.
To draw something, you call one of primitive object functions provided in the modeler library:
We draw a sphere here.
- sphere( r )
- draws a sphere of radius r.
- box( x, y, z )
- draws a box with corners at (0,0,0) and (x,y,z).
- cylinder( h, r1, r2 )
- draws a cylinder with axis from the origin to (0,0,h). The radius at the origin is r1; the radius at z=h is r2. If r1 and r2 are different, you get a frustum. If r1 or r2 is zero, you get a cone.
- triangle( x1, y1, z1, x2, y2, z2, x3, y3, z3 )
- draws a triangle with vertices at the three given points.
Since the sphere is centered at the origin, which is exactly where the camera is. We use the following code fragment,
glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0, 0.0, -15.0 );to move the sphere so that we can see it. The default camera is looking down the -z axis, so translate the sphere in that direction.
![]()
We can set material properties with four other functions:
The code fragment
- ambient_color( r, g, b );
- diffuse_color( r, g, b );
- specular_color( r, g, b );
- shininess( s );
ambient_color( 0.0, 0.0, 0.2 ); diffuse_color( 0.0, 0.3, 0.8 );is used to set the material properties of the object. Now we get:
![]()
Adding interactive controls
The sample models have UI widgets that you can interact with to change the model. Now we'll see how to add those, allowing the user to vary the radius of the sphere in our simple example. Each control widget that you want must have a unique integer ID. To keep these straight, we recommend using #define'd constants. Sticksomewhere at the top of your file. Note that this doesn't mean the radius of the sphere is 1 unit, it means that control #1 is going to control the radius. We can use any number as the ID, as long as it is unique in the model.#define SPHERE_RADIUS 1init is where we create the widgets. The available commands to create widgets are listed below.
- scale( id, name, min, max, res, start )
- Create a slider widget. res is the resolution of the slider (the smallest amount you can move it). start is the initial value. name, as in all these calls, is a string that labels the widget.
- checkbox( id, name, start )
- Create a checkbox. start is the initial setting.
- menu( id, name, start, ... )
- Create a selection widget - either a set of radio buttons or a menu of choices. The "..." arguments are one or more strings, terminated with NULL - these are the available choices. They are numbered choice 0, 1, 2, and so on. start is the initial selection.
This will be used in project 4 when we do the animation. It creates a control variable in the curve editor which doesn't appear in the user interface.
Let's create a slider for the sphere. In init, we have the line:Now, in the model drawing function, we need to read the current value of the slider. Widget settings can be read with the get_control_* functions, where "*" is one of "d" (to read a double), "i" (to read an int), or "b" (to read a boolean). You pass the function the ID of the control whose value you want.scale( SPHERE_RADIUS, "radius", 0.1, 3.0, 0.01, 1.0 );In redraw, we use
for the purpose.sphere( get_control_d( SPHERE_RADIUS ) );Now when you load the model, there will be a slider added to the main window. Moving the slider will change the radius of the sphere: