///////////////////////////////////////////////////////// // startRendering // ///////////////////////////////////////////////////////// void GemMan :: startRendering() { if (!m_windowState) { error("GEM: Create window first!"); return; } if (m_rendering) return; logpost(NULL, 3, "GEM: Start rendering"); // set up all of the gemheads renderChain(gensym("__gem_render"), true); renderChain(gensym("__gem_render_osd"), true); m_rendering = 1; // if only single buffering then just return if (GemMan::m_buffer == 1) return; m_lastRenderTime = clock_getsystime(); render(NULL); }
///////////////////////////////////////////////////////// // stopRendering // ///////////////////////////////////////////////////////// void GemMan :: stopRendering() { if (!m_rendering) return; m_rendering = 0; clock_unset(s_clock); s_hit = 1; // clean out all of the gemheads renderChain(gensym("__gem_render"), false); renderChain(gensym("__gem_render_osd"), false); logpost(NULL, 3, "GEM: Stop rendering"); }
void GemMan :: render(void *) { int profiling=m_profile; t_symbol*chain1=gensym("__gem_render"); t_symbol*chain2=gensym("__gem_render_osd"); if(GemMan::pleaseDestroy)GemMan::destroyWindow(); if (!m_windowState)return; // are we profiling? double starttime=sys_getrealtime(); double stoptime=0; s_hit = 0; resetValues(); GemState currentState; float tickTime; // fill in the elapsed time if (m_buffer == 1) tickTime = 50.f; else tickTime = static_cast<float>(clock_gettimesince(m_lastRenderTime)); currentState.set(GemState::_TIMING_TICK, tickTime); m_lastRenderTime = clock_getsystime(); //test to see if stereo is supported //XXX maybe there is a better place to do this? GLboolean stereoWindowTest; glGetBooleanv (GL_STEREO, &stereoWindowTest); //if we're trying to do crystal glasses stereo but don't have a stereo window //disable stereo and post a warning if(m_stereo == 3 && !stereoWindowTest){ error("GEM: you've selected Crystal Glasses Stereo but your graphics card isn't set up for stereo, setting stereo=0"); m_stereo = 0; } else if(stereoWindowTest) { //if we're not doing crystal eyes stereo but our window is enabled to do stereo //select the back buffer for drawing glDrawBuffer(GL_BACK); } // if stereoscopic rendering switch (m_stereo) { case 1: // 2-screen stereo { int xSize = m_w / 2; int ySize = m_h; float xDivy = static_cast<float>(xSize) / static_cast<float>(ySize); // setup the left viewpoint glViewport(0, 0, xSize, ySize); // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(m_lookat[0] - m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render left view fillGemState(currentState); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 - m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); // setup the right viewpoint glViewport(xSize, 0, xSize, ySize); // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(m_lookat[0] + m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render right view fillGemState(currentState); tickTime=0; currentState.set(GemState::_TIMING_TICK, tickTime); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 + m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); if (GemMan::m_stereoLine){ // draw a line between the views glDisable(GL_LIGHTING); glViewport(0, 0, m_w, m_h); xDivy = static_cast<float>(m_w) / static_cast<float>(ySize); // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1, 20); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 4, 0, 0, 0, 0, 1, 0); glLineWidth(2.f); glColor3f(1.f, 1.f, 1.f); glBegin(GL_LINES); glVertex2f(0.f, -6.f); glVertex2f(0.f, 6.f); glEnd(); glLineWidth(1.0f); } } break; case 2: // color-stereo { int xSize = m_w; int ySize = m_h; float xDivy = static_cast<float>(xSize) / static_cast<float>(ySize); int left_color=0; // RED int right_color=1; // GREEN glClear(GL_COLOR_BUFFER_BIT & m_clear_mask); glClear(GL_DEPTH_BUFFER_BIT & m_clear_mask); glClear(GL_STENCIL_BUFFER_BIT & m_clear_mask); glClear(GL_ACCUM_BUFFER_BIT & m_clear_mask); // setup the left viewpoint switch (left_color){ case 1: glColorMask(GL_FALSE,GL_TRUE,GL_FALSE,GL_TRUE); break; case 2: glColorMask(GL_FALSE,GL_FALSE,GL_TRUE,GL_TRUE); break; case 0: default: glColorMask(GL_TRUE,GL_FALSE,GL_FALSE,GL_TRUE); } // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(m_lookat[0] - m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render left view fillGemState(currentState); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 - m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); // setup the right viewpoint glClear(GL_DEPTH_BUFFER_BIT & m_clear_mask); switch (right_color){ case 0: glColorMask(GL_TRUE,GL_FALSE,GL_FALSE,GL_TRUE); break; case 1: default: glColorMask(GL_FALSE,GL_TRUE,GL_FALSE, GL_TRUE); break; case 2: glColorMask(GL_FALSE,GL_FALSE,GL_TRUE,GL_TRUE); } // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(m_lookat[0] + m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render right view fillGemState(currentState); tickTime=0; currentState.set(GemState::_TIMING_TICK, tickTime); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 + m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); } break; case 3: // Crystal Eyes Stereo { int xSize = m_w; int ySize = m_h; float xDivy = static_cast<float>(xSize) / static_cast<float>(ySize); // setup the left viewpoint // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(m_lookat[0] - m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render left view fillGemState(currentState); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 - m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); // setup the right viewpoint glClear(GL_DEPTH_BUFFER_BIT & m_clear_mask); // setup the matrices glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(GemMan::m_perspect[0] * xDivy, GemMan::m_perspect[1] * xDivy, // left, right GemMan::m_perspect[2], GemMan::m_perspect[3], // bottom, top GemMan::m_perspect[4], GemMan::m_perspect[5]); // front, back glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_RIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(m_lookat[0] + m_stereoSep / 100.f, m_lookat[1], m_lookat[2], m_lookat[3], m_lookat[4], m_lookat[5] + m_stereoFocal, m_lookat[6], m_lookat[7], m_lookat[8]); // render right view fillGemState(currentState); tickTime=0; currentState.set(GemState::_TIMING_TICK, tickTime); renderChain(chain1, ¤tState); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0 + m_stereoSep / 100.f, 0, 4, 0, 0, 0 + m_stereoFocal, 0, 1, 0); renderChain(chain2, ¤tState); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); } break; default: // normal rendering { fillGemState(currentState); renderChain(chain1, ¤tState); // setup the matrices glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 4, 0, 0, 0, 0, 1, 0); renderChain(chain2, ¤tState); } } swapBuffers(); // are we profiling? stoptime=sys_getrealtime(); if (profiling>0) { double seconds = stoptime-starttime; if(seconds>0.f) { GemMan::fps = (1 / (seconds * 1000.f)) * 1000.f; } else { error("GEM: unable to profile"); } } // only keep going if no one set the s_hit (could be hit if scheduler gets // ahold of a stopRendering command) double deltime=s_deltime; if(profiling<0) { float spent=(stoptime-starttime)*1000; if(profiling<-1) { deltime-=spent; } else if(spent<deltime && spent>0.f) { deltime-=spent; } else { post("unable to annihiliate %f ms", spent); } if(deltime<0.){ logpost(NULL, 5, "negative delay time: %f", deltime); deltime=1.f; } } if (!s_hit && (0.0 != deltime)) clock_delay(s_clock, deltime); glReportError(); }
OVR_PUBLIC_FUNCTION(ovrResult) ovr_SubmitFrame(ovrSession session, long long frameIndex, const ovrViewScaleDesc* viewScaleDesc, ovrLayerHeader const * const * layerPtrList, unsigned int layerCount) { //ovrLayerType 2, 6 do not exists anymore. max layer count is 16 instead of 32 unsigned int trueLayerCount = 0; for (unsigned int i = 0;i < layerCount;i++) { if (layerPtrList[i] != NULL) { trueLayerCount++; } } if (trueLayerCount > 16) { trueLayerCount = 16; //ignore layer counts > 16 } ovrLayerHeader1_3** newlayers = (ovrLayerHeader1_3**)malloc(sizeof(ovrLayerHeader1_3*) * trueLayerCount); unsigned int np = 0; for (unsigned int i = 0;i < layerCount;i++) { const ovrLayerHeader* layer = layerPtrList[i]; if (layer == NULL) { continue; } if (layer->Type == ovrLayerType_EyeFov) { const ovrLayerEyeFov* oldelayer = (const ovrLayerEyeFov*)layer; ovrLayerEyeFov1_3 *elayer = (ovrLayerEyeFov1_3*)malloc(sizeof(ovrLayerEyeFov1_3)); //if both eyes use same swaptextureset if (oldelayer->ColorTexture[0] == oldelayer->ColorTexture[1]) { elayer->ColorTexture[0] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[0]); elayer->ColorTexture[1] = elayer->ColorTexture[0]; } else { elayer->ColorTexture[0] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[0]); elayer->ColorTexture[1] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[1]); } elayer->Fov[0].DownTan = oldelayer->Fov[0].DownTan; elayer->Fov[0].LeftTan = oldelayer->Fov[0].LeftTan; elayer->Fov[0].UpTan = oldelayer->Fov[0].UpTan; elayer->Fov[0].RightTan = oldelayer->Fov[0].RightTan; elayer->Fov[1].DownTan = oldelayer->Fov[1].DownTan; elayer->Fov[1].LeftTan = oldelayer->Fov[1].LeftTan; elayer->Fov[1].UpTan = oldelayer->Fov[1].UpTan; elayer->Fov[1].RightTan = oldelayer->Fov[1].RightTan; elayer->Header.Flags = oldelayer->Header.Flags; elayer->Header.Type = (ovrLayerType1_3)oldelayer->Header.Type; copyPoseR(&elayer->RenderPose[0], &oldelayer->RenderPose[0]); copyPoseR(&elayer->RenderPose[1], &oldelayer->RenderPose[1]); elayer->SensorSampleTime = oldelayer->SensorSampleTime; elayer->Viewport[0] = oldelayer->Viewport[0]; elayer->Viewport[1] = oldelayer->Viewport[1]; newlayers[np] = (ovrLayerHeader1_3*)elayer; } else if (layer->Type == ovrLayerType_EyeMatrix) { const ovrLayerEyeMatrix* oldelayer = (const ovrLayerEyeMatrix*)layer; ovrLayerEyeMatrix1_3 *elayer = (ovrLayerEyeMatrix1_3*)malloc(sizeof(ovrLayerEyeMatrix1_3)); //if both eyes use same swaptextureset if (oldelayer->ColorTexture[0] == oldelayer->ColorTexture[1]) { elayer->ColorTexture[0] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[0]); elayer->ColorTexture[1] = elayer->ColorTexture[0]; } else { elayer->ColorTexture[0] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[0]); elayer->ColorTexture[1] = renderChain((ovrSession1_3)session, oldelayer->ColorTexture[1]); } elayer->Matrix[0] = oldelayer->Matrix[0]; elayer->Matrix[1] = oldelayer->Matrix[1]; elayer->Header.Flags = oldelayer->Header.Flags; elayer->Header.Type = (ovrLayerType1_3)oldelayer->Header.Type; copyPoseR(&elayer->RenderPose[0], &oldelayer->RenderPose[0]); copyPoseR(&elayer->RenderPose[1], &oldelayer->RenderPose[1]); elayer->SensorSampleTime = oldelayer->SensorSampleTime; elayer->Viewport[0] = oldelayer->Viewport[0]; elayer->Viewport[1] = oldelayer->Viewport[1]; newlayers[np] = (ovrLayerHeader1_3*)elayer; } else if (layer->Type == ovrLayerType_Quad) { const ovrLayerQuad* oldelayer = (const ovrLayerQuad*)layer; ovrLayerQuad1_3 *elayer = (ovrLayerQuad1_3*)malloc(sizeof(ovrLayerQuad1_3)); elayer->Header.Type = ovrLayerType1_3_Quad; elayer->Header.Flags = layer->Flags; elayer->ColorTexture = renderChain((ovrSession1_3)session, oldelayer->ColorTexture); copyPoseR(&elayer->QuadPoseCenter, &oldelayer->QuadPoseCenter); elayer->QuadSize = oldelayer->QuadSize; newlayers[np] = (ovrLayerHeader1_3*)elayer; } else if (layer->Type == ovrLayerType_Disabled) { ovrLayerHeader1_3 *elayer = (ovrLayerHeader1_3*)malloc(sizeof(ovrLayerHeader1_3)); elayer->Flags = layer->Flags; elayer->Type = (ovrLayerType1_3)layer->Type; newlayers[np] = (ovrLayerHeader1_3*)elayer; } else { continue; //ignore unsupported layers } np++; if (np > 15) { break; } } ovrResult r = ovr_SubmitFrame1_3((ovrSession1_3)session, frameIndex, (const ovrViewScaleDesc1_3*)viewScaleDesc, newlayers, trueLayerCount); for (unsigned int i = 0;i < trueLayerCount;i++) { free(newlayers[i]); } free(newlayers); return r; }