OpenTracker

An Open Architecture for Reconfigurable Tracking based on XML | Contact

SpaceMouseModule.cxx

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (c) 2006,
00003  * Institute for Computer Graphics and Vision
00004  * Graz University of Technology
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  * Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the following disclaimer.
00013  *
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the distribution.
00017  *
00018  * Neither the name of the Graz University of Technology nor the names of
00019  * its contributors may be used to endorse or promote products derived from
00020  * this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00023  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00024  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00025  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00026  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * ========================================================================
00034  * PROJECT: OpenTracker
00035  * ======================================================================== */
00042 /* ======================================================================= */
00043 
00044 // this will remove the warning 4786
00045 #include "../tool/disable4786.h"
00046 
00047 #include "SpaceMouseSource.h"
00048 #include "SpaceMouseModule.h"
00049 
00050 #ifdef USE_SPACEMOUSE
00051 
00052 #include <stdio.h>
00053 #if defined (WIN32) || defined (GCC3)
00054 #include <iostream>    // VisualC++ uses STL based IOStream lib
00055 #else
00056 #include <iostream.h>
00057 #endif
00058 
00059 #include <Windows.h>
00060 #include <math.h>
00061 
00062 /* SpaceWare Specific Includes */
00063 #include "spwmacro.h"  /* Common macros used by SpaceWare functions. */
00064 #include "si.h"        /* Required for any SpaceWare support within an app.*/
00065 #include "siapp.h"     /* Required for siapp.lib symbols */
00066 
00067 #include "..\core\MathUtils.h"
00068 
00069 //using namespace std;
00070 
00071 namespace ot {
00072 
00073     HWND        SpaceMouseModule::hWndSpaceMouse = NULL;
00074     SiHdl       devHdl;         /* Handle to Spaceball Device */
00075     SiOpenData  oData;          /* OS Independent data to open ball  */
00076 
00077 
00078     LRESULT FAR PASCAL WndSpaceMouseProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00079     {
00080         return DefWindowProc(hWnd, uMsg, wParam, lParam);
00081     };
00082 
00083     // Destructor method
00084     SpaceMouseModule::~SpaceMouseModule()
00085     {
00086         nodes.clear();
00087     }
00088 
00089     // This method is called to construct a new Node.
00090     Node * SpaceMouseModule::createNode( const std::string& name, StringTable& attributes)
00091     {
00092         if( name.compare("SpaceMouseSource") == 0 )
00093         {
00094             SpaceMouseSource * source = new SpaceMouseSource;
00095             source->event.getConfidence() = 1.0f;
00096             nodes.push_back( source );
00097             ACE_LOG_INFO("ot:Built SpaceMouseSource node\n");
00098             initialized = 1;
00099             return source;
00100         }
00101         return NULL;
00102     }
00103 
00104     // opens SpaceMouse library
00105     void SpaceMouseModule::start()
00106     {
00107         if( isInitialized() == 1 && !nodes.empty())
00108         {
00109             ThreadModule::start();
00110         }
00111     }
00112 
00113     // closes SpaceMouse library
00114     void SpaceMouseModule::close()
00115     {
00116         // stop thread
00117         lock();
00118         stop = 1;
00119         unlock();
00120 
00121         if( (isInitialized() == 1) && (devHdl != NULL))
00122         {
00123             /* should maybe be called even if devHdl == NULL */
00124             SiTerminate();  /* called to shut down the SpaceWare input library */
00125         }
00126     }
00127 
00128 
00129     // This is the method executed in its own thread. It polls the joysticks.
00130 
00131     void SpaceMouseModule::run()
00132     {
00133         WNDCLASS  wndclass ;
00134         static int init = 0;
00135 
00136         if( init == 0 )
00137         {
00138 
00139             /*init the SpaceWare input library */
00140             if (SiInitialize() == SPW_DLL_LOAD_ERROR)
00141             {
00142                 LOG_ACE_ERROR("ot:SpaceMouseModule Error Loading SIAPPDLL.DLL.\n");
00143                 exit(1);
00144             }
00145 
00146             // Fill in window class structure with parameters that describe the message-only window.
00147             wndclass.style =         0;
00148             wndclass.lpfnWndProc =   WndSpaceMouseProc ;
00149             wndclass.cbClsExtra =    0;
00150             wndclass.cbWndExtra =    0;
00151             wndclass.hInstance =     NULL;
00152             wndclass.hIcon =         NULL;
00153             wndclass.hCursor =       NULL;
00154             wndclass.hbrBackground = 0;
00155             wndclass.lpszMenuName =  NULL ;
00156             wndclass.lpszClassName = "dummyClassSpaceMouseModule";
00157 
00158             /* Register display window class */
00159             if ( RegisterClass(&wndclass) == 0)
00160             {
00161                 LOG_ACE_ERROR("ot:SpaceMouseModule Could not register windowclass.\n");
00162                 exit(1);
00163             }
00164 
00165             hWndSpaceMouse = CreateWindow(
00166                                           "dummyClassSpaceMouseModule",
00167                                           NULL,
00168                                           NULL,
00169                                           0,
00170                                           0,
00171                                           CW_USEDEFAULT,
00172                                           CW_USEDEFAULT,
00173                                           NULL,
00174                                           NULL,
00175                                           NULL,
00176                                           NULL
00177                                           );
00178 
00179             if (hWndSpaceMouse == NULL)
00180             {
00181                 LOG_ACE_ERROR("ot:SpaceMouseModule Could not create message-only window.\n");
00182                 exit(1);
00183             }
00184 
00185             SiOpenWinInit (&oData, hWndSpaceMouse);  /* init Win. platform specific data  */
00186             SiSetUiMode(devHdl, SI_UI_ALL_CONTROLS); /* Config SoftButton Win Display */
00187 
00188             /* open data, which will check for device type and return the device handle
00189                to be used by this function */
00190             if ( (devHdl = SiOpen ("ot_spacemouse", SI_ANY_DEVICE, SI_NO_MASK,
00191                                    SI_EVENT, &oData)) == NULL)
00192             {
00193                 // could not open spacemouse device handle
00194                 SiTerminate();  /* called to shut down the SpaceWare input library */
00195                 ACE_LOG_INFO("ot:Could not fetch device handle for SpaceMouse.\n");
00196                 /* ? do not exit? close dummy window? */
00197                 initialized = 0;
00198                 exit(1);
00199             }
00200 
00201             initialized = 1;
00202             init = 1;
00203 
00204             /*      if (SiBeep(devHdl, "ffffffff") == SI_BAD_HANDLE)
00205             {
00206             ACE_LOG_INFO("could not beep...\n");
00207             }
00208 
00209             */
00210         }
00211 
00212 
00213         while(stop == 0)
00214         {
00215             processMessages();
00216         }
00217     }
00218 
00219 
00220     void SpaceMouseModule::pushEvent()
00221     {
00222         SpaceMouseSource *source;
00223 
00224         if( isInitialized() == 1 )
00225         {
00226             for( NodeVector::iterator it = nodes.begin(); it != nodes.end(); it++ )
00227             {
00228                 source = (SpaceMouseSource *) *it;
00229 
00230                 lock();
00231                 if (source->changed == 1)
00232                 {
00233                     source->event = source->tmpEvent;
00234                     source->changed = 0;
00235                     unlock();
00236                     source->push();
00237                 }
00238                 else
00239                     unlock();
00240             }
00241         }
00242     }
00243 
00244 
00245     // pushes events into the tracker tree.
00246     void SpaceMouseModule::processMessages()
00247     {
00248         MSG            msg;      /* incoming message to be evaluated */
00249         BOOL           handled;  /* is message handled yet */
00250         SiSpwEvent     Event;    /* SpaceWare Event */
00251         SiGetEventData EData;    /* SpaceWare Event Data */
00252 
00253         int             num;
00254         unsigned short  newBut;
00255         float           newPosX;
00256         float           newPosY;
00257         float           newPosZ;
00258         float           newRotX;
00259         float           newRotY;
00260         float           newRotZ;
00261 
00262         if( isInitialized() == 1 )
00263         {
00264             /* as long as there are messages waiting */
00265             WaitMessage();
00266             while ( PeekMessage( &msg, hWndSpaceMouse, 0, 0, PM_REMOVE ) )
00267             {
00268                 //ACE_LOG_INFO("successful!\n");
00269                 handled = SPW_FALSE;
00270 
00271                 /* init Window platform specific data for a call to SiGetEvent */
00272                 SiGetEventWinInit(&EData, msg.message, msg.wParam, msg.lParam);
00273 
00274                 /* check whether msg was a Spaceball event and process it */
00275                 if (SiGetEvent (devHdl, 0, &EData, &Event) == SI_IS_EVENT)
00276                 {
00277                     if (Event.type == SI_MOTION_EVENT)
00278                     {
00279 
00280                         /* process Spaceball motion event */
00281                         newPosX = Event.u.spwData.mData[SI_TX] / 330.0;
00282                         newPosY = Event.u.spwData.mData[SI_TY] / 330.0;
00283                         newPosZ = -Event.u.spwData.mData[SI_TZ] / 330.0;
00284                         newRotX = (Event.u.spwData.mData[SI_RX] / 330.0)*SPW_PI/2.0;
00285                         newRotY = (Event.u.spwData.mData[SI_RY] / 330.0)*SPW_PI/2.0;
00286                         newRotZ = -(Event.u.spwData.mData[SI_RZ] / 330.0)*SPW_PI/2.0;
00287 
00288                         for( NodeVector::iterator it = nodes.begin(); it != nodes.end(); it++ )
00289                         {
00290                             lock();
00291                             SpaceMouseSource * source = (SpaceMouseSource *)(*it);
00292                             source->tmpEvent.getPosition()[0] = newPosX;
00293                             source->tmpEvent.getPosition()[1] = newPosY;
00294                             source->tmpEvent.getPosition()[2] = newPosZ;
00295                             MathUtils::eulerToQuaternion(newRotX, newRotY, newRotZ, source->tmpEvent.orientation);
00296                             MathUtils::normalizeQuaternion(source->tmpEvent.orientation);
00297                             source->changed = 1;
00298                             unlock();
00299                         }
00300                     }
00301                     if (Event.type == SI_ZERO_EVENT)
00302                     {
00303                         // process Spaceball zero event
00304                         for( NodeVector::iterator it = nodes.begin(); it != nodes.end(); it++ )
00305                         {
00306                             lock();
00307                             SpaceMouseSource * source = (SpaceMouseSource *)(*it);
00308                             source->tmpEvent.getPosition()[0] = 0.0;
00309                             source->tmpEvent.getPosition()[1] = 0.0;
00310                             source->tmpEvent.getPosition()[2] = 0.0;
00311                             source->tmpEvent.getOrientation()[0]  = 0.0;
00312                             source->tmpEvent.getOrientation()[1]  = 0.0;
00313                             source->tmpEvent.getOrientation()[2]  = 0.0;
00314                             source->tmpEvent.getOrientation()[3]  = 1.0;
00315                             source->changed = 1;
00316                             unlock();
00317                         }
00318                     }
00319 
00320                     if (Event.type == SI_BUTTON_EVENT)
00321                     {
00322                         if ((num = SiButtonPressed (&Event)) != SI_NO_BUTTON)
00323                         {
00324                             /* process Spaceball button event */
00325                             newBut = pow(2, num - 1);
00326                             for( NodeVector::iterator it = nodes.begin(); it != nodes.end(); it++ )
00327                             {
00328                                 lock();
00329                                 SpaceMouseSource * source = (SpaceMouseSource *)(*it);
00330                                 source->tmpEvent.getButton() |= newBut;
00331                                 source->changed = 1;
00332                                 unlock();
00333                             }
00334                         }
00335                         if ((num = SiButtonReleased (&Event)) != SI_NO_BUTTON)
00336                         {
00337                             /* process Spaceball button release event */
00338                             newBut = pow(2, num - 1);
00339                             for( NodeVector::iterator it = nodes.begin(); it != nodes.end(); it++ )
00340                             {
00341                                 lock();
00342                                 SpaceMouseSource * source = (SpaceMouseSource *)(*it);
00343                                 source->tmpEvent.getButton() ^= newBut;
00344                                 source->changed = 1;
00345                                 unlock();
00346                             }
00347                         }
00348                     }
00349 
00350                     handled = SPW_TRUE;              /* spaceball event handled */
00351                 }
00352 
00353                 /* not a Spaceball event, let windows handle it */
00354                 if (handled == SPW_FALSE)
00355                 {
00356                     TranslateMessage( &msg );
00357                     DispatchMessage( &msg );
00358                 }
00359             }
00360         }
00361     }
00362 
00363 } // namespace ot
00364 
00365 #else
00366 #pragma message(">>> no space mouse support")
00367 #endif
00368 
00369 /* 
00370  * ------------------------------------------------------------
00371  *   End of SpaceMouseModule.cxx
00372  * ------------------------------------------------------------
00373  *   Automatic Emacs configuration follows.
00374  *   Local Variables:
00375  *   mode:c++
00376  *   c-basic-offset: 4
00377  *   eval: (c-set-offset 'substatement-open 0)
00378  *   eval: (c-set-offset 'case-label '+)
00379  *   eval: (c-set-offset 'statement 'c-lineup-runin-statements)
00380  *   eval: (setq indent-tabs-mode nil)
00381  *   End:
00382  * ------------------------------------------------------------ 
00383  */

copyright (c) 2006 Graz University of Technology