void Pi::MainLoop() { double time_player_died = 0; #ifdef MAKING_VIDEO Uint32 last_screendump = SDL_GetTicks(); int dumpnum = 0; #endif /* MAKING_VIDEO */ #if WITH_DEVKEYS Uint32 last_stats = SDL_GetTicks(); int frame_stat = 0; int phys_stat = 0; char fps_readout[256]; memset(fps_readout, 0, sizeof(fps_readout)); #endif int MAX_PHYSICS_TICKS = Pi::config->Int("MaxPhysicsCyclesPerRender"); if (MAX_PHYSICS_TICKS <= 0) MAX_PHYSICS_TICKS = 4; double currentTime = 0.001 * double(SDL_GetTicks()); double accumulator = Pi::game->GetTimeStep(); Pi::gameTickAlpha = 0; while (Pi::game) { double newTime = 0.001 * double(SDL_GetTicks()); Pi::frameTime = newTime - currentTime; if (Pi::frameTime > 0.25) Pi::frameTime = 0.25; currentTime = newTime; accumulator += Pi::frameTime * Pi::game->GetTimeAccelRate(); const float step = Pi::game->GetTimeStep(); if (step > 0.0f) { int phys_ticks = 0; while (accumulator >= step) { if (++phys_ticks >= MAX_PHYSICS_TICKS) { accumulator = 0.0; break; } game->TimeStep(step); accumulator -= step; } // rendering interpolation between frames: don't use when docked int pstate = Pi::game->GetPlayer()->GetFlightState(); if (pstate == Ship::DOCKED || pstate == Ship::DOCKING) Pi::gameTickAlpha = 1.0; else Pi::gameTickAlpha = accumulator / step; #if WITH_DEVKEYS phys_stat += phys_ticks; #endif } else { // paused } frame_stat++; // fuckadoodledoo, did the player die? if (Pi::player->IsDead()) { if (time_player_died > 0.0) { if (Pi::game->GetTime() - time_player_died > 8.0) { Pi::SetView(0); Pi::TombStoneLoop(); Pi::EndGame(); break; } } else { Pi::game->SetTimeAccel(Game::TIMEACCEL_1X); Pi::deathView->Init(); Pi::SetView(Pi::deathView); time_player_died = Pi::game->GetTime(); } } Pi::renderer->BeginFrame(); Pi::renderer->SetTransform(matrix4x4f::Identity()); /* Calculate position for this rendered frame (interpolated between two physics ticks */ // XXX should this be here? what is this anyway? for (Space::BodyIterator i = game->GetSpace()->BodiesBegin(); i != game->GetSpace()->BodiesEnd(); ++i) { (*i)->UpdateInterpTransform(Pi::GetGameTickAlpha()); } game->GetSpace()->GetRootFrame()->UpdateInterpTransform(Pi::GetGameTickAlpha()); currentView->Update(); currentView->Draw3D(); // XXX HandleEvents at the moment must be after view->Draw3D and before // Gui::Draw so that labels drawn to screen can have mouse events correctly // detected. Gui::Draw wipes memory of label positions. Pi::HandleEvents(); // hide cursor for ship control. SetMouseGrab(Pi::MouseButtonState(SDL_BUTTON_RIGHT)); Pi::renderer->EndFrame(); Gui::Draw(); #if WITH_DEVKEYS if (Pi::showDebugInfo) { Gui::Screen::EnterOrtho(); Gui::Screen::PushFont("ConsoleFont"); Gui::Screen::RenderString(fps_readout, 0, 0); Gui::Screen::PopFont(); Gui::Screen::LeaveOrtho(); } #endif Pi::renderer->SwapBuffers(); // game exit or failed load from GameMenuView will have cleared // Pi::game. we can't continue. if (!Pi::game) return; if (Pi::game->UpdateTimeAccel()) accumulator = 0; // fix for huge pauses 10000x -> 1x if (!Pi::player->IsDead()) { // XXX should this really be limited to while the player is alive? // this is something we need not do every turn... if (!config->Int("DisableSound")) AmbientSounds::Update(); StarSystem::ShrinkCache(); } cpan->Update(); musicPlayer.Update(); #if WITH_DEVKEYS if (Pi::showDebugInfo && SDL_GetTicks() - last_stats > 1000) { size_t lua_mem = Lua::manager->GetMemoryUsage(); int lua_memB = int(lua_mem & ((1u << 10) - 1)); int lua_memKB = int(lua_mem >> 10) % 1024; int lua_memMB = int(lua_mem >> 20); Pi::statSceneTris += LmrModelGetStatsTris(); snprintf( fps_readout, sizeof(fps_readout), "%d fps (%.1f ms/f), %d phys updates, %d triangles, %.3f M tris/sec, %d terrain vtx/sec, %d glyphs/sec\n" "Lua mem usage: %d MB + %d KB + %d bytes", frame_stat, (1000.0/frame_stat), phys_stat, Pi::statSceneTris, Pi::statSceneTris*frame_stat*1e-6, GeoSphere::GetVtxGenCount(), Text::TextureFont::GetGlyphCount(), lua_memMB, lua_memKB, lua_memB ); frame_stat = 0; phys_stat = 0; Text::TextureFont::ClearGlyphCount(); GeoSphere::ClearVtxGenCount(); if (SDL_GetTicks() - last_stats > 1200) last_stats = SDL_GetTicks(); else last_stats += 1000; } Pi::statSceneTris = 0; LmrModelClearStatsTris(); #endif #ifdef MAKING_VIDEO if (SDL_GetTicks() - last_screendump > 50) { last_screendump = SDL_GetTicks(); std::string fname = stringf(Lang::SCREENSHOT_FILENAME_TEMPLATE, formatarg("index", dumpnum++)); Screendump(fname.c_str(), GetScrWidth(), GetScrHeight()); } #endif /* MAKING_VIDEO */ }
void Pi::MainLoop() { StartGame(); Uint32 last_stats = SDL_GetTicks(); int frame_stat = 0; int phys_stat = 0; char fps_readout[128]; double time_player_died = 0; #ifdef MAKING_VIDEO Uint32 last_screendump = SDL_GetTicks(); int dumpnum = 0; #endif /* MAKING_VIDEO */ double currentTime = 0.001 * (double)SDL_GetTicks(); double accumulator = Pi::GetTimeStep(); Pi::gameTickAlpha = 0; memset(fps_readout, 0, sizeof(fps_readout)); while (isGameStarted) { double newTime = 0.001 * (double)SDL_GetTicks(); Pi::frameTime = newTime - currentTime; if (Pi::frameTime > 0.25) Pi::frameTime = 0.25; currentTime = newTime; accumulator += Pi::frameTime * GetTimeAccel(); const float step = Pi::GetTimeStep(); if (step) { while (accumulator >= step) { Space::TimeStep(step); gameTime += step; phys_stat++; accumulator -= step; } Pi::gameTickAlpha = accumulator / step; } else { // paused } if (frame_stat == 0) { // called not more than once per second PiLuaModules::UpdateOncePerRealtimeSecond(); } frame_stat++; Render::PrepareFrame(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Calculate position for this rendered frame (interpolated between two physics ticks */ for (std::list<Body*>::iterator i = Space::bodies.begin(); i != Space::bodies.end(); ++i) { (*i)->UpdateInterpolatedTransform(Pi::GetGameTickAlpha()); } Space::rootFrame->UpdateInterpolatedTransform(Pi::GetGameTickAlpha()); currentView->Draw3D(); // XXX HandleEvents at the moment must be after view->Draw3D and before // Gui::Draw so that labels drawn to screen can have mouse events correctly // detected. Gui::Draw wipes memory of label positions. Pi::HandleEvents(); // hide cursor for ship control. if (Pi::MouseButtonState(3)) { SDL_ShowCursor(0); SDL_WM_GrabInput(SDL_GRAB_ON); // SDL_SetRelativeMouseMode(true); } else { SDL_ShowCursor(1); SDL_WM_GrabInput(SDL_GRAB_OFF); // SDL_SetRelativeMouseMode(false); } Render::PostProcess(); Gui::Draw(); //#ifdef DEBUG if (Pi::showDebugInfo) { Gui::Screen::EnterOrtho(); glColor3f(1,1,1); Gui::Screen::RenderString(fps_readout, 0, 0); Gui::Screen::LeaveOrtho(); } //#endif /* DEBUG */ glError(); Render::SwapBuffers(); //if (glGetError()) printf ("GL: %s\n", gluErrorString (glGetError ())); int timeAccel = Pi::requestedTimeAccelIdx; if (Pi::player->GetFlightState() == Ship::FLYING) { // check we aren't too near to objects for timeaccel // /* for (std::list<Body*>::iterator i = Space::bodies.begin(); i != Space::bodies.end(); ++i) { if ((*i) == Pi::player) continue; if ((*i)->IsType(Object::HYPERSPACECLOUD)) continue; vector3d toBody = Pi::player->GetPosition() - (*i)->GetPositionRelTo(Pi::player->GetFrame()); double dist = toBody.Length(); double rad = (*i)->GetBoundingRadius(); if (dist < 1000.0) { timeAccel = std::min(timeAccel, 1); } else if (dist < std::min(rad+0.0001*AU, rad*1.1)) { timeAccel = std::min(timeAccel, 2); } else if (dist < std::min(rad+0.001*AU, rad*5.0)) { timeAccel = std::min(timeAccel, 3); } else if (dist < std::min(rad+0.01*AU,rad*10.0)) { timeAccel = std::min(timeAccel, 4); } else if (dist < std::min(rad+0.1*AU, rad*1000.0)) { timeAccel = std::min(timeAccel, 5); } } */ } if (timeAccel != Pi::GetTimeAccelIdx()) { Pi::SetTimeAccel(timeAccel); accumulator = 0; // fix for huge pauses 10000x -> 1x } // fuckadoodledoo, did the player die? if (Pi::player->IsDead()) { if (time_player_died) { if (Pi::GetGameTime() - time_player_died > 8.0) { Sound::DestroyAllEvents(); Pi::TombStoneLoop(); break; } } else { Pi::SetTimeAccel(1); Pi::cpan->HideAll(); Pi::SetView(static_cast<View*>(Pi::worldView)); Pi::player->Disable(); time_player_died = Pi::GetGameTime(); } } else { // this is something we need not do every turn... AmbientSounds::Update(); StarSystem::ShrinkCache(); } cpan->Update(); currentView->Update(); if (SDL_GetTicks() - last_stats > 1000) { Pi::statSceneTris += LmrModelGetStatsTris(); snprintf(fps_readout, sizeof(fps_readout), "%d fps, %d phys updates, %d triangles, %.3f M tris/sec", frame_stat, phys_stat, Pi::statSceneTris, Pi::statSceneTris*frame_stat*1e-6); frame_stat = 0; phys_stat = 0; last_stats += 1000; } Pi::statSceneTris = 0; LmrModelClearStatsTris(); #ifdef MAKING_VIDEO if (SDL_GetTicks() - last_screendump > 50) { last_screendump = SDL_GetTicks(); char buf[256]; snprintf(buf, sizeof(buf), "screenshot%08d.tga", dumpnum++); Screendump(buf); } #endif /* MAKING_VIDEO */ } }
void Viewer::MainLoop() { Uint32 lastTurd = SDL_GetTicks(); Uint32 t = SDL_GetTicks(); int numFrames = 0; Uint32 lastFpsReadout = SDL_GetTicks(); g_campos = vector3f(0.0f, 0.0f, m_cmesh->GetBoundingRadius()); g_camorient = matrix4x4f::Identity(); matrix4x4f modelRot = matrix4x4f::Identity(); printf("Geom tree build in %dms\n", SDL_GetTicks() - t); Render::State::SetZnearZfar(1.0f, 10000.0f); for (;;) { PollEvents(); Render::PrepareFrame(); if (g_keyState[SDLK_LSHIFT] || g_keyState[SDLK_RSHIFT]) { if (g_keyState[SDLK_UP]) g_camorient = g_camorient * matrix4x4f::RotateXMatrix(g_frameTime); if (g_keyState[SDLK_DOWN]) g_camorient = g_camorient * matrix4x4f::RotateXMatrix(-g_frameTime); if (g_keyState[SDLK_LEFT]) g_camorient = g_camorient * matrix4x4f::RotateYMatrix(-g_frameTime); if (g_keyState[SDLK_RIGHT]) g_camorient = g_camorient * matrix4x4f::RotateYMatrix(g_frameTime); if (g_mouseButton[3]) { float rx = 0.01f*g_mouseMotion[1]; float ry = 0.01f*g_mouseMotion[0]; g_camorient = g_camorient * matrix4x4f::RotateXMatrix(rx); g_camorient = g_camorient * matrix4x4f::RotateYMatrix(ry); if (g_mouseButton[1]) { g_campos = g_campos - g_camorient * vector3f(0.0f,0.0f,1.0f) * 0.01 * m_model->GetDrawClipRadius(); } } } else { if (g_keyState[SDLK_UP]) modelRot = modelRot * matrix4x4f::RotateXMatrix(g_frameTime); if (g_keyState[SDLK_DOWN]) modelRot = modelRot * matrix4x4f::RotateXMatrix(-g_frameTime); if (g_keyState[SDLK_LEFT]) modelRot = modelRot * matrix4x4f::RotateYMatrix(-g_frameTime); if (g_keyState[SDLK_RIGHT]) modelRot = modelRot * matrix4x4f::RotateYMatrix(g_frameTime); if (g_mouseButton[3]) { float rx = 0.01f*g_mouseMotion[1]; float ry = 0.01f*g_mouseMotion[0]; modelRot = modelRot * matrix4x4f::RotateXMatrix(rx); modelRot = modelRot * matrix4x4f::RotateYMatrix(ry); } } if (g_keyState[SDLK_EQUALS]) g_campos = g_campos - g_camorient * vector3f(0.0f,0.0f,1.0f); if (g_keyState[SDLK_MINUS]) g_campos = g_campos + g_camorient * vector3f(0.0f,0.0f,1.0f); if (g_keyState[SDLK_PAGEUP]) g_campos = g_campos - g_camorient * vector3f(0.0f,0.0f,1.0f); if (g_keyState[SDLK_PAGEDOWN]) g_campos = g_campos + g_camorient * vector3f(0.0f,0.0f,1.0f); // geom->MoveTo(modelRot, vector3d(0.0,0.0,0.0)); glMatrixMode(GL_PROJECTION); glLoadIdentity(); float fracH = g_height / (float)g_width; glFrustum(-1, 1, -fracH, fracH, 1.0f, 10000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetSbreParams(); int beforeDrawTriStats = LmrModelGetStatsTris(); if (g_renderType == 0) { glPushAttrib(GL_ALL_ATTRIB_BITS); matrix4x4f m = g_camorient.InverseOf() * matrix4x4f::Translation(-g_campos) * modelRot.InverseOf(); if (g_doBenchmark) { for (int i=0; i<1000; i++) m_model->Render(m, ¶ms); } else { m_model->Render(m, ¶ms); } glPopAttrib(); } else if (g_renderType == 1) { glPushMatrix(); matrix4x4f m = g_camorient.InverseOf() * matrix4x4f::Translation(-g_campos) * modelRot.InverseOf(); glMultMatrixf(&m[0]); render_coll_mesh(m_cmesh); glPopMatrix(); } else { matrix4x4f tran = modelRot * g_camorient;//.InverseOf(); vector3d forward = tran * vector3d(0.0,0.0,-1.0); vector3d up = tran * vector3d(0.0,1.0,0.0); raytraceCollMesh(modelRot * g_campos, up, forward, m_space); } Render::State::UseProgram(0); Render::UnbindAllBuffers(); { char buf[128]; Aabb aabb = m_cmesh->GetAabb(); snprintf(buf, sizeof(buf), "%d triangles, collision mesh size: %.1fx%.1fx%.1f (radius %.1f)", (g_renderType == 0 ? LmrModelGetStatsTris() - beforeDrawTriStats : m_cmesh->m_numTris), aabb.max.x-aabb.min.x, aabb.max.y-aabb.min.y, aabb.max.z-aabb.min.z, aabb.GetBoundingRadius()); m_trisReadout->SetText(buf); } Render::PostProcess(); Gui::Draw(); glError(); Render::SwapBuffers(); numFrames++; g_frameTime = (SDL_GetTicks() - lastTurd) * 0.001f; lastTurd = SDL_GetTicks(); if (SDL_GetTicks() - lastFpsReadout > 1000) { int numTris = LmrModelGetStatsTris(); LmrModelClearStatsTris(); printf("%d fps, %.3f Million tris/sec\n", numFrames, numTris/1000000.0f); numFrames = 0; lastFpsReadout = SDL_GetTicks(); } //space->Collide(onCollision); } }