void DrawContext::updateTransforms( const AffineTransform3& head, const AffineTransform3& view, float eyeSeparation, float nearZ, float farZ) { DisplaySystem* ds = renderer->getDisplaySystem(); DisplayConfig& dcfg = ds->getDisplayConfig(); Vector3f pa = tile->bottomLeft; Vector3f pb = tile->bottomRight; Vector3f pc = tile->topLeft; if(tile->isHMD) { pa = head * pa; pb = head * pb; pc = head * pc; } // half eye separation float hes = eyeSeparation / 2; Vector3f pe = Vector3f::Zero(); switch(eye) { case EyeLeft: pe[0] = -hes; break; case EyeRight: pe[0] = hes; break; } // Transform eye with head position / orientation. After this, eye position // and tile coordinates are all in the same reference frame. if(dcfg.panopticStereoEnabled) { // CAVE2 SIMPLIFICATION: We are just interested in adjusting the observer yaw AffineTransform3 ht = AffineTransform3::Identity(); ht.translate(head.translation()); pe = ht.rotate( AngleAxis(-tile->yaw * Math::DegToRad, Vector3f::UnitY())) * pe; } else { pe = head * pe; } Vector3f vr = pb - pa; Vector3f vu = pc - pa; Vector3f vn = vr.cross(vu); Vector2f viewSize = viewMax - viewMin; // Update tile corners based on local view position and size pa = pa + vr * viewMin[0] + vu * viewMin[1]; pb = pa + vr * viewSize[0]; pc = pa + vu * viewSize[1]; vr.normalize(); vu.normalize(); vn.normalize(); // Compute the screen corner vectors. Vector3f va = pa - pe; Vector3f vb = pb - pe; Vector3f vc = pc - pe; // Find distance from eye to screen plane. //Vector3f tm = pe - pa; float d = -(vn.dot(va)); // Find the extent of the perpendicular projection. float l = vr.dot(va) * nearZ / d; float r = vr.dot(vb) * nearZ / d; float b = vu.dot(va) * nearZ / d; float t = vu.dot(vc) * nearZ / d; // Compute the projection matrix. Transform3 oax; oax.setIdentity(); oax(0,0) = 2 * nearZ / (r - l); oax(0,2) = (r + l) / (r - l); oax(1,1) = 2 * nearZ / (t - b); oax(1,2) = (t + b) / (t - b); oax(2,2) = - (farZ + nearZ) / (farZ - nearZ); oax(2,3) = - (2 * farZ * nearZ) / (farZ - nearZ); oax(3,2) = - 1; oax(3,3) = 0; projection = oax; // Compute the view matrix. The view matrix has two main components: // - the navigational component given by myViewTransform, converts points // from world space to 'camera' space (origin is determined by camera position / orientation) // - the screen plane component, given by the current tile orientation and head position. // this component converts points from camera space to screen-oriented eye space // (that is, origin is at eye position, and orientation is determined by the screen plane, // with positive Y being screen up vector, X being screen right vector and Z being screen normal) AffineTransform3 newBasis; newBasis.setIdentity(); newBasis.data()[0] = vr[0]; newBasis.data()[1] = vu[0]; newBasis.data()[2] = vn[0]; newBasis.data()[4] = vr[1]; newBasis.data()[5] = vu[1]; newBasis.data()[6] = vn[1]; newBasis.data()[8] = vr[2]; newBasis.data()[9] = vu[2]; newBasis.data()[10] = vn[2]; newBasis = newBasis.translate(-pe); modelview = newBasis * view; }
void displayCallback(void) { static float lt = 0.0f; static uint64 frame = 0; GlutDisplaySystem* ds = (GlutDisplaySystem*)SystemManager::instance()->getDisplaySystem(); Engine* as = ds->getApplicationServer(); Renderer* ac = ds->getApplicationClient(); // Compute dt. float t = (float)((double)clock() / CLOCKS_PER_SEC); UpdateContext uc; uc.dt = t - lt; lt = t; as->update(uc); //ac->update(uc); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // setup the context viewport. DrawContext dc; DisplayTileConfig dtc(ds->getDisplayConfig()); dtc.device = 0; //dtc.index = Vector2i::Zero(); dtc.offset = Vector2i::Zero(); dtc.pixelSize = ds->getCanvasSize(); dc.frameNum = frame++; dc.tile = &dtc; dc.gpuContext = ds->getGpuContext(); ds->updateProjectionMatrix(); Camera* cam = Engine::instance()->getDefaultCamera(); // Push observer matrix. glPushMatrix(); AffineTransform3 mat = cam->getViewTransform(); glLoadIdentity(); glLoadMatrixd(mat.data()); dc.viewport = Rect(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)); glGetDoublev( GL_MODELVIEW_MATRIX, dc.modelview.data() ); glGetDoublev( GL_PROJECTION_MATRIX, dc.projection.data() ); //dc.drawBuffer = ds->getFrameBuffer(); // Process events. ServiceManager* im = SystemManager::instance()->getServiceManager(); int av = im->getAvailableEvents(); if(av != 0) { Event evts[OMICRON_MAX_EVENTS]; im->getEvents(evts, ServiceManager::MaxEvents); // Dispatch events to application server. for( int evtNum = 0; evtNum < av; evtNum++) { as->handleEvent(evts[evtNum]); } } dc.eye = DrawContext::EyeCyclop; dc.task = DrawContext::SceneDrawTask; ac->draw(dc); dc.task = DrawContext::OverlayDrawTask; ac->draw(dc); glPopMatrix(); //glFlush(); glutPostRedisplay(); // poll the input manager for new events. im->poll(); if(SystemManager::instance()->isExitRequested()) { exit(0); } }