Re: Magellan Space Mouse

New Message Reply Date view Thread view Subject view Author view

Joerg Wallmersperger (joerg++at++munich.sgi.com)
Tue, 26 Aug 1997 12:14:24 +0200


Hallo Herr Kociok,

I integrated the Space Mouse into the Performer demo 'complex.C'. You can
use either the mouse, Space Mouse or both. I attached the code for
'spacemouse.C' to this mail. All extra code for the Space Mouse is
enclosed in '#ifdef SPACEMOUSE...#endif' directives.

Viel Spass mit der Space Mouse

Joerg Wallmersperger

On Aug 21, 4:04pm, Norbert Kociok wrote:
} Subject: Magellan Space Mouse
} Hi Performers!
}
} I try to integrate the Magellan Space Mouse in a small performer
sample
} programm (stats.c). There you can navigate in the scene with the
} standard-mouse.
} In addition I want to navigate with the Magellan Space Mouse in this
} sample programm. I have make it so far that the Magellan Space Mouse is
} initialized and connected to the application-window.
}
} The problem is now where the XSelectInput-query (of the keybord and the
} standard-mouse) takes place.
}
} I can get started the programm and navigate with the standard-mouse,
but
} in this moment when I make actions with the Magellan Space Mouse the
} programm plunge with the error-message "Bus error".
}
} Regards,
}
} Norbert Kociok
} =======================================================================
} List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/
} Submissions: info-performer++at++sgi.com
} Admin. requests: info-performer-request++at++sgi.com
}-- End of excerpt from Norbert Kociok

-- 
Joerg Wallmersperger
Silicon Graphics GmbH, Am Hochacker 3, 85630 Grasbrunn
E-mail: joerg++at++munich.sgi.com
Tel.:   089-46108314 (US: 49.89.46108314)
Fax.:   089-46107314 (US: 49.89.46107314)
http://reality.sgi.com/joerg_munich

// // Copyright 1995, Silicon Graphics, Inc. // ALL RIGHTS RESERVED // // UNPUBLISHED -- Rights reserved under the copyright laws of the United // States. Use of a copyright notice is precautionary only and does not // imply publication or disclosure. // // U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND: // Use, duplication or disclosure by the Government is subject to restrictions // as set forth in FAR 52.227.19(c)(2) or subparagraph (c)(1)(ii) of the Rights // in Technical Data and Computer Software clause at DFARS 252.227-7013 and/or // in similar or successor clauses in the FAR, or the DOD or NASA FAR // Supplement. Contractor/manufacturer is Silicon Graphics, Inc., // 2011 N. Shoreline Blvd. Mountain View, CA 94039-7311. // // Permission to use, copy, modify, distribute, and sell this software // and its documentation for any purpose is hereby granted without // fee, provided that (i) the above copyright notices and this // permission notice appear in all copies of the software and related // documentation, and (ii) the name of Silicon Graphics may not be // used in any advertising or publicity relating to the software // without the specific, prior written permission of Silicon Graphics. // // THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, // EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY // WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. // // IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, // INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY // DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, // WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY // THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE // OR PERFORMANCE OF THIS SOFTWARE. // // // spacemouse.C // ------------ // // is based on the Performer example complex.C and includes support // for the spacemouse device. // // new command line options are // // -s translation_speed; > 1.0 more translation speed, 0..1 less speed // // For further information on spacemouse // devices watch out for // // http://dv.op.dlr.de/FF-DR-RS/SC // // If the compiler directives SPACEMOUSE and SPACEMOUSE_DEBUG are // omitted the program behaves like 'complex'. // // spacemouse code was added by Andreas Loesch <andreas++at++munich.sgi.com> // and Joerg Wallmersperger <joerg++at++munich.sgi.com> // // complex.C documentation: // ------------------------ // IRIS Performer example using cull and draw process callbacks. // Mouse and keyboard go through GL which is simpler than mixed // model (GLX), but does incur some overhead in the draw process. // X input handling is done in a forked event handling process. // // $Revision: 1.18 $ // $Date: 1996/12/18 03:49:02 $ // // Command-line options: // -b : norborder window // -f : full screen // -F : put X input handling in a forked process // -m procsplit : multiprocess mode // -w : write scene to file // // Run-time controls: // ESC-key: exits // F1-key: profile // Left-mouse: advance // Middle-mouse: stop // Right-mouse: retreat

#include <stdlib.h> #include <string.h> #include <math.h> #include <signal.h> // for sigset for forked X event handler process #include <getopt.h> // for cmdline handler #include <X11/keysym.h> #ifdef IRISGL #include <gl/device.h> #endif // GL type

#include <Performer/pf/pfNode.h> #include <Performer/pf/pfPipe.h> #include <Performer/pf/pfChannel.h>

#include <Performer/pr/pfLight.h>

#include <Performer/pfutil.h> #include <Performer/pfdu.h> #ifdef SPACEMOUSE #include <X11/extensions/XInput.h> #endif // // structure that resides in shared memory so that the // application, cull, and draw processes can access it.

typedef struct { pfPipeWindow *pw; int exitFlag; int inWindow, reset; float mouseX, mouseY; int winSizeX, winSizeY; int mouseButtons; pfCoord view, viewOrig; float accelRate; float sceneSize; int drawStats; int XInputInited; #ifdef SPACEMOUSE int spacemouse; pfCoord spacecoord; float smousefactor; #endif #ifdef STEREO int stereo; #endif } SharedData;

static SharedData *Shared;

#ifdef SPACEMOUSE int MagellanMotionEventType, MagellanButtonPressEventType, MagellanButtonReleaseEventType, MagellanMotionEventClass, MagellanButtonPressEventClass, MagellanButtonReleaseEventClass; XEventClass ListOfEventClass[3]; float transSpeed = 1.0; #endif #ifdef STEREO static float Iod = .2f; static float Converge = .02f; static float Fov = 45.f; static int FBAttrs[] = { PFFB_RGBA, PFFB_DOUBLEBUFFER, PFFB_STEREO, PFFB_DEPTH_SIZE, 23, PFFB_RED_SIZE, 1, PFFB_STENCIL_SIZE, 1, None, }; #endif // // APP process variables

// for configuring multi-process static int ProcSplit = PFMP_DEFAULT; // write out scene upon read-in - uses pfDebugPrint static int WriteScene = 0; static int FullScreen = 0; static int WinType = PFPWIN_TYPE_X; static int NoBorder = 0; static int ForkedXInput = 0; char ProgName[PF_MAXSTRING]; // light source created and updated in DRAW-process static pfLight *Sun;

static void CullChannel(pfChannel *chan, void *data); static void DrawChannel(pfChannel *chan, void *data); static void OpenPipeWin(pfPipeWindow *pw); static void UpdateView(void); static void GetGLInput(void); static void InitXInput(pfWSConnection dsp); static void DoXInput(void); static void GetXInput(Display *dsp); static void Usage(void); #ifdef SPACEMOUSE static void initSpaceMouse(void); #endif

// // Usage() -- print usage advice and exit. This procedure // is executed in the application process.

static void Usage (void) { pfNotify(PFNFY_FATAL, PFNFY_USAGE, "\ Usage: %s [-s translation_speed] [-m procSplit] [-f] [-F] [-b]\ [-w] [file.ext ...]\n", ProgName); exit(1); }

// // docmdline() -- use getopt to get command-line arguments, // executed at the start of the application process.

static int docmdline(int argc, char *argv[]) { int opt; strcpy(ProgName, argv[0]); // process command-line arguments while ((opt = getopt(argc, argv, "s:fFbm:wxp:?")) != -1) { switch (opt) { case 'f': FullScreen = 1; break; case 'F': ForkedXInput = 1; break; case 'm': case 'p': ProcSplit = atoi(optarg); break; case 'w': WriteScene = 1; break; case 'x': WinType &= ~(PFPWIN_TYPE_X); break; case 'b': NoBorder ^= 1; break; #ifdef SPACEMOUSE case 's': transSpeed = atof(optarg); break; #endif #ifdef STEREO case 'i': /* get interocular distance */ Iod = atof(optarg); break; case 'c': /* set convergence ratio */ Converge = atof(optarg); break; case 'v': /* get field of view */ Fov = atof(optarg); break; #endif case '?': case 'h': Usage(); } } return optind; }

// // main() -- program entry point. this procedure // is executed in the application process.

int main (int argc, char *argv[]) { int arg; int found; pfPipe *p; pfBox bbox; float far = 10000.0f; float near = .1f; pfWSConnection dsp=NULL; #ifdef SPACEMOUSE pfMatrix mat1,mat2; static double thisTime = -1.0f; double prevTime; float deltaTime; #endif #ifdef STEREO unsigned int mask; int *leftArg, *rightArg; float halfNearWidth; float eyeAngle; pfVec3 xyzOffsets; pfVec3 hprOffsets; #endif arg = docmdline(argc, argv); pfInit(); // configure multi-process selection pfMultiprocess(ProcSplit); // allocate shared before fork()'ing parallel processes Shared = (SharedData*)pfMalloc(sizeof(SharedData), pfGetSharedArena()); Shared->inWindow = 0; Shared->reset = 0; Shared->exitFlag = 0; Shared->drawStats = 1; Shared->XInputInited = 0; // Load all loader DSO's before pfConfig() forks for (found = arg; found < argc; found++) pfdInitConverter(argv[found]);

// initiate multi-processing mode set in pfMultiprocess call // FORKs for Performer processes, CULL and DRAW, etc. happen here. pfConfig(); // configure pipes and windows p = pfGetPipe(0); Shared->pw = new pfPipeWindow(p); Shared->pw->setName("IRIS Performer"); Shared->pw->setWinType(WinType); if (NoBorder) Shared->pw->setMode(PFWIN_NOBORDER, 1); // Open and configure the GL window. Shared->pw->setConfigFunc(OpenPipeWin); Shared->pw->config(); if (FullScreen) Shared->pw->setFullScreen(); else Shared->pw->setOriginSize(0, 0, 300, 300); // set off the draw process to open windows and call init callbacks pfFrame(); // create forked XInput handling process // since the Shared pointer has already been initialized, that structure // will be visible to the XInput process. Nothing else created in the // application after this fork whose handles are not put in shared memory // (such as the database and channels) will be visible to the // XInput process. if (WinType & PFPWIN_TYPE_X) { pid_t fpid = 0; if (ForkedXInput) { if ((fpid = fork()) < 0) pfNotify(PFNFY_FATAL, PFNFY_SYSERR, "Fork of XInput process failed."); else if (fpid) pfNotify(PFNFY_NOTICE,PFNFY_PRINT,"XInput running in forked process %d", fpid); else if (!fpid) DoXInput(); } else { dsp = pfGetCurWSConnection(); } } // specify directories where geometry and textures exist if (!(getenv("PFPATH"))) pfFilePath( "." ":./data" ":../data" ":../../data" ":/usr/share/Performer/data" ); pfNotify(PFNFY_INFO, PFNFY_PRINT,"FilePath: %s\n", pfGetFilePath()); // load files named by command line arguments pfScene *scene = new pfScene(); for (found = 0; arg < argc; arg++) { pfNode *root; if ((root = pfdLoadFile(argv[arg])) != NULL) { scene->addChild(root); found++; } } // if no files successfully loaded, terminate program #if 0 if (!found) Usage(); #endif // Write out nodes in scene (for debugging) if (WriteScene) { FILE *fp; if (fp = fopen("scene.out", "w")) { pfPrint(scene, PFTRAV_SELF|PFTRAV_DESCEND, PFPRINT_VB_DEBUG, fp); fclose(fp); } else pfNotify(PFNFY_WARN, PFNFY_RESOURCE, "Could not open scene.out for debug printing."); } // determine extent of scene's geometry pfuTravCalcBBox(scene, &bbox); pfFrameRate(30.0f); pfPhase(PFPHASE_FREE_RUN); #ifdef STEREO

/* create a channel for each eye */ pfChannel *left = new pfChannel(p); pfChannel *chan = left; pfChannel *right = new pfChannel(p); left->attach(right); mask = left->getShare();

/* same viewport */ mask |= PFCHAN_VIEWPORT; left->setShare(mask); left->setTravFunc(PFTRAV_CULL, CullChannel); left->setTravFunc(PFTRAV_DRAW, DrawChannel); left->setScene(scene); left->setNearFar(0.1f, far);

/* set up data to distinguish between left and right eye */ leftArg = (int *)left->allocChanData(sizeof(int)); rightArg = (int *)right->allocChanData(sizeof(int));

*leftArg = 1; *rightArg = 0;

/* data never changes, so we only need to pass it once */ left->passChanData(); right->passChanData(); left->setFOV(45.f, -1.f);

/* set up offsets for left and right channels for stereo viewing */

/* both eyes look at same spot 1/2 way between eyes at fusion distance */ eyeAngle = PF_RAD2DEG( atanf(Iod *.5f /(Converge * (far - near) + near)));

/* left eye */ hprOffsets.set(-eyeAngle, 0.f, 0.f); xyzOffsets.set(-Iod/2.f, 0.f, 0.f); left->setViewOffsets(xyzOffsets, hprOffsets);

/* right eye */ hprOffsets.set(eyeAngle, 0.f, 0.f); xyzOffsets.set(Iod/2.f, 0.f, 0.f); right->setViewOffsets(xyzOffsets, hprOffsets); #else pfChannel *chan = new pfChannel(p); Shared->pw->addChan(chan); chan->setTravFunc(PFTRAV_CULL, CullChannel); chan->setTravFunc(PFTRAV_DRAW, DrawChannel); chan->setScene(scene); chan->setNearFar(near, far); // vertical FOV is matched to window aspect ratio chan->setFOV(45.0f, -1.0f); #endif // Create an earth/sky model that draws sky/ground/horizon // pfEarthSky *eSky = new pfEarthSky(); // eSky->setMode(PFES_BUFFER_CLEAR, PFES_SKY_GRND); // eSky->setAttr(PFES_GRND_HT, -10.0f); // chan->setESky(eSky); chan->setTravMode(PFTRAV_CULL, PFCULL_VIEW|PFCULL_GSET); if (found) { float sceneSize; // Set initial view to be "in front" of scene // view point at center of bbox Shared->view.xyz.add(bbox.min, bbox.max); Shared->view.xyz.scale(0.5f, Shared->view.xyz); // find max dimension sceneSize = bbox.max[PF_X] - bbox.min[PF_X]; sceneSize = PF_MAX2(sceneSize, bbox.max[PF_Y] - bbox.min[PF_Y]); sceneSize = PF_MAX2(sceneSize, bbox.max[PF_Z] - bbox.min[PF_Z]); sceneSize = PF_MIN2(sceneSize, 0.5f * far); Shared->sceneSize = sceneSize; // offset so all is visible Shared->view.xyz[PF_Y] -= sceneSize; Shared->view.xyz[PF_Z] += 0.25f*sceneSize; } else { Shared->view.xyz.set(0.0f, 0.0f, 100.0f); PFSET_VEC3(bbox.min, -5000.0f, -5000.0f, -1000000.0f); PFSET_VEC3(bbox.max, 5000.0f, 5000.0f, 10000000.0f); Shared->sceneSize = 10000.0f; } Shared->view.hpr.set(0.0f, 0.0f, 0.0f); chan->setView(Shared->view.xyz, Shared->view.hpr); PFCOPY_VEC3(Shared->viewOrig.xyz, Shared->view.xyz); PFCOPY_VEC3(Shared->viewOrig.hpr, Shared->view.hpr); #ifdef SPACEMOUSE Shared->smousefactor = transSpeed * Shared->sceneSize; #endif // main simulation loop while (!Shared->exitFlag) { // wait until next frame boundary pfSync(); pfFrame(); // Set view parameters for next frame UpdateView(); #ifndef SPACEMOUSE chan->setView(Shared->view.xyz, Shared->view.hpr); #else prevTime = thisTime; thisTime = pfGetTime(); if (prevTime > 0){ deltaTime = thisTime-prevTime; Shared->spacecoord.xyz.scale(deltaTime,Shared->spacecoord.xyz); Shared->spacecoord.hpr.scale(deltaTime,Shared->spacecoord.hpr); } mat1.makeCoord(&Shared->view); mat2.makeCoord(&Shared->spacecoord); mat1.preMult(mat2); chan->setViewMat(mat1); mat1.getOrthoCoord(&Shared->view); #endif // initiate traversal using current state if (!ForkedXInput) { if (!Shared->XInputInited) InitXInput(dsp); if (Shared->XInputInited) GetXInput(dsp); } } // terminate cull and draw processes (if they exist) pfExit(); // exit to operating system return 0; }

static void InitXInput(pfWSConnection dsp) { Window w; #ifdef SPACEMOUSE initSpaceMouse(); #endif /* wait for X Window to exist in Performer shared memory */ if (w = Shared->pw->getWSWindow()) { XSelectInput(dsp, w, PointerMotionMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask); XMapWindow(dsp, w); XFlush(dsp); Shared->XInputInited = 1; } }

// // DoXInput() runs an asychronous forked even handling process. // Shared memory structures can be read from this process // but NO performer calls that set any structures should be // issues by routines in this process.

void DoXInput(void) { // windows from draw should now exist so can attach X input handling // to the X window Display *dsp = pfGetCurWSConnection(); prctl(PR_TERMCHILD); // Exit when parent does sigset(SIGHUP, SIG_DFL); // Exit when sent SIGHUP by TERMCHILD InitXInput(dsp); while (1) { XEvent event; if (!Shared->XInputInited) InitXInput(dsp); if (Shared->XInputInited) { XPeekEvent(dsp, &event); GetXInput(dsp); } } }

// // UpdateView() updates the eyepoint based on the information // placed in shared memory by GetInput().

static void UpdateView(void) { static float speed = 0.0f; pfCoord *view = &Shared->view; float cp; float mx, my; static double thisTime = -1.0f; double prevTime; float deltaTime;

prevTime = thisTime; thisTime = pfGetTime();

if (prevTime < 0.0f) return;

if (!Shared->inWindow || Shared->reset) { speed = 0; Shared->reset = 0; Shared->accelRate = 0.1f * Shared->sceneSize; return; }

deltaTime = thisTime - prevTime; switch (Shared->mouseButtons) { case Button1Mask: /* LEFTMOUSE: faster forward or slower backward*/ case Button1Mask|Button2Mask: speed += Shared->accelRate * deltaTime; if (speed > Shared->sceneSize) speed = Shared->sceneSize; break; case Button3Mask: /* RIGHTMOUSE: faster backward or slower foreward*/ case Button3Mask|Button2Mask: speed -= Shared->accelRate * deltaTime; if (speed < -Shared->sceneSize) speed = -Shared->sceneSize; break; } if (Shared->mouseButtons) { mx = 2.0f * (Shared->mouseX / (float)Shared->winSizeX) - 1.0f; my = 2.0f * (Shared->mouseY / (float)Shared->winSizeY) - 1.0f; /* update view direction */ view->hpr[PF_H] -= mx * PF_ABS(mx) * 30.0f * deltaTime; view->hpr[PF_P] += my * PF_ABS(my) * 30.0f * deltaTime; #ifndef SPACEMOUSE view->hpr[PF_R] = 0.0f; #endif

/* update view position */ cp = cosf(PF_DEG2RAD(view->hpr[PF_P])); view->xyz[PF_X] += speed*sinf(-PF_DEG2RAD(view->hpr[PF_H]))*cp; view->xyz[PF_Y] += speed*cosf(-PF_DEG2RAD(view->hpr[PF_H]))*cp; view->xyz[PF_Z] += speed*sinf( PF_DEG2RAD(view->hpr[PF_P])); } else { speed = 0.0f; Shared->accelRate = 0.1f * Shared->sceneSize; } }

// // CullChannel() -- traverse the scene graph and generate a // display list for the draw process. This procedure is // executed in the CULL process.

static void CullChannel(pfChannel *, void *) { // // pfDrawGeoSet or other display listable Performer routines // could be invoked before or after pfCull() pfCull(); }

// // OpenPipeWin() -- create a win: setup the GL and IRIS Performer. // This procedure is executed in the DRAW process // (when there is a separate draw process).

static void OpenPipeWin(pfPipeWindow *pw) { #ifdef STEREO pw->setFBConfigAttrs(FBAttrs); #endif pw->open(); #ifdef STEREO pw->query(PFQWIN_STEREO, &Shared->stereo); if(Shared->stereo == PFQFTR_FALSE) pfNotify(PFNFY_NOTICE, PFNFY_RESOURCE, "Couldn't get a stereo window; using mono mode"); #endif #ifdef IRISGL if (!(WinType & PFPWIN_TYPE_X)) { // register events of note with event-queue manager qdevice(ESCKEY); qdevice(F1KEY); qdevice(GKEY); } #endif // GL type // create a light source in the "south-west" (QIII) Sun = new pfLight(); Sun->setPos(-0.3f, -0.3f, 1.0f, 0.0f); }

// // DrawChannel() -- draw a channel and read input queue. this // procedure is executed in the draw process (when there is a // separate draw process).

static void DrawChannel (pfChannel *channel, void *left) { // rebind light so it stays fixed in position Sun->on(); #ifdef STEREO /* which buffer to draw into ? */ if(Shared->stereo) { /* if not stereo, draw to left all the time */ if(*(int*)left) { #ifdef IRISGL leftbuffer(1); rightbuffer(0); #else glDrawBuffer(GL_BACK_LEFT); #endif } else { #ifdef IRISGL leftbuffer(0); rightbuffer(1); #else glDrawBuffer(GL_BACK_RIGHT); #endif #endif /*STEREO*/ } } // erase framebuffer and draw Earth-Sky model channel->clear(); // invoke Performer draw-processing for this frame pfDraw(); // draw Performer throughput statistics if (Shared->drawStats) channel->drawStats(); // read window origin and size (it may have changed) channel->getPWin()->getSize(&Shared->winSizeX, &Shared->winSizeY); #ifdef IRISGL // if (!(WinType & PFPWIN_TYPE_X)) GetGLInput(); #endif // GL type #ifdef STEREO if(!Shared->stereo) /* mono mode */ if(*(int*)left) /* add extra swap to draw both buffers */ (channel->getPWin())->swapBuffers(); #endif }

#ifdef IRISGL static void GetGLInput(void) { long x, y; long xo, yo; while (qtest()) { short value; int device = qread(&value); // only act on key-down transitions if (value) { switch (device) { // ESC-key signals end of simulation case ESCKEY: Shared->exitFlag = 1; break; // g-key and F1-key toggles channel-stats display case GKEY: case F1KEY: Shared->drawStats = !Shared->drawStats; break; } } } // read cursor position (may be outside our window) x = getvaluator(MOUSEX); y = getvaluator(MOUSEY); // IRIS GL - mouse pos in screen relative and focus management is not so good // so update cursor virtual position when cursor inside window getorigin(&xo, &yo); if (x >= xo && x < (xo + Shared->winSizeX) && y >= yo && y < (yo + Shared->winSizeY)) { Shared->inWindow = 1; Shared->mouseX = x - xo; Shared->mouseY = y - yo; Shared->mouseButtons = ((getbutton(LEFTMOUSE) ? Button1Mask : 0) | (getbutton(MIDDLEMOUSE) ? Button2Mask : 0) | (getbutton(RIGHTMOUSE) ? Button3Mask : 0)); } else Shared->inWindow = 0; } #endif // GL type

static void GetXInput(pfWSConnection dsp) { static int x=0, y=0; if (XEventsQueued(dsp, QueuedAfterFlush)) while (XEventsQueued(dsp, QueuedAlready)) { XEvent event; #ifdef SPACEMOUSE XDeviceButtonEvent *ButtonPtr; XDeviceMotionEvent *MotionPtr; #endif XNextEvent(dsp, &event); switch (event.type) { case ConfigureNotify: break; case FocusIn: Shared->inWindow = 1; break; case FocusOut: Shared->inWindow = 0; break; case MotionNotify: { XMotionEvent *motion_event = (XMotionEvent *) &event; x = motion_event->x; y = Shared->winSizeY - motion_event->y; } break; case ButtonPress: { XButtonEvent *button_event = (XButtonEvent *) &event; x = event.xbutton.x; y = Shared->winSizeY - event.xbutton.y; Shared->inWindow = 1; switch (button_event->button) { case Button1: Shared->mouseButtons |= Button1Mask; break; case Button2: Shared->mouseButtons |= Button2Mask; break; case Button3: Shared->mouseButtons |= Button3Mask; break; } } break; case ButtonRelease: { XButtonEvent *button_event = (XButtonEvent *) &event; switch (button_event->button) { case Button1: Shared->mouseButtons &= ~Button1Mask; break; case Button2: Shared->mouseButtons &= ~Button2Mask; break; case Button3: Shared->mouseButtons &= ~Button3Mask; break; } } break; case KeyPress: { char buf[100]; int rv; KeySym ks; rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0); switch(ks) { case XK_Escape: Shared->exitFlag = 1; exit(0); break; case XK_space: Shared->reset = 1; PFCOPY_VEC3(Shared->view.xyz, Shared->viewOrig.xyz); PFCOPY_VEC3(Shared->view.hpr, Shared->viewOrig.hpr); pfNotify(PFNFY_NOTICE, PFNFY_PRINT, "Reset"); break; case XK_g: Shared->drawStats = !Shared->drawStats; break; default: break; } } break; default: #ifdef SPACEMOUSE if (event.type == MagellanMotionEventType){ MotionPtr = (XDeviceMotionEvent *) &(event); if ( (MotionPtr->axes_count == 6) && (MotionPtr->first_axis == 0)){ Shared->spacecoord.xyz[0]=MotionPtr->axis_data[ 0 ] *(.001*Shared->smousefactor); Shared->spacecoord.xyz[1]=MotionPtr->axis_data[ 2 ] *(.001*Shared->smousefactor); Shared->spacecoord.xyz[2]=MotionPtr->axis_data[ 1 ] *(.001*Shared->smousefactor); Shared->spacecoord.hpr[0]=.1*MotionPtr->axis_data[ 4 ]; Shared->spacecoord.hpr[1]=.1*MotionPtr->axis_data[ 3 ]; Shared->spacecoord.hpr[2]=.1*MotionPtr->axis_data[ 5 ]; Shared->spacemouse=TRUE; #ifdef SPACEMOUSE_DEBUG printf("factor: %f spaceball motion: xyz: %f %f %f hpr: %f %f %f\n", Shared->smousefactor, Shared->spacecoord.xyz[0], Shared->spacecoord.xyz[1], Shared->spacecoord.xyz[2], Shared->spacecoord.hpr[0], Shared->spacecoord.hpr[1], Shared->spacecoord.hpr[2]); #endif

} } if (event.type == MagellanButtonPressEventType){ ButtonPtr = (XDeviceButtonEvent *) &(event); } if (event.type == MagellanButtonReleaseEventType){ ButtonPtr = (XDeviceButtonEvent *) &(event); } #endif break; }// switch } Shared->mouseX = x; Shared->mouseY = y; }

#ifdef SPACEMOUSE void initSpaceMouse() { int MagellanID, DeviceNumber, loop, c_class; XDeviceInfo *DeviceInfo; XDevice *Device; Window w; Display *dsp;

XAxisInfoPtr XAxisPtr; XAnyClassPtr XClassPtr; int axis, axes;

XExtensionVersion *ExtVersion;

XFeedbackState *MagellanFeedback; int FeedbackNumber;

w = Shared->pw->getWSWindow(); dsp = pfGetCurWSConnection(); ExtVersion = XGetExtensionVersion( dsp, "XInputExtension" ); if ( (ExtVersion == NULL) || ((int)ExtVersion == NoSuchExtension) ) { fprintf( stderr, "Cannot access X Input Extension. Exit ... \n"); exit( -1 ); }; printf("X Input Extension Version %d.%d \n", ExtVersion->major_version, ExtVersion->minor_version ); XFree( ExtVersion );

DeviceInfo = XListInputDevices( dsp, &DeviceNumber ); MagellanID = -1; for ( loop=0; loop<DeviceNumber; ++loop ) { printf("------------------------------------------------------------------------\n"); printf(" Type = %d \n", DeviceInfo[loop].type ); printf("Device Name = %s Type = %d Atom = %s \n", DeviceInfo[loop].name, DeviceInfo[loop].type, XGetAtomName(dsp,DeviceInfo[loop].type) ); printf(" Device Class(es) = %d Use = %s \n", DeviceInfo[loop].num_classes, DeviceInfo[loop].use ? "TRUE" : "FALSE" );

XClassPtr = (XAnyClassPtr) DeviceInfo[loop].inputclassinfo; for ( c_class=0; c_class<DeviceInfo[loop].num_classes; ++c_class ) { switch( XClassPtr->c_class ) { case 0: printf(" Keyboard Keycode Min = %d Max = %d Number of Keys = %d \n", ((XKeyInfo *)XClassPtr)->min_keycode, ((XKeyInfo *)XClassPtr)->max_keycode, ((XKeyInfo *)XClassPtr)->num_keys ); break;

case 1: printf(" Button(s) Number of Buttons = %d \n", ((XButtonInfo *)XClassPtr)->num_buttons ); break;

case 2: printf(" Valuator(s) Axes = %d Mode = %d Motion Buffer = %d \n", ((XValuatorInfo *)XClassPtr)->num_axes, ((XValuatorInfo *)XClassPtr)->mode, ((XValuatorInfo *)XClassPtr)->motion_buffer ); XAxisPtr = ((XValuatorInfo *)XClassPtr)->axes; axes = ((XValuatorInfo *)XClassPtr)->num_axes; for ( axis=0; axis<axes; ++axis ) { printf(" Valuator = %d Min = %d Max = %d Resolution = %d \n", axis+1, XAxisPtr->min_value, XAxisPtr->max_value, XAxisPtr->resolution ); ++XAxisPtr; }; break;

default: printf(" Class ID = %d Length = %d \n", XClassPtr->c_class, XClassPtr->length ); break; }; XClassPtr = (XAnyClassPtr) ((char *)XClassPtr+XClassPtr->length); }; };

for ( loop=0; loop<DeviceNumber; ++loop ) { if ( strcmp( DeviceInfo[loop].name, "MAGELLAN" ) == NULL || strcmp( DeviceInfo[loop].name, "magellan" ) == NULL ) { MagellanID = DeviceInfo[loop].id; break; }; }; if ( MagellanID == -1 ) { for ( loop=0; loop<DeviceNumber; ++loop ) { if ( strcmp( DeviceInfo[loop].name, "SPACEBALL" ) == NULL || strcmp( DeviceInfo[loop].name, "spaceball" ) == NULL ) MagellanID = DeviceInfo[loop].id; }; };

XFreeDeviceList( DeviceInfo ); printf("------------------------------------------------------------------------\n"); printf("\n\n");

if ( MagellanID == -1 ) { printf("Magellan X Input Extension. \nCan't find Magellan. Exit ... \n" ); exit( -1 ); } else printf("Magellan X Input Extension ID = %d \n", MagellanID );

Device = XOpenDevice( dsp, MagellanID ); if ( Device == 0 ) { printf("Magellan X Input Extension. \nCan't open Magellan. Exit ... \n" ); exit( -1 ); };

DeviceMotionNotify( Device, MagellanMotionEventType, MagellanMotionEventClass ); DeviceButtonPress( Device, MagellanButtonPressEventType, MagellanButtonPressEventClass ); DeviceButtonRelease( Device, MagellanButtonReleaseEventType, MagellanButtonReleaseEventClass );

printf("MotionNotify Type=%d Class=%d \n", MagellanMotionEventType, MagellanMotionEventClass ); printf("ButtonPress Type=%d Class=%d \n", MagellanButtonPressEventType, MagellanButtonPressEventClass ); printf("ButtonRelease Type=%d Class=%d \n", MagellanButtonReleaseEventType, MagellanButtonReleaseEventClass );

ListOfEventClass[0] = MagellanMotionEventClass; ListOfEventClass[1] = MagellanButtonPressEventClass; ListOfEventClass[2] = MagellanButtonReleaseEventClass;

XSelectExtensionEvent( dsp, w, ListOfEventClass, 3 );

MagellanFeedback = XGetFeedbackControl( dsp, Device, &FeedbackNumber ); printf("Magellan Feedback Number = %d \n", FeedbackNumber ); for ( loop=0; loop<FeedbackNumber; ++loop ) { printf("Feedback = %d Class = %d Length = %d ID = %d \n", loop+1, MagellanFeedback->c_class, MagellanFeedback->length, MagellanFeedback->id ); switch( MagellanFeedback->c_class ) { case KbdFeedbackClass: printf(" KbdFeedbackClass Bell Volume = %d Pitch = %d Duration = %d \n", ((XKbdFeedbackState *)MagellanFeedback)->percent, ((XKbdFeedbackState *)MagellanFeedback)->pitch, ((XKbdFeedbackState *)MagellanFeedback)->duration ); break;

case BellFeedbackClass: printf(" BellFeedbackClass Bell Volume = %d Pitch = %d Duration = %d \n", ((XBellFeedbackState *)MagellanFeedback)->percent, ((XBellFeedbackState *)MagellanFeedback)->pitch, ((XBellFeedbackState *)MagellanFeedback)->duration ); break;

case PtrFeedbackClass: printf(" PtrFeedbackClass \n"); break;

case IntegerFeedbackClass: printf(" IntegerFeedbackClass \n"); break;

case StringFeedbackClass: printf(" StringFeedbackClass \n"); break;

case LedFeedbackClass: printf(" LedFeedbackClass \n"); break;

default: printf(" Unkonw FeedbackClass \n"); } MagellanFeedback = (XFeedbackState *)((char *)MagellanFeedback+MagellanFeedback->length); } Shared->spacemouse=FALSE;

} #endif

#!smake -J 1 #-------------------------------------------------------------------# #-- Makefile for Performer/src/pguide/libpf/C++ directory --# #-------------------------------------------------------------------# #-- RCS version information --# #-- $Revision: 1.74 $ --# #-- $Date: 1997/06/06 11:30:05 $ --# #-------------------------------------------------------------------#

PFROOT ?= $(ROOT) NEED_MOTIF_LIBS = true include $(PFROOT)/usr/share/Performer/src/pfmakedefs

LCDEFS += -DSPACEMOUSE #-DSPACEMOUSE_DEBUG LCXXDEFS += -DSPACEMOUSE #-DSPACEMOUSE_DEBUG #-- targets are the executables TARGETS = \ spacemouse

OBJECTS = $(TARGETS:=.o)

include $(PFROOT)/usr/share/Performer/src/pfmakerules

======================================================================= List Archives, FAQ, FTP: http://www.sgi.com/Technology/Performer/ Submissions: info-performer++at++sgi.com Admin. requests: info-performer-request++at++sgi.com


New Message Reply Date view Thread view Subject view Author view

This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:55:47 PDT

This message has been cleansed for anti-spam protection. Replace '++at++' in any mail addresses with the '@' symbol.