/** * @brief initializeExperiment */ void initializeExperiment() { // MUST BE CALLED WITHIN A VALID OPENGL CONTEXT //Screen screen(SCREEN_WIDE_SIZE, SCREEN_WIDE_SIZE*SCREEN_HEIGHT/SCREEN_WIDTH, alignmentX, alignmentY, focalDistance ); screen.init(SCREEN_WIDE_SIZE, SCREEN_WIDE_SIZE*SCREEN_HEIGHT/SCREEN_WIDTH, alignmentX, alignmentY, focalDistance ); screen.setOffset(alignmentX,alignmentY); screen.setFocalDistance(focalDistance); cam.init(screen); // Initialize all the streams for file output eccetera parameters.loadParameterFile("C:/cncsvisiondata/parametersFiles/Fulvio/expMicroHeadMovements/parametersExpMicroHeadMovementsActive.txt"); // Initialize focal distance and interocular distance from parameter file focalDistance = parameters.get("FocalDistance"); interocularDistance = parameters.get("IOD"); infoDraw = (int)parameters.get("DrawInfo"); useCircularOcclusor = (int)parameters.get("UseCircularOcclusor"); // Initialize trials balance factors trial.init(parameters); trial.next(); // Base directory, full path string baseDir = parameters.find("BaseDir"); // Subject name string subjectName = parameters.find("SubjectName"); // Principal streams file string markersFileName = baseDir + "markersFile_MicroHeadMovementsActive_" + subjectName + ".txt"; string outputFileName = baseDir + "responseFile_MicroHeadMovementsActive_" + subjectName +".txt"; string timingFileName = baseDir + "timingFile_MicroHeadMovementsActive_" + subjectName + ".txt"; // Check for output file existence if ( !util::fileExists((outputFileName)) ) responseFile.open(outputFileName.c_str()); cerr << "File " << outputFileName << " loaded successfully" << endl; // Check for output markers file existence if ( !util::fileExists((markersFileName)) ) markersFile.open(markersFileName.c_str()); cerr << "File " << markersFileName << " loaded successfully" << endl; // Check for output timing file existence if ( !util::fileExists((timingFileName)) ) timingFile.open(( timingFileName ).c_str()); cerr << "File " << timingFileName << " opened successfully" << endl; // Write the response file header responseFile << "# SubjectName\tTrialNumber\tFocalDistance\tKeyPressed\tResponseTime\tfZWidth\tfSlant\tfTilt\tfStimAnchored" << endl; // Finished loading parameter files // Update the stimulus updateStimulus(); trialTimer.start(); globalTimer.start(); }
/** * @brief idle */ void idle() { // Update markers optotrak.updateMarkers(); markers = optotrak.getAllMarkers(); allVisiblePatch = isVisible(markers[1].p) && isVisible(markers[2].p) && isVisible(markers[3].p); allVisibleHead = isVisible(markers[17].p) && isVisible(markers[18].p) && allVisiblePatch; headEyeCoords.update(markers.at(1).p,markers.at(2).p,markers.at(3).p); if ( trialTimer.getElapsedTimeInMilliSec() >= parameters.get("WaitTime") && trialMode==BLACK_MODE ) { frame=0.0; trialMode++; trialTimer.start(); } if ( trialTimer.getElapsedTimeInMilliSec() >= parameters.get("ProbeTime") && trialMode==PROBE_MODE ) { frame=0.0; trialMode++; trialTimer.start(); } if ( trialTimer.getElapsedTimeInMilliSec() >= parameters.get("StimulusTime") && trialMode==STIMULUS_MODE ) { Beep(660,660); frame=0.0; trialMode=RESPONSE_MODE; trialTimer.start(); } markersFile << fixed << trialNumber << " " << headCalibrationDone << " " << trialMode << " " ; markersFile << setprecision(3) << ( isVisible(markers[1].p) ? markers[1].p.transpose() : junk ) << " " << ( isVisible(markers[2].p) ? markers[2].p.transpose() : junk ) << " " << ( isVisible(markers[3].p) ? markers[3].p.transpose() : junk ) << " " << ( isVisible(markers[17].p) ? markers[17].p.transpose() : junk ) << " " << ( isVisible(markers[18].p) ? markers[18].p.transpose() : junk ) << " " << ( isVisible(markers[18].p) ? markers[18].p.transpose() : junk ) << " " << ( isVisible(headEyeCoords.getLeftEye()) ? headEyeCoords.getLeftEye().transpose() : junk ) << " " << ( isVisible(headEyeCoords.getRightEye()) ? headEyeCoords.getRightEye().transpose() : junk ) << " " ; markersFile << setprecision(1) << trial.getCurrent().at("ZWidth") << " " << trial.getCurrent().at("Slant") << " " << trial.getCurrent().at("Tilt") << " " << trial.getCurrent().at("StimulusAnchored") << " " << endl; }
/** * @brief drawFixation */ void drawFixation() { double circleRadius = parameters.get("MaxCircleRadius"); // millimeters double zBoundary = parameters.get("MaxZOscillation"); // millimeters // Projection of view normal on the focal plane Vector3d directionOfSight = (headEyeCoords.getRigidStart().getFullTransformation().linear()*Vector3d(0,0,-1)).normalized(); Eigen::ParametrizedLine<double,3> lineOfSightRight = Eigen::ParametrizedLine<double,3>::Through( headEyeCoords.getRightEye() , headEyeCoords.getRightEye()+directionOfSight ); Eigen::Hyperplane<double,3> focalPlane = Eigen::Hyperplane<double,3>::Through( Vector3d(1,0,focalDistance), Vector3d(0,1,focalDistance),Vector3d(0,0,focalDistance) ); double lineOfSightRightDistanceToFocalPlane = lineOfSightRight.intersection(focalPlane); Vector3d opticalAxisToFocalPlaneIntersection = lineOfSightRightDistanceToFocalPlane *(directionOfSight)+ (headEyeCoords.getRightEye()); switch ( headCalibrationDone ) { case 1: { // STIM_FIXED stimulus at (0,0,focalDistance) glPushAttrib(GL_POINT_BIT); glColor3fv(glRed); glPointSize(5); glBegin(GL_POINTS); glVertex3d(0,0,focalDistance); glVertex3d(headEyeCoords.getRightEye().x(),headEyeCoords.getRightEye().y(),focalDistance); glEnd(); glPopAttrib(); break; } case 2: { // STIM_FIXED stimulus + projected points glPushAttrib( GL_ALL_ATTRIB_BITS ); glPointSize(5); glLineWidth(2); glBegin(GL_POINTS); glColor3fv(glRed); glVertex3d(0,0,focalDistance); glColor3fv(glBlue); glVertex3dv(opticalAxisToFocalPlaneIntersection.data()); glColor3fv(glWhite); glVertex3d(headEyeCoords.getRightEye().x(),headEyeCoords.getRightEye().y(),focalDistance); glEnd(); double r2EyeRight = pow(headEyeCoords.getRightEye().x(),2)+pow(headEyeCoords.getRightEye().y(),2); // Draw the calibration circle if ( pow(opticalAxisToFocalPlaneIntersection.x(),2)+pow(opticalAxisToFocalPlaneIntersection.y(),2) <= circleRadius*circleRadius && abs(headEyeCoords.getRightEye().z()) < zBoundary && r2EyeRight<circleRadius*circleRadius ) { readyToStart=true; drawCircle(circleRadius,0,0,focalDistance,glGreen); } else { drawCircle(circleRadius,0,0,focalDistance,glRed); } glPopAttrib(); break; } } }
/** * @brief initializeExperiment */ void initializeExperiment() { initStreams(); factors.init(parameters); factors.next(); generateSphereStimulus(factors.getCurrent().at("StimulusRadius") ); initProjectionScreen(factors.getCurrent().at("Distances")); vector<double> distances = util::str2num<double>(parameters.find("fDistances")," "); maxCoveredDistance = max(distances.begin(),distances.end()) - min(distances.begin(),distances.end()); selectedFinger = util::str2num<int>(parameters.find("SelectedFinger")); // For the rod initialization thetaRod = M_PI/180.0*parameters.get("RodLatitude"); phiRod = M_PI/180.0*parameters.get("RodLongitude"); r = parameters.get("RodRadius"); rodStart = visualStimCenter + r*Vector3d(sin(thetaRod)*cos(phiRod),cos(thetaRod),sin(thetaRod)*sin(phiRod)); rodEnd= visualStimCenter - r*Vector3d(sin(thetaRod)*cos(phiRod),cos(thetaRod),sin(thetaRod)*sin(phiRod)); }
/** * @brief updateStimulus */ void updateStimulus() { double stimSize = parameters.get("StimulusSize"); double stimPeriod = parameters.get("StimulusPeriod"); double zWidth = trial.getCurrent().at("ZWidth"); int nStimulusPoints = (int)(stimSize*stimSize*parameters.get("StimulusDensity")); // Generate the plane stimulus if (parameters.find("StimulusType")=="Plane") { stimulus.setDimensions(stimSize,stimSize,0.001); stimulus.setNpoints(nStimulusPoints); stimulus.setFluffiness(0.001); stimulus.compute(); } else if (parameters.find("StimulusType")=="Sinusoid") { stimulus.setDimensions(stimSize,stimSize,0.001); stimulus.setNpoints(nStimulusPoints); stimulus.setFluffiness(0.001); for (PointsRandIterator iter = stimulus.pointsRand.begin(); iter!=stimulus.pointsRand.end();++iter) { (*iter)->x = mathcommon::unifRand(-stimSize/2,stimSize/2); (*iter)->y = mathcommon::unifRand(-stimSize/2,stimSize/2); (*iter)->z = 0.5*zWidth*sin(((*iter)->x)/stimPeriod*M_PI); } } else { throw std::runtime_error("Wrong argument! Must be Sinusoid or Plane"); } // Generate the front stimulus stimDrawer.setSpheres(false); stimDrawer.setStimulus(&stimulus); stimDrawer.initList(&stimulus,glRed,parameters.get("PointsSize")); }
/** * @brief drawStimulus */ void drawStimulus() { ////////////////////////////// // Update stimuli double oscillationAmplitude=50.0; double oscillationPeriod=100.0; static double timeFrame=0.0; timeFrame+=1.0; if ( !trial.getCurrent().at("StimulusAnchored") ) { // FISSO glPushMatrix(); glLoadIdentity(); Vector3d translationFactor(0,0,focalDistance); double instantPlaneSlant = trial.getCurrent().at("Slant"); switch ( (int) trial.getCurrent().at("Tilt") ) { case 0: { glTranslated( translationFactor.x(), translationFactor.y(), translationFactor.z()); glRotated( -instantPlaneSlant ,0,1,0); glScaled(1/sin(toRadians( -90-trial.getCurrent().at("Slant"))),1,1); //backprojection phase break; } case 90: { glTranslated( translationFactor.x(), translationFactor.y(), translationFactor.z()); glRotated( -instantPlaneSlant ,1,0,0); glScaled(1,1/sin(toRadians( -90-trial.getCurrent().at("Slant") )),1); //backprojection phase break; } case 180: { glTranslated( translationFactor.x(), translationFactor.y(), translationFactor.z()); glRotated( -instantPlaneSlant ,0,1,0); glScaled(1/sin(toRadians( -90-trial.getCurrent().at("Slant") )),1,1); //backprojection phase break; } case 270: { glTranslated( translationFactor.x(), translationFactor.y(), translationFactor.z()); glRotated( -instantPlaneSlant ,1,0,0); glScaled(1,1/sin(toRadians( -90-trial.getCurrent().at("Slant") )),1); //backprojection phase break; } } glGetDoublev(GL_MODELVIEW_MATRIX,objectActiveTransformation.data()); stimDrawer.draw(); glPopMatrix(); } else { // ANCORATO glPushMatrix(); glLoadMatrixd( (headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(Vector3d(0,0,focalDistance))).data() ); glGetDoublev(GL_MODELVIEW_MATRIX,objectActiveTransformation.data()); stimDrawer.draw(); glPopMatrix(); } // Draw the occlusor if ( useCircularOcclusor ) { double maskRadius=parameters.get("CircularOcclusorRadius"); glPushMatrix(); glLoadIdentity(); Vector3d projCoords; if ( trial.getCurrent().at("StimulusAnchored") ) projCoords << project( (headEyeCoords.getRigidStart().getFullTransformation()*Translation3d(Vector3d(0,0,focalDistance))).translation() ); else projCoords << project( Vector3d(0,0,focalDistance) ); circleMask( projCoords.x(), projCoords.y(), maskRadius ); glPopMatrix(); } bool passiveMode=false; stimDrawer.projectStimulusPoints( objectActiveTransformation, headEyeCoords.getRigidStart().getFullTransformation(), cam, focalDistance, screen, eyeCalibration, passiveMode, true); }