Open Inventor Technical FAQ


(Copyright 2000-2004, Mercury Computer Systems, All Rights Reserved)

  Other Tools/Operating System Features  

  1. How can I write my application so it will run on UNIX, Linux, and Windows?

    First, Linux is essentially the same as UNIX, no problem there. However, there is no "silver bullet" for cross-platform app development in general. Open Inventor itself is mostly platform independent. There are a few methods unique to UNIX or unique to Windows, but they are flagged in the help files. The real problem is the user interface. Here are some of the many possible strategies.

    • Write command line apps only (these can be very portable but inherently have a very limited user interface).
    • Use dialog boxes only for the user interface -- then you can use the DialogMaster component of Open Inventor to create portable apps. These user interfaces are also limited, but can be effective for test, demo, and prototype apps.

    • Use a third party cross-platform user interface (UI) toolkit. This may require some work on integrating Open Inventor with the UI toolkit, especially on UNIX where the Open Inventor SoXt components are specifically Motif widgets. However some UI toolkits use Motif on UNIX and allow you to get the actual Motif widget handle for a UI object. On Windows, the Open Inventor SoWin components only use Win32 APIs, so they should work with almost any UI toolkit that allows you to get the native window handle (HWnd) for a UI object. See, for example, Qt (http://www.trolltech.com).

    • Write the user interface twice, once using Motif and once using Win32 and/or MFC. This is the traditional approach. It provides a "native look and feel" in both environments, but at the cost of significantly more programming.

    • Write the user interface using Win32 and/or MFC and use a porting environment to build and run on UNIX. The major ones are Wind/U (http://www.bristol.com) and MainWin (http://www.mainsoft.com). Mercury Computer Systems does not directly support these but we have customers using them. It allows a single source, but requires additional licensing and a runtime environment.

    • Use Java. Mercury provides MeshViz and Open Inventor as a Java class library. You can write the entire application in Java or you can write the user interface in Java and use JNI to call into a C++ application "core". We have customers doing both. This allows a single source, but there can be problems with Java portability, security, etc.

  2. Back | Top

  3. Can we use OpenGL functions in Open Inventor?

    The answer is a very resounding yes! However, one cannot arbitrarily mix Open Inventor and OpenGL calls in one's program. Usually the OpenGL calls are placed in an SoCallback node or in a custom node. You must be careful to save and restore any OpenGL state, so that Open Inventor doesn't get confused about which state changes it needs to send to OpenGL. The code might look something like the fragment below.

    Chapter 17 of the Inventor Mentor addresses this whole area and is entitled "Using Inventor with OpenGL". The Mentor example programs are included with the Open Inventor distribution, hence you will receive some example programs on OpenGL being used with Open Inventor.

    
      ...
      SoGLRenderAction *pGLRA = (SoGLRenderAction*)action;
      const SbViewportRegion vport = pGLRA->getViewportRegion();
      const SbVec2s vpSize = vport.getViewportSizePixels();
      short vpWidth, vpHeight;
      vpSize.getValue( vpWidth, vpHeight );
    

    // Save OpenGL state glPushAttrib( GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT );
    // Setup optimal OpenGL state for drawing glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); // Draw on top of everything glDisable(GL_DITHER); glDisable(GL_FOG); glDisable(GL_LIGHTING); glDisable(GL_LOGIC_OP); glDisable(GL_POLYGON_SMOOTH); glDisable(GL_POLYGON_STIPPLE); glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_1D); glDepthMask( 0 ); // don't update Z buffer

    // Setup 2D drawing environment (pseudo-pixel coordinates) glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glOrtho( 0., vpWidth, 0., vpHeight, 0., 1. );
    // Draw glBegin( GL_TRIANGLE_STRIP ); ... glEnd();
    // Restore OpenGL state glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glPopAttrib();

    Note: The callback function will be called by every action that traverses the callback node. Remember to test the type of the action if the function should do something different (or not at all) for different actions. For example:

    if (action->isOfType(SoGLRenderAction::getClassTypeId()))
    

    Specifically, callbacks should generally not make OpenGL calls except when handling an SoGLRenderAction. This is the only time that Inventor guarantees that a valid OpenGL context exists and is current.

    Note: By default the callback node may become part of a render cache (OpenGL display list). In this case, so long as the cache remains valid, the callback node will not be traversed by the render action. If the callback function always makes the same OpenGL calls, this might be OK since the OpenGL calls will be part of the cache. But if the callback function interacts with the application or performs different actions at different times, then it should disable render caching. For example:

    SoState *state = action->getState();
    SoGLCacheContextElement::shouldAutoCache(state,
    SoGLCacheContextElement::DONT_AUTO_CACHE);


  4. Back | Top

  5. [Win32] If I want to use GDI with Open Inventor (e.g., for drawing a rubberband line), what do I need to look out for?

    • It is not guaranteed that GDI calls can be made on an OpenGL window. It does work in almost all cases with the Microsoft generic OpenGL, but may not work with some 3D accelerators.

      You can tell if GDI rendering is allowed by looking at the PIXELFORMATDESCRIPTOR structure, specifically if the bit PFD_SUPPORT_GDI is set in the dwFlags member. (The oglinfo program supplied by Mercury displays info about GDI support.)

    • There is absolutely no way to do GDI drawing on the OpenGL "back buffer". You can only draw on the "front buffer" (aka the screen). (This is a "feature" of OpenGL.) So you need to make sure the scene has been rendered and wglSwapBuffers has been called before doing GDI drawing. Usually this is not too hard in an Inventor program.
      The boxZoom example (...\src\Inventor\examples\IVF) shows one way of using GDI calls.

  6. Back | Top

  7. What is Wind/U?

    Wind/U is a "porting environment" for migrating apps from Microsoft Windows (Win32, MFC) to UNIX (X, Motif). It is conceptually the opposite of NuTCRACKER and Interix. Wind/U is a product of Bristol Technology (http://www.bristol.com).


  8. Back | Top

  9. What can you tell me about using Open Inventor with Wind/U?

    The following information was supplied by one of our customers.

    1. The first major hurdle is to make sure that the Open Inventor libraries are compiled using a compiler compatible with what is necessary for Wind/U (i.e. we had to use aCC, the new HP C++ compiler, which is not binary compatible with its predecessor).

    2. Issue a wuhWndToDrawingWidget call on the HWND (window handle) to convert the Wind/U window handle to the true Motif window handle in the SoXt::init message.

      void ClinkGraphics::graphicsWindow(HWND pHWND, CWinApp *pApp)
      {
      #ifdef CLINK_HPUX_SOURCE
      	SoXt::init(wuhWndToDrawingWidget(pHWND));
      #else
      	SoXt::init(pHWND);
      	SoXt::setInstance(pApp->m_hInstance);
      	SoXt::setPrevInstance(pApp->m_hPrevInstance);
      #endif
      }
    3. Wind/U defines WIN32 on UNIX platforms, which causes problems with Open Inventor. I have created a file called StdInventor and put the following around the set of includes I need:
      #ifdef _DEBUG
      #define StdInventor_DEBUG_UNDEF _DEBUG
      #undef _DEBUG
      #endif
      
      #ifdef CLINK_HPUX_SOURCE
      
      #undef WIN32
      #undef BOOL
      
      #else
      
      #ifdef WIN32
      #include <SoWinEnterScope.h>
      #endif
      
      #endif
      
      .... #includes...
      
      #ifdef CLINK_HPUX_SOURCE
      
      #undef WIN32
      #define BOOL microsoftBOOL
      
      #else
      
      #ifdef WIN32
      #include <SoWinLeaveScope.h>
      #endif
      
      #endif
      
      #ifdef StdInventor_DEBUG_UNDEF
      #undef StdInventor_DEBUG_UNDEF
      #define _DEBUG
      #endif
       
    4. Multiple typedefs of BOOL (very neat problem...). Motif defines BOOL as an unsigned char, while Wind/U typedefs it as an int. Most compilers do not like multiple typedefs to the same token. This is not pretty but it does the job in conjunction with #3 (see above).

      
      windef.h (in Wind/U include files)
      


      typedef int microsoftBOOL; //typedef int BOOL; #define BOOL microsoftBOOL

    5. Protection of some Open Inventor .h files
      <Inventor/SbTime.h>
      

      #ifdef WIN32 static SbTime maxTime() #else #define ___PROTECT_MAX___ max #undef max static SbTime max() #define max ___PROTECT_MAX___ #undef ___PROTECT_MAX___ #endif

      <Inventor/errors/SoDebugError.h>

      #ifdef WIN32 enum Severity { SERROR, // Error WARNING, // Just a warning INFO // No error, just information }; #else enum Severity { #define ___PROTECT_ERROR___ ERROR #undef ERROR ERROR, // Error #define ERROR ___PROTECT_ERROR___ #undef ___PROTECT_ERROR___ WARNING, // Just a warning INFO // No error, just information }; #endif

      <MeshViz/graph/PbBase.h>

      #define ___PROTECT_DELETE___ DELETE #undef DELETE DELETE, #define DELETE ___PROTECT_DELETE___ #undef ___PROTECT_DELETE___


  10. Back | Top

  11. Can I make my Open Inventor program multi-threaded to run on more than one CPU?

    [NEW: Open Inventor 3.0] Yes!
    Open Inventor 3.0 includes multiple thread support. Here are just a few of the ways you can use multiple threads in your Open Inventor 3.0 application:

    1. One thread for rendering, another thread for computation.
    2. Multiple threads rendering different scene graphs.
    3. Multiple threads rendering the same scene graph.

    In a multithreaded program, every thread that uses Open Inventor classes must call SoDB::threadInit.

    See the help file for additional info. The following two topics will likely be of particular interest: the Multi-Threads Overview and SoDB (threadInit method).

    In particular, note that if more than one thread is accessing the same scene graph, each thread should request a read or write lock (depending on its needs). See SoDB::writeLock, etc.

    [OLD: Open Inventor 2.6.2 and earlier] Yes...
    Your application can be multi-threaded to take advantage of multiple CPUs. HOWEVER, because Open Inventor is not "thread-safe," Open Inventor can only run in one of those threads. Specifically, the application should ensure that all creation and use of Inventor objects occurs in a single thread. If necessary, other threads can signal the Inventor thread (for example by sending a Windows message) when a change needs to be made to the scene graph.


  12. Back | Top

  13. Is there any Unicode support in Open Inventor and/or MeshViz?

    Open Inventor and MeshViz do not directly support Unicode at this time. However, we do support MBCS (multi-byte character set) encoding of other character sets. You can use Unicode in your application as long as you convert to/from MBCS when accessing Open Inventor.

    [Win32] A customer reports they have been able to compile a Unicode version of their Open Inventor application by making heavy use of the TCHAR, USES_CONVERSION, A2CT() and T2CA() macros to help with the conversion.

    
    CString theText(_T("Text"));
    

    LPCTSTR pText = theText;

    USES_CONVERSION;

    SbString strText(T2CA(pText));

    theText = A2CT(strText.getString());

    basic_string theCPPString = A2CT(strText.getString());

    strText = T2CA(theCPPString.c_str());


  14. Back | Top

  15. Can I run a 3D graphics application on a UNIX system and display the graphics remotely on a Windows PC?

    Yes, this is possible.

    You would need to have installed an X server on the PC, and in particular it would need to support the GLX extension because GLX is the protocol that UNIX OpenGL implementations send over the network.

    If you want 3D acceleration (and this would be highly desirable), the X server's GLX implementation must be able to take advantage of the 3D hardware accelerator installed on the PC. We know of two PC X server vendors that do support the GLX extension and offer support for hardware acceleration: Hummingbird and WRQ. There may be others.

    Open Inventor 3.0 and Beyond
    An X server without GLX will not work if an Open Inventor version prior to 3.0 is used. With Open Inventor 3.0 and its new remote rendering feature, one can display from a UNIX host to a vanilla X server -- but the performance will not be very good because X does not provide image compression. This scenerio of displaying on a remote PC having an X server (but no GLX) would be OK for crude tests but certainly not for scenes that include dynamics. The recommended way of displaying remotely on a PC without GLX would be to use a remote viewer like VNC that supports image compression (www.uk.research.att.com/vnc/). See also the Remote Rendering chapter in the User's Guide.


  16. Back | Top

  17. Does Open Inventor support 64-bit programming?

    Yes, but on most systems 64-bit code is incompatible with 32-bit code, so you need 64-bit compatible Open Inventor libraries. There are 64-bit compatible Open Inventor libraries for SGI IRIX and Sun Solaris systems (so far).


  18. Back | Top

- end -