SMLib Introduction



Let's first get an overview of where things reside. The downloaded 'Zip' files should all be unzipped into a Directory called 'SMLib' .Alldirectories and files will be relative to this top level directory.

Look for a 'Readme' text document for any important changes.

Source Code Directories

  • NMTLib - Contains all the'C++'  libraries for the 'IW_' routines
    Note: This is called GSNLib and TSNLib ( an edited subset) for those customers
  • src - Source code (.cpp) files
  • inc - Include (.h) files
  • prog_test - Directory for programmatic test
  • src - Source code (.cpp) files.
  • inc - Include (.h) files.
  • ui_test - Directory for user-interface test
  • src - Source code (.cpp) files.
  • inc - Include (.h) files.
  • NLib - Contains source code and header files for the 'C' routines.
  • src - Source code (.c) files.
  • inc - Include (.h) files.
  • U_globals.c - contains external definitions of global variables.
  • HWLib - (Optional) Contains Data Translators for IGES, STEP, VDAFS, and SAT
  • src - Source code (,cpp) files
  • inc - Include (.h) files

Project Directories

  • NMTLib
  • NMTLib.dsw and .dsp - Visual C++6.0  project to build NMTLib.dll and NMTlib.lib 
  • NMTLib.sln and .vproj  - Visual Studio 2005  project to build NMTLib.dll and NMTlib.lib 
  • sm_unix.tar -UNIX scripts and utilities
  • Debug - Directory for compiled(.obj) files.
  • prog_test
  • prog_test.dsw and .dsp - Visual C++ 6.0  project to build programmatic test program prog_test.exe
  • prog_test.sln and .vproj  - Visual Studio 2005  project to build prog_test.exe
  • ui_test_test
  • ui_test.dsw and .dsp - Visual C ++6.0   project to build interactive test program  ui_test.exe
  • ui_test.sln and .vproj  - Visual Studio 2005  project to build ui_test.exe
  • NLib
  • NLib.dsw  and .dsp- Visual C++6.0  project to build NLib.dll and NLib.lib
  • NLib.sln and .vproj - Visual Studio 2005  project to build NLib.dll and NLib.lib
  • N_unix.tar - UNIX scripts and utilities.
  • HWLibs (Optional)
  • hw_nmtlib_core.dsw/dsp & .sln/vproj   - Visual C++ project to build harmonyware translator
  • iges_nmtlib.dsw/dsp   & .sln/vproj  - Visual C++ project to build IGES translators
  • sat_nmtlib.dsw/dsp     & .sln/vproj - Visual C++ project to build SAT translators
  • vdafs_nmtlib.dsw/dsp & .sln/vproj  - Visual C++ project to build VDAFS translators
  • Winlibs- directory into which the *.dll, *.lib and *.exe files are put for all projects


  • SMLibManual - You will need to edit this link to /DocSMLib/contentsf.html for the SMLib Manual. If you do not have a browser that works with frames, edit this link to/DocSMLib/contents.html.
  • DocSMLib -   A directory containing a large number of '.html' files for the SMLib Manual. 
  • NLibManual - You will need to edit this link to /DocNLib/contentsf.html for the NLib Manual. If you do not have a browser that works with frames, edit this link to  /DocNLib/contents.html.
  • DocNLib - A directory containing a large number of '.html' files for the documentation
  • HWLibsDoc(Optional) - Directory containingHWLibs (.html) files. These are documented separately from SMLib and NLib documentation.

Test Data Directories

  • Fillet Tests- Test files (IGES and others)for fillets
  • igesfiles - Directory with test suite of IGES files used by programmatic test. 
  • drop - Directory with drop curve and lift curve test files . 
  • fillet - Directory with fillet data files
  • solids - Directory with IGES files for Boolean/Merge tests. 

Sample Code

  • Directory NLib/Examples - Some samples of NLib source code
  • Directory NMTLib/Examples - Examples of application programs that are stand-alone tests
  • Examples are also available under the SMLib Documentation
  • See also '.cpp' files in NMTLib/prog_test and ui_test directories

Build for Windows 98/NT/XP using Visual C++

If you are using Windows 98/NT/XP and have Visual C++ 4.0, 5.0 or 6.0 you can do the following to be quickly up and running: 

  • For every new release or update, we recommend that you first remove all files from Winlibs, so that only new dll's and libs are used. Failure to do this may result in co-mingling of old and new versions of the same routine.
  • Enter the NLib directory, and open the NLib.dsw project. Compile and link all files.
  • Enter the NMTLib directory, and open NMTLib.dsw .
  • In the project settings there are two candidates for removal/inclusion:IW_NOT_USING_OPENGL should be removed if you are running OpenGL on a PC using our ui_test, and IW_NO_HWLIBSshould be removed if you are Harmonyware translators.
  • There are some edits needed in iwos_config.h, If you ARE using any of the HarmonyWare translators you must comment out
  • #define IW_NO_HWLIBS_IGES 1
  • #define IW_NO_HWLIBS_VDAFS 1
  • #define IW_NO_HWLIBS_STEP 1
  • #define IW_NO_HWLIBS_SAT

for each of the libraries you are using.You should be careful to check each option in the iwos_config.h file, Other defines of interest are: IW_DEBUG_CODE, IW_GFX_CODE, IW_ISOCPP and IW_IOS.Compile and link NMTLib.

  • Enter the program test project using prog_test.dsw. Check that the settings are compatible with NMTLib. Compile and link prog_test. You can execute prog_test, which also includes some multi-threaded tests. The code should run to completion.There will be a few warnings about tolerances and face classification and a few errors messages from other places and only one "Boolean Failure". If you are not sure, send us the generated text and compare the results to the file LOG_of_prog_test.txt in the NMTLib directory.
  • Enter the UserTest project using ui_test.dsw. Check the settings for using OpenGL and the HW translators. Compile and link ui_test. You can execute the ui_test program, and make selections with the mouse from the interactive window.
  • If you are using the harmonyware translators you need to enter the HWLibs project using the (up to 6) .dsw projects. Compile and link (the link process references the NMTLib.lib in WinLibs).For compiling the ui_test project you will need to add the include (/I)to HwLibs include files (./HWLibs/inc). For linking, you will need to add the (up to)6 library files for hw_xxxx. libs in Winlibs.
  • You can nowstart development with NLib.dll and NMTLib.dll in the Winlibs directory. We suggest that you keep the libraries in "Debug" mode so that you will get any errors that occur printed out. Alternately you can use the callback feature in iwos_error.h and iwos_error.cpp to call a function that you supply when errors occur in NMTLib.dll.

If you port to unix, you will have to turn off the #define MSWINDOWS. After you have done testing and validation, you may want to turn off IW_DEBUG_CODE. You may turn off IW_GFX_CODE if you don't utilize our drawing facilities.If you are not using Visual C++ 6.0 or some other ISO C++ compiler you may need to add the comment before #define IW_ISOCPP. 

Build for Windows 98/NT/XP using Microsoft.Net

If you are using Windows 98/NT/XP and are using Microsoft Visual ".Net", there are 2 known problems when compared to the Visual C++ environment

  • In the program /ui_test/Cube.cpp in the routine "Run2(0,  after the "for (;;) {"add "MSG m_msgCur;"  This cast replaces missing a VisaulC++ cast.
  • Some users have had difficulty in getting the ui_test demo to draw correctly. This may be to do with the OpenGL treatment under .Net

Build for UNIX

If you are utilizing UNIX there are some make scripts in ./SMLib/NMTLib/unix directory for building the C++ code on SUN Solaris, HP and Linux that may be of some help. You will have to generate your own make files for NLib. There is no user interface for the test harness on UNIX. If you have any problems installing the software please contact us as soon as possible. Here are the approximate steps to follow on UNIX:

1. Compile and build NLib library in the NLib directory.

  • Comment out the "#define BUILDING_MS_DLL" in the beginning of "nurbs.h" because it is not needed in unix. 
  • In NLib create the unix directory by doing "tar -xvf N_unix.tar". 
  • You can try using the script "make_src_linux" in ./NLib/unix directory as a starting point. 
  • You can either link directly to the *.o files or you can build a library. 

2. Compile and build NMTLib in the NMTLib directory

  • In NMTLib create the unix directory by doing "tar -xvf SM_UNIX.TAR" 
  • In the unix directory convert all of the NMTLib files from DOS to UNIX format by running the script d2u_SMLib. This removes the ^M at the end of the lines in DOS. 
  • In the file iwos_config.h remove the #define MSWINDOWS by placing a // in front of it. 
  • Use or modify one of the make_src_* files to compile NMTLib. 

3. Use or modify one of the make_prog_test_* files to build the programmatic test.  

4. Run the programmatic tests and validate.

5.Customers have written their own 'make' files for their version of GCC or UNIX. They are given here as a suggestion, without    any assurance that they will work for your compiler:

cd ../src
find ../src -name '*.c' -print -exec ../unix/compile {} \;
cd ../unix
(This searches on .c instead of .cpp)
* The unix/compile file needs to be changed to:
gcc -ansi
-DHW_STD=std -w
-Wno-deprecated -I. -I../../NLib/inc
-I../inc -g -c $1
I am using
gcc (GCC) 3.3.1 (SuSE Linux)
for building the Linux shared library, and
i386-mingw32msvc-gcc (GCC) 3.2.3 (mingw special 20030504-1)
for building the Windows DLL (mingw32 is a cross-compiler toolkit
which runs on Linux but produces object files targeted for Windows --
this is very convenient since Linux is currently my main development
platform for GDL).
NMTLib (v6.0)
Here is the compile command-line I am using for Windows:
g++ -Wno-deprecated
 -I. -I../../NLib/inc -I../inc -O2 -c -o ../objects/windows/[file].o [file].c
And for Linux:
g++ -Wno-deprecated
-fPIC -I. -I../../NLib/inc -I../inc -O2 -c -o
../objects/windows/[file].o [file].c

> Interface to Graphics

The ui_test interface is currently an MFC single window application using simple graphics to display SMS geometry objects for demonstration and debugging purposes. The ui_test application and its approach to graphics management can be used as an example of how to write an NMTLib based geometry application but it is assumed most customers will want to pick and choose between using bits of this interface for their own and rewriting the rest.

Display Architecture

The ui_test program is a Microsoft MFC windows application using state-based graphics, that is, the user interface is used to specify a set of graphic state bits and values which control the graphics displayed in the output window. The Windows message system framework converts user I/O actions into calls to the methods of the CSMLibView class defined in file ui_test/cubeview.h. Most of the CSMLibView class methods are simple wrapper functions that pass their calls on to an IwView object whose methods do the actual work.

The subset of CSMLibView and IwView methods that control the ui_test graphics make iwgfx_SetCalls() declared in file iwgfx_extern.h to set the global view and drawing parameters. The global viewing and drawing parameters are stored together within two static global objects called s_Disp and s_View of type IwDisplayParameters and IwViewParameters respectively.

Display and view parameters are stored in the following classes:

  • IwDisplayParameters Draw Bits, Parameters, and Colors
  • IwViewParameters Display Draw State and View Orientation
  • IwView Window Size, View Orientation, and Transformation, Pick Object Data, Window handle, and Cursor Operation Type.
  • ViewData View Orientation for Orientation save/restore.

The ui_test 3D graphics are output using the OpenGL DisplayList mechanism. All 3D graphics to be displayed are first compiled into an OpenGL DisplayList and added to a global array of display lists stored in s_View::m_ pActiveLists. All the stored display lists are drawn to the output window with a call to iwgfx_DrawLists(). The iwgfx_DrawLists() function is called either directly or by the IwView::DrawScene() method which clears the OpenGL color and depth buffers, applies the s_View::m_aViewMatrix to the current (ModelView) matrix stack, outputs the display lists stored in s_View::m_pActiveLists with a call to iwgfx_DrawLists(), restores the matrix stack, and swap buffers.

DisplayLists are created and added to the global DisplayList array by Draw() methods implemented for various members of the NMTLib IwObject class hierarchy. The structures of these Draw methods are all supposed to be the same. First they create and add a DisplayList to the global DisplayList array with a call to iwgfx_Open(), followed by a sequence of draw commands designed to display the object which all get compiled into the open DisplayList, and ended with a call to iwgfx_Close() which ends the construction of the DisplayList.

The iwgfx_Open()/iwgfx_Close() commands concatenate nested calls. That is a 2nd call to iwgfx_Open() made before calling iwgfx_Close() does not create a new nested DisplayList but rather continues using the currently open DisplayList and increments a counter. Each iwgfx_Close() call decrements the counter until the matching iwgfx_Close() call is made for the initial iwgfx_Open() call at which time the Display list completed and closed. This property is important in limiting the total number of display lists generated by objects like faces which draw edges and points as part of their own display.

For objects with simple graphics, the draw commands are contained within the Draw() functions otherwise the draw commands for objects with more complicated graphics are isolated in methods called OutputGraphics(). The basic draw commands include the following:

  • iwgfx_DrawPoint(),
  • iwgfx_DrawLine(),
  • iwgfx_DrawPolyLine(),
  • iwgfx_DrawTriangle(), and for drawing meshes
  • iwgfx_NewNurbsRenderer(),
  • iwgfx_NurbsSurface(), and
  • iwgfx_NurbsCurve().

The Draw() and OutputGraphics() methods use the s_Disp IwDisplayParameters object values as needed to control the graphics that they add to the open DisplayList.

The ui_test implementations of these draw command functions make OpenGL calls, however other rendering engines can be used to display the ui_test graphics by rewriting these functions for the desired display engine.

Some of the classes derived from IwObject that have Draw() methods, with or without OutputGraphics() methods, include:

  • IwBrep    IwPolyBrep   IwBrepCache
  • IwRegion  IwPolyFace   IwSurfaceCache
  • IwShell   IwCPolyFace  IwCurveCache
  • IwFace    IwPolyLoop
  • IwLoopuse IwPolyEdge   IwVector2d
  • IwEdge    IwVector3d
  • IwEdgeuse IwSurface    IwExtend2d
  • IwVertex  IwCubicBezierSurface IwExtend3D
  • IwFilletEdge IwBSplineSurface IwGrid
  • IwCurve   IwTangentField
  • IwCurveClassification IwCompositeCurve IwAxis2Placement
  • IwPointClassification IwPolarBox
  • IwLineSegmentClassification IwCutter IwPseudoBox
  • IwPolyPointClassification IwPlaneCutter
  • IwCurveInterval IwGaps
  • IwSolution IwObjGaps
  • IwSolutionArray

The Draw() methods can be called at anytime to place the graphics for an object into a display list that gets added to the global DisplayList array. This feature is very helpful for debugging. Object Draw() methods can be placed within an algorithm to see how it modifies geometry as it progresses. The function my_gfx_loop() can be called at anytime to render the DisplayLists and to temporarily switch the flow of control to the ui_test interface so that the displayed graphics can be rotated, zoomed, and panned before continuing with the algorithm under study.

Standard object display is managed through a set of global lists named:

  • UserBreps contains all Breps to render
  • UserPoints contains all Points to render
  • UserCurves contains all Curves to render
  • UserSurfaces contains all Surfaces to render
  • UserPolyBreps contains all PolyBreps to render
  • UserBooleanTrees contains all BooleanTrees to render
  • UserGaps contains all ObjGaps to render

The user object lists are managed by the following functions:

  • my_Delete_All_Objects() Clear all user object lists.
  • my_Draw_All_Objects() Rebuild global DisplayList array with DisplayLists for every user object list item.
  • my_Dump_All_Objects() Dump a pretty printed description of every user object list item to standard output.
  • UserTest::Draw(IwBrep *) Add Brep copy to UserBreps
  • UserTest::Draw(IwPolyBrep *) Add PolyBrep copy to UserPolyBreps
  • UserTest::Draw(IwCurve *) Add Curve copy to UserCurves
  • UserTest::Draw(IwEdge *) Add Edge->Curve copy to UserCurves
  • UserTest::Draw(IwSurface *) Add Surface copy to UserSurfaces
  • UserTest::Draw(IwFace *) Add Face->Surface copy to UserSurfaces
  • UserTest::Draw(IwVertex *) Add Vertex->Point copy to UserPoints
  • UserTest::Draw(IwPoint3d *) Add Point copy to UserPoints
  • UserTest::Draw(IwPoint3d *, IwPoint3d *) Add Line to UserCurves
  • UserTest::Draw(IwTArray<IwPoint3d>) Add point copies to UserPoints

Functions within the ui_test interface and explicit calls in user programs add and remove objects from the user object lists. A call to my_Draw_All_Objects() clears the old global display list array and replaces it with a new array of display lists generated by calling the Draw() method on every user object list item.

The following picture summarizes the ui_test graphics flow of control:


                                   Figure 1: ui_test graphics flow of control

View Parameters

The parameters that control the size, orientation, and positioning of the view box in model coordinates are stored in s_View, an IwViewParameters object. Currently this object is also used to store global interface state data.

Display Parameters

The parameters that control the output behavior of the Object Draw() functions are stored in s_Disp, an IwDisplayParameters object. Actions by the user change these values that will change the output graphics the next time that the global DisplayList array members are regenerated and redisplayed. The first set of values in this object is a set of draw bits and values that specify how to draw Breps, Faces, and Edges. These draw bits, their default values, and their associated behaviors include:

  • m_bHiddenCurve [FALSE] TRUE = Draw hidden line image
  • m_bDrawWireFrame [TRUE ] TRUE = Draw all Edges and Vertices
  • m_bDrawFacets [FALSE] TRUE = Generate/Output polygon facets
  • m_bDoShading [TRUE ] TRUE = display polygon facets as shaded image
                                       FALSE= display polygon facets as wires.
  • m_eTessellator [IW_DM_NLIB] Specify Nlib/openGL/NMTLib tessellator
  • m_bUseEdgeTypeColors [TRUE ] TRUE = Select EdgeColor based on type (manifold, lamina, wire)
                                                     FALSE= Select EdgeColor based on attribute or owner color
  • m_bDrawCrossHatch [FALSE] TRUE = Draw UV IsoParameterCurve crosshatch lines
  • m_bDrawKnots [FALSE] TRUE = Draw edge knotPoints (place surface xhatch lines on knot boundaries)
  • m_bDrawPolygon [FALSE] TRUE = Draw surface->ControlNet and curve->ControlPolygon
  • m_bDrawNormals [FALSE] TRUE = Draw Surface midPoint Normal vector
  • m_bDrawCurvature [FALSE] TRUE = Draw Curve Curvature combs
  • m_bDrawDerivatives [FALSE] TRUE = Draw Curve 1st Derivative combs
  • m_bDrawPinCushion [FALSE] TRUE = Draw surface vector fields
  • m_eLastMode Last value stored by iwgfx_SetDrawingMode. note: this value does not determine the draw state - rather when it was set all the drawing bits were set to a specific state, since that time, any draw bit might have been altered. This is saved to be kind of backward compatible with the previous mode based interface style.

The following sets of values within the s_Disp object contain parameters that specify the size and look of the graphical output. These values, their default values, and their behaviors are as follows:


  • m_bFlatShading // [FALSE] TRUE = When shading use flat shading, not Gouraud shading
  • m_bHIddenPolygon // [FALSE] TRUE = When shading skip back facing polygons

Cross Hatch

  • m_lCrossHatchUCount // [4] How many curves between the Knots in the U cross hatch
  • m_lCrossHatchVCount // [4] How many curves between the Knots in the V cross hatch
  • m_dCrossHatchLineWidth // [1] Line width for the non-knot cross hatch curves
  • m_dCrossHatchKnotLineWidth // [2] Line width for the cross hatch curves on knot values

Hidden Curve

  • m_lHiddenCurveDash // [1] 0 = visible, 1 - dash invisible, 2 - silhouette only
  • m_vHCRView // [Origin=(0,0,0), XAxis=(1,0,0), YAxis=(0,1,0)]
  • m_bPerspective // [FALSE] TRUE = Use Projection View not OrthoGraphic


  • m_dCrvTessAngle [10.0] Angular tolerance used in tessellation in degrees
  • m_dSrfTessAngle [25.0] Angular tolerance used in tessellation in degrees
  • m_dChordHeight [ 0.1] Tolerance that controls curve and polygon tessellation using chord height measurements. If using NURBS this is a pixel space distance (i.e. 25.0). If using Tessellation it is a model space distance.
  • m_dMax3DEdge [-4.0] Expected max EdgeLength to tessellate. When negative, compute dMax3DEdge based on box object BoundingBox size as compute dMax3DEdge based on box object BoundingBox size as dMax3DEdge = -0.025 * BBox.Size * dMax3DEdge
  • m_dMaxAspectRatio [ 0.0] When negative, use viewBased surface tessellation, else use view independent surface tessellation.
  • m_ePolygonOutputType [IW_PO_TRIANGLES] Specify how NMTLib tessellator
  • m_bViewBasedTess [FALSE] TRUE = NOT USED YET
  • Curvature and Derivative Combs and PinCushions
  • m_lSamplePointCount [25] Number of curve sample points
  • m_lUPointCount [10] Number of surface U Sample Points
  • m_lVPointCount [10] Number of surface V Sample Points
  • m_ePinCushionType [IW_DM_UNIT_NORMAL] Select various vector fields
  • m_dPinCushionScale [10.0] Scale applied to PinCushion Vectors
  • m_dCurvatureScale [-20.0] Scale applied to curvature combs

Line and Point Size

  • m_dLineWidth [2.0] number of pixels used to draw lines
  • m_dPointSize [4.0] number of pixels used to draw point icons
  • m_bDashedLines [FALSE] TRUE = draw crosshatched curves dashed

Application Colors

  • m_DefaultColor [0,0,0] normal object default color
  • m_DefaultShadingColor [.7,.7,.7] normal object default color used for Shaded Breps
  • m_InterruptColor [IW_BIG_DOUBLE..] when set to anything but IW_BIG_DOUBLE, overrides normal object color selection

Object Color, Line Width, and PointSize Management

When a display list is played back into the OpenGL pipeline its graphics are output using the current color, line width, and point size values up until the time when the display list itself sets these values. The NMTLib rule for building display lists is that color is always set prior to outputting geometry objects but that line width and point size are only set when a special size is needed. Whenever a line width or point size is set within a display list it is restored to its initial value when that line width or point size value is no longer needed.

Controlling Object Color in an Object DisplayList

The ui_test interface stores a default object color in s_Disp that is used to render all objects without a color specification. The default color can be changed at run time with the iwgfx_SetDefaultColor() function.

At run time, an objectís color is specified by a color attribute attached to the object or to the objectís owning Brep or PolyBrep. Attach a color attribute to an object or its containing Brep or PolyBrep with the calls,

  • IwVector3dAttribute *pColor = new(*s_pContext) IwVector3dAttribute( IW_AI_COLOR, s_VColor);
  • pObject->AddAttribute(pColor);

For debugging purposes, an objectís specified color can be overridden by setting an interrupt color stored in the s_Disp object with the commands,

  • iwgfx_SetColor()
  • iwgfx_ChangeColor(), and
  • iwgfx_ClearColor().

Sometimes drawn objects are rendered using a special application color such as vectors drawn for curvature combs and surface normals, or curves belonging to wire or lamina edges. Under these circumstances, when there is no interrupt or attribute color rather than using the default color for the object, use an application color instead.

The rule for determining which object color to use while building an object DisplayList is executed while building a DisplayList for an object and encoded into the function iwgfx_OutputObjectColor(IwColorRuleType eColorRule).

The rule is

  1. When s_Disp has a set interrupt color Ė use it, else
  2. When the object or the objectís Brep or PolyBrep owner has a color attribute Ė use it, else
  3. When eColorRule != IW_CR_STANDARD Ė use appropriate application color, else
  4. Use the DefaultColor stored in the s_Disp object.

Note the difference between modifying the default color and the interrupt color. Objects are drawn with the interrupt color even when the object has a color attribute or is drawn with an application color rule. Objects are only drawn with the default color when the object does not have a color attribute and the object is not being drawn with an application color rule. Also note shaded objects do not use the default color, they use the default shaded color.

The iwgfx_OutputObjectColor() function outputs the selected object color to OpenGL with a glColor() call which causes the color change to be compiled into the currently open DisplayList so that the color change will execute at the appropriate time when the DisplayList is finally played back by a call to iwgfx_DrawLists(). Only call the iwgfx_OutputObjectColor() function from within object Draw() and OutputGraphics() methods.

Implementing Object Draw() and OutputGraphics() Methods

All Draw() methods open and add a new DisplayList to the global DisplayList array to contain all the draw commands used to render the object. The behavior of many Draw() functions depend on the values stored within s_Disp. Most Draw() methods only use the s_Disp values while others overwrite some of those values as they draw. Two functions exist to fetch the s_Disp values depending on if the parameters are only to be used or if they are to be overwritten. These functions are:

  • iwgfx_RefGlobalDisplayParameters Get s_Disp reference when using parameters without modifications.
  • iwgfx_GetGlobalDisplayParameters Get copy of s_Disp parameters, needed when the called Draw() method overwrites any of the s_Disp parameter values.

A typical Draw() method

void Object::Draw()



// locals: global display parameters

const IwDisplayParameters &rDisp = iwgfx_RefGlobalDisplayParameters();

// use following instead when view parameter modification is required

// IwDisplayParameters sDisp ;

// Iwgfx_GetGlobalDisplayParameters(sDisp) ;

// start new DisplayList (unless one is already open)

iwgfx_Open() ;

// set Object Color

IwVector3D sColor = iwgfx_OutputObjectColor

(this, rDisp.GetShadedColorRule()) ;

// output Object graphics

OutputGraphics(rDisp) ;

// restore color state and end new DisplayList

iwgfx_OutputColor(sColor) ;

iwgfx_Close() ;

} // end Object::Draw

Writing OutputGraphics() methods.

The stream of color, line width, point size, and draw functions that render the object are placed within the OutputGraphics() method. Because a DisplayList is open, these calls do not get output to the graphics pipeline. Instead they get compiled into the open DisplayList to be played back into the graphics pipeline at some future time. Some objects with simple graphics donít bother to isolate the render functions into a separate OutputGraphics() method choosing to place the draw function calls directly into the Draw() method.

Outputting the color, line width, and point size values is not done with the iwgfx_SetCalls() but with iwgfx_OutputCalls(). The iwgfx_SetCalls() modify the global values stored within s_Disp while the iwgfx_OutputCalls() push a value out to the OpenGL stream. The set of iwgfx_OutputCalls() includes:

  • iwgfx_OutputObjectColor()
  • iwgfx_OutputColor()
  • iwgfx_ChangeOutputColor()
  • iwgfx_OutputPointSize()
  • iwgfx_OutputLineWidth()
  • iwgfx_OutputDashedLines()

Once the color, line width, and point size parameters are set as desired output actual geometry shapes using the iwgfx_DrawCalls() including:

  • iwgfx_DrawPoint(),
  • iwgfx_DrawLine(),
  • iwgfx_DrawPolyLine(),
  • iwgfx_DrawTriangle(), and for drawing meshes
  • iwgfx_NewNurbsRenderer(),
  • iwgfx_NurbsSurface(), and
  • iwgfx_NurbsCurve().

Draw() and OutputGraphics() Architectural Rules

The NMTLib architecture rules for implementing Draw() and OutputGraphics() methods include:

  1. Never use the iwgfx_SetCalls() from within a Draw() or OutputGraphics() method. Abiding by this rule prevents one draw routine from modifying the behavior of other draw routines.
  2. The generalization of rule 1 is: never make a change to the global display parameters stored in s_Disp from a Draw() or OutputGraphics() method. Some OutputGraphics() methods want to override s_Disp global values. Always send such methods a copy of the s_Disp values retrieved with the iwgfx_GetGlobalDisplayParameters() function so that any overrides cannot have side effects on other draw routines.
  3. Avoid calling a Draw() method from a Draw() or OutputGraphics() method, instead make sure the desired object graphics is divided up into a Draw() and OutputGraphics() function and call the OutputGraphics() function directly. This rule is not required as long as all Draw() functions make sure that they make no permanent change to the color, line width, and point size state of the OpenGL pipeline and the values stored in s_Disp.
  4. Whenever the point size or line width is changed it must be changed back to its current value when the need for the new size is done. This allows draw functions to call other Draw() or OutputGraphics() methods without side effects.

DisplayLists in OpenGL, NMTLib, and ui_test

An openGL displayList is a compiled set of openGL commands that can be run repeatedly very quickly. One creates a displayList by 

  • opening a new displayList 
  • executing any set of openGL rendering commands 
  • close displayList 

All the executed openGL commands get compiled into a openGL secret format. Applications access the display through an ID, which is implemented as an integer value. The display is rendered by sending the displayList ID to the openGl call, glCallList(DisplayListID). 

NMTLib rendering is designed to build and store  displaylists while keeping color, line width, point size,  and dashed line pattern information outside of the list so that an application can vary those without having  to rebuild the displaylist. This makes it possible for  NMTlib rendering to support highlighting and the like at interactive rates. One makes iwgfx_Calls() which encapsulate the openGl calls.

NMTLib does this by creating and managing its own display lists in objects called IwDisplayList. The IwDisplayList stores the openGL DisplayList Id and color and draw size parameters. NMTLib stores all the the displayLists in a global array and uses the function iwgfx_DrawLists() to render those. Prior to asking openGL to render the openGL display list the iwgfx_DrawLists() funtion makes openGL calls to set color and draw size as 

  • iwgfx_OutputPointSize(rDisplayList.GetPointSize()) ;
  •  iwgfx_OutputLineWidth(rDisplayList.GetLineWidth()) ;
  •  iwgfx_OutputDashedLines(rDisplayList.GetDashedLine()) ; 
  • iwgfx_OutputColor(rDisplayList.GetColor()) ;
  •  // output DisplayList 
  • GLuint lDisplayListId = rDisplayList.GetDisplayListId() ; 
  • glCallList(lDisplayListId); IW_GL_DUMP("glCallList", lDisplayListId);

 All one needs to do to change a color or draw size is to modify the rDisplayList member value and leave it to iwgfx_DrawLists() to get that information out at display time. 

NMTLib's list of IwDisplayLists is stored in an instance of the class IwViewParameters. This instance should be created and stored by the ui-test application as part of the IwView object. However, due to evolutionary reasons, NMTlib creates one global IwViewParameters object called s_View. 

Applications need to control which color and draw sizes are stored in the IwDisplayList objects when the objects are created and when an application wants to change those values. 

IwDisplayLists are created and stored in the global list by the call iwgfx_Open(). the current behavior for iwgfx_Open() is to initialize the stored color and draw sizes from values  fetched from a passed in color value and the calls,  

  • iwgfx_GetLineWidth() and  
  • iwgfx_GetPointSize(). 

The values fetched by iwgfx_GetLineWidth() and iwgfx_GetPointSize() come from a second global graphics value called s_Disp, an instance of IwDisplayParameters. The IwDisplayParameters class is a long list of all the object rendering values that are displayed in ui_test. Values in s_Disp can be set with iwgfx_calls. A typical calling sequence to store the desired color and draw size parameters in an IwDisplayList are:

  • // set pointsize = 1, linesize = 2, color = 0.0, 0.0, 1.0 in global s_Disp object. 
  • iwgfx_SetLook(1, 2, 0,0,1) ; 
  • // create an IwDisplayList using values fetched from s_Disp and store it in the displayLists array within the global s_View object. 
  • iwgfx_Open() ;
  •  . . . gl Draw commands get compiled into the drawlist . . . 
  • perhaps: pBrep->Draw() ; 
  •  // closes the openGl display list 
  • iwgfx_Close(); 

New behaviors

The iwgfx_Open() method has been modified to take optional color, line width, and point size arguments. If used, these are stored in the IwDisplayList created and placed on the global displayList array instead of using the ones stored in s_Disp. This allows a special draw function to use special colors and draw sizes rather than the general ones. I used this feature when creating a drawList for the new IwGap object.  An example call might look like 

  • // start new displayList (unless one is already open) 
  • // use gap color and draw sizes rather than default ones
  •  double dLineWidth = iwgfx_GetGapLineWidth() ; 
  • double dPointSize = iwgfx_GetGapPointSize() ; 
  • IwVector3d &rGapColor = iwgfx_GetRuleColor(NULL, IW_CR_GAP) ; 
  • iwgfx_Open(rGapColor, &dLineWidth, &dPointSize);

 Later when iwgfx_DrawLists() is called, the drawList created by the  above call will be rendered after setting the color, line width and Point size values as specified above. 

For highlight purposes one will want to fetch the IwDisplayList object stored in the global array and modify the stored colors and draw sizes. This is a little tricky only because the drawlists on the global list array are stored by value, not by reference.  

The new function iwgfx_GetDisplayList() returns a pointer to the IwDisplayList taking a GLuint Id value. So to support highlighting in application one has to manage the following challenges: 

  1. Some kind of I/O that fetches the IwDisplayList Id value. 
  2. IwDisplayList *pDisplayList = iwgfx_GetDisplayList(lDisplayListId) ; 
  3. Some combination of pDisplayList->SetColor(), pDisplayList->SetPointSize(), pDisplayList->SetLineWidth() calls.
  4. Redisplay all lists with iwgfx_DrawLists().

Action Items 

1. If we want ui-test to grow up into a multiwindow application we need to replace the s_View global instance of  the IwViewParameters object with a pointer stored in the IwView object.

2. We also need to replace the s_Disp global instance of the IwDisplayParameters object with a pointer stored in the IwVeiwObject.

3. To be backward compatible for our users we will need to support both the current global variable approach and the desired stored in the application approach. We need to add a trailing optional IwViewParameters argument to most of the iwgfx_Calls() as iwgfx_Call(IwViewParameters *pOptViewParameters = &s_View) ;

4. Change the IwViewParameters array of IwDisplayLists from IwTArray<IwDisplayList> to IwTArray<IwDisplayList *>. This may not be possible if any existing applications use our rendering package.

Interfacing Between NLib and 'Iw' Objects

SMLibprovides an interface which allows users to construct 'Iw'objects directly from NLib structures. The IwBSplineCurve and the IwBSplineSurface both contain equivalent NLib CURVE and SURFACE structures. Structurally they are the same but the memory management utilized in each case is extremely different.The 'Iw' object allocates the corresponding NURBS curve or surface as a single block of memory. NLib allocates a NURBS curve or surface as many smaller components. In terms of usage what this means is that they are interchangeable only for operations where no editing or manipulation of these structures is required. For example you may utilize the CURVE pointer inside of a IwBSplineCurve in query operation such as evaluation (N_crvevn) but you could not add a knot to it (N_kntadd). In general we recommend that you do not try to interchange the forms directly but go through existing interfaces which create the corresponding copies. Only interchange the forms when it is absolutely necessary for performance.

We have several utilities which will help you to transfer data between the libraries. Both the IwBSplineCurve and IwBSplineSurfacehave constructors which will take a pointer to a NLib CURVE or SURFACE. The constructors either create a copy or reference the NLib structure directly. We recommend that you create a copy. There is a section of software below that shows how this process works. You may also obtain the internal pointer to the CURVE or SURFACE by invoking the GetGwNurbPointer methods. You can then use this to create a NLib native NURBS using a copy method. This is shown below also.

This first example shows how to construct a IwBSplineCurve that copies the data from a CURVE generated in NLib.

CURVE *cur; // pointer to an NLib curve structure. IwBSplineCurve *pBSplineCurve; // pointer to a NMTLib curve (internally it has a pointer to a CURVE). cur = ... // create and manipulate curve in NLib. pBSplineCurve = new (pContext)IwBSplineCurve(3, (void*)cur);    // constructs a NMTLib curve by copying the NLib cur.

This second example shows how to construct aIwBSplineCurve which references an existing CURVE from NLib. 

BOOLEAN bIsBorrowed = TRUE;   // prevents copy of cur - it utilizes cur directly inside of the IwBSplineCurve object.
  // This is a little dangerous and is recommended only for expert users. pBSplineCurve = new (pContext) IwBSplineCurve(void*)cur, 3, bIsBorrowed);

 This third example shows how to create a CURVE from a IwBSplineCurve. 

IwBSplineCurve *pBSplineCurve = .....; CURVE *pcur = pBSplineCurve->GetGwNurbPointer(); // note the pcur is an internal pointer used by the IwBSplineCurve and must not be deleted or edited. STACKS SL; CURVE new_cur; U_inicur(new_cur); U_curcop(pcur,new_cur,SL);
// Now there is a new curve which is in the NLib format it may be editied, deleted, etc.

The fourth example shows how to convert a IwCurve into a IwBSplineCurve;

IwCurve *pCurve; IwBSplineCurve *pBSC = IW_CAST_PTR(IwBSplineCurve, pCurve);

There are equivalent methods that can be used to transfer data between the IwBSplineSurface, IwSurface, and the NLib SURFACE. 

The fifth example shows how to convert an analytic surface (cylinder, cone etc) into a Nurbs form;

IwCylinder *Cyl; IwBSplineSurface *pNurbsSrf = new (crContext) IwBSplineSurface (*Cyl);

SMLib Variable Naming

SMLib source code uses CamelCased long variable names with type prefixing.

Prefixes are:

  • m    Class member
  • p     Pointer to any type
  • r        Reference to any type
  • s     A structure or class automatic variable, or a contained member
  • v     Vector -used just like an 's'
  • cr    A const reference variable
  • cp   A const pointer variable
  • e    An enum type
  • l     Type ULONG, long
  • n    Type ULONG, int, long used for index, counts and sizes
  • d    Type double
  • b    Type IwBoolean
  • t     Type IW_TYPE
  • a     An array of any type
  • ap   An array of pointers to any type

Example SMLib class member definitions:

  • IwRegion     *m_pInfiniteRegion
  • IwCurve       &m_rCurve
  • IwTArray,IwObject *>        m_sBaseObjs
  • IwExtend1dm_sInterval
  • IwExtend2dm_UVDomain
  • const IwCurve &m_crCurve
  • const IwCurve *m_cpCurve
  • IwSolutionType m_eSolutionType
  • ULONG           m_lDebugCount
  • ULONG          m_nSize
  • double            m_dTol
  • IwBoolean      m_bEditingEnabled
  • IW_TYPE      m_tShellType
  • IwTree           *m_apTrees[IW_GS_MAX_TREES]

Example SMLib formal argument and automatic variable definitions

  • IwBrep          *pBrep
  • IwSolution     &rSolution
  • IwExtent1d    sUnion
  • IwVector3d    vAxis  
  • const IwSolution  &crSolution
  • const gw_CURVE *cpGwNurb
  • IwBSplineCurveForm   eBSplineCurveForm
  • ULONG        ldim, nSolutions
  • double          dAngle
  • IwBoolean    bFailedFaces
  • IwVector3d   aVectors[6]

Legal Stuff

All of the software and documentation received with this release is copyrighted by Solid Modeling Solutions, Inc. You may not distribute source code or documentation for this software outside of the company and the site which owns the license. The standard license agreement allows you to freely distribute object code in any application which does not contain a programmatic interface. All software and documentation is considered proprietary information and the intellectual property of Solid Modeling Solutions, Inc. This document contains trade secret information which is deemed proprietary.

Copyright © 1998-2010 Solid Modeling Solutions All rights reserved.
Information in this document is subject to change without notice.