DWORD WINAPI ProcessGazepointData(void *hfEyegazePort) /* This function executes a continuous loop to receive and process the */ /* gazepoint data from the Eyegaze System. This is the place in the */ /* program where the developer should put most of his custom real-time */ /* Eyegaze data processing functions. Presently, this function simply */ /* displays the gazepoint on the client monitor. The gazepoint data */ /* processing continues until the user stops it from the menu. */ { int iVis; // the number of the vision system producing the most recent sample /* Clear the screen. */ lct_clearscreen(BLACK); /* Start data flowing from the Eyegaze system. */ stEgControl.bTrackingActive = TRUE; /* Loop until the user selects "End" to end the eyegaze processing. */ for (EVER) { /* Get the eyegaze data for the next camera frame. */ iVis = EgGetData(&stEgControl); /* Adjust the gaze coordinates to accomodate the window offset. */ iIGaze = stEgControl.pstEgData->iIGaze - iWindowHorzOffset; iJGaze = stEgControl.pstEgData->iJGaze - iWindowVertOffset; /* Plot the gazepoint on the client monitor. */ PlotGazepoint(iIGaze, iJGaze, stEgControl.pstEgData->bGazeVectorFound); /* One option in the EgServer program allows eye images to be sent to */ /* the client. If this is enabled, the eye image events will come in */ /* through the EgGetEvent function. */ /* Check to see if there's an event waiting to be processed. */ { int iEvent; static char achBuffer[6000]; iEvent = EgGetEvent(&stEgControl, (void *)&achBuffer); // 060830 PLN removed if (iEvent != EG_EVENT_UPDATE_EYE_IMAGE) DisplayEyeImages(hdc, (struct _stEventEyeImage *)achBuffer, 0); } /* If the user requests a stop, */ if (bStopCommunications == TRUE) { /* Break out of the forever loop. */ break; } } /* The 2-PC interface requires you to switch bTrackingActive to FALSE, */ /* call EgGetData() one last time to stop the data transmission from */ /* the server. */ stEgControl.bTrackingActive = FALSE; iVis = EgGetData(&stEgControl); return 0; }
DWORD WINAPI GazeDemo(void *pvoid) { /* This function is the core of the Eyegaze application that is executed */ /* as a separate thread when the program starts. */ #define EG_BUFFER_LEN 60 /* The constant EG_BUFFER_LEN sets the */ /* number of past samples stored in */ /* its gazepoint data ring buffer. */ /* Assuming an Eyegaze sample rate of */ /* 60 Hz, the value 60 means that one */ /* second's worth of past Eyegaze data */ /* is always available in the buffer. */ /* The application can get up to 60 */ /* samples behind the Eyegaze image */ /* processing without losing eyetracking */ /* data. */ /* Demonstration Program variables: */ int iIGazeSmooth; /* smoothed values of the eyegaze */ /* coordinates (pixels) */ int iJGazeSmooth; int iVis; /* The vision system returning data */ int rc; /* Return code from EgInit function call */ /*---------------------------- Function Code -------------------------------*/ /* Calibrate to the Eyegaze user (test subject). */ /* Since an Eyegaze thread has not yet been started, execute the external */ /* Eyegaze Calibration program (CALIBRATE.EXE), which starts and terminates */ /* its own Eyegaze thread. */ /* (See discussion of alternative calibration calls in the Eyegaze System */ /* Programmer's Manual. NOTE: If using the double computer configuration, */ /* spawning the external CALIBRATE.EXE is not an option. EgCalibrate must */ /* be used. See Programmer's Manual) */ /* P_WAIT causes the calibration program to terminate before this program */ /* proceeds. */ //_spawnl(P_WAIT, "Calibrate.exe", "Calibrate.exe", NULL); /* Set the input control constants in stEgControl required for starting */ /* the Eyegaze thread. */ stEgControl.iNDataSetsInRingBuffer = EG_BUFFER_LEN; /* Tell Eyegaze the length of the Eyegaze */ /* data ring buffer */ stEgControl.bTrackingActive = FALSE; /* Tell Eyegaze not to begin image */ /* processing yet (so no past gazepoint */ /* data samples will have accumulated */ /* in the ring buffer when the tracking */ /* loop begins). */ stEgControl.bEgCameraDisplayActive = FALSE; /* Tell Eyegaze not to display the full */ /* camera image in a separate window. */ stEgControl.iScreenWidthPix = iScreenWidth; stEgControl.iScreenHeightPix = iScreenHeight; /* Tell the image processing software what */ /* the physical screen dimensions are */ /* in pixels. */ stEgControl.iEyeImagesScreenPos = 1; #if defined RUN_LOCALLY stEgControl.iCommType = EG_COMM_TYPE_LOCAL; /* We are calibrating on the local */ /* computer, not over a serial or TCP/IP */ /* link. */ #else stEgControl.iCommType = EG_COMM_TYPE_SOCKET; stEgControl.pszCommName = achIPAddress; #endif /* Create the Eyegaze image processing thread. */ rc = EgInit(&stEgControl); if (rc != 0) { _TCHAR achErrorText[120]; swprintf_s(achErrorText, _countof(achErrorText), _T("Error %i Initializing Eyegaze"), rc); MessageBox(NULL, achErrorText, _T("GazeDemo"), MB_ICONEXCLAMATION | MB_OK); } EgCalibrate2(&stEgControl, EG_CALIBRATE_NONDISABILITY_APP); /* Push the GazeDemo program window up into the upper right corner of the */ /* screen. */ SetWindowPos(hwndEyegaze, // handle to window HWND_TOP, // placement-order handle iScreenWidth-160, // horizontal position 0, // vertical position 160, // width 50, // height 0); // Flags /* Tell Eyegaze to start eyetracking, i.e. to begin image processing. */ /* Note: No eyetracking takes place until this flag is set to true, and */ /* eye image processing stops when this flag is reset to false. */ stEgControl.bTrackingActive = TRUE; /* Loop for ever until the program is terminated. */ for (EVER) { /*----------------------- Synchronize to Eyegaze --------------------------*/ /* This code keeps the GazeDemo loop synchronized with the real-time */ /* Eyegaze image processing, i.e. looping at 60 Hz, but insures that all */ /* gazepoint data samples are processed, even if the GazeDemo loop gets */ /* a little behind the real-time Eyegaze image processing. Data */ /* buffers allow the GazeDemo loop to process all past gazepoint data */ /* samples even if the loop falls up to EG_BUFFER_LEN samples behind */ /* real time. */ /* If the ring buffer has overflowed, */ if (stEgControl.iNBufferOverflow > 0) { /* The application program acts on data loss if necessary. */ // (appropriate application code) } /* The image processing software, running independently of this */ /* application, produces a new eyegaze data sample every 16.67 milli- */ /* seconds. If an unprocessed Eyegaze data sample is still available */ /* for processing, EgGetData() returns immediately, allowing the */ /* application to catch up with the Eyegaze image processing. If the */ /* next unprocessd sample has not yet arrived, EgGetData blocks until */ /* data is available and then returns. This call effectively puts the */ /* application to sleep until new Eyegaze data is available to be */ /* processed. */ iVis = EgGetData(&stEgControl); /*-------------------- Process Next Eyegaze Data Sample --------------------*/ /* Compute the smoothed gazepoint, averaging over the last 12 samples. */ SmoothGazepoint(stEgControl.pstEgData->bGazeVectorFound, stEgControl.pstEgData->iIGaze, stEgControl.pstEgData->iJGaze, &iIGazeSmooth, &iJGazeSmooth, 12); /* If the gazepoint was found this iteration, */ if (stEgControl.pstEgData->bGazeVectorFound == TRUE) { /* Move the mouse to the smoothed gazpoint location. */ mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, iIGazeSmooth*65535/iScreenWidth, iJGazeSmooth*65535/iScreenHeight, 0, 0); } } return 0; if (pvoid); // quiet the compiler. }