void StarSystem::UpdateUnitPhysics( bool firstframe ) { static bool phytoggle = true; static int batchcount = SIM_QUEUE_SIZE-1; double aitime = 0; double phytime = 0; double collidetime = 0; double flattentime = 0; double bolttime = 0; targetpick = 0; aggfire = 0; numprocessed = 0; stats.CheckVitals( this ); if (phytoggle) { for (++batchcount; batchcount > 0; --batchcount) { //BELOW COMMENTS ARE NO LONGER IN SYNCH //NOTE: Randomization is necessary to preserve scattering - otherwise, whenever a //unit goes from low-priority to high-priority and back to low-priority, they //get synchronized and start producing peaks. //NOTE2: But... randomization must come only on priority changes. Otherwise, it may //interfere with subunit scheduling. Luckily, all units that make use of subunit //scheduling also require a constant base priority, since otherwise priority changes //will wreak havoc with subunit interpolation. Luckily again, we only need //randomization on priority changes, so we're fine. try { Unit *unit = NULL; for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter); ++iter) { int priority = UnitUtil::getPhysicsPriority( unit ); //Doing spreading here and only on priority changes, so as to make AI easier int predprior = unit->predicted_priority; //If the priority has really changed (not an initial scattering, because prediction doesn't match) if (priority != predprior) { if (predprior == 0) //Validate snapshot of current interpolated state (this is a reschedule) unit->curr_physical_state = unit->cumulative_transformation; //Save priority value as prediction for next scheduling, but don't overwrite yet. predprior = priority; //Scatter, so as to achieve uniform distribution priority = 1+( ( (unsigned int) vsrandom.genrand_int32() )%priority ); } float backup = SIMULATION_ATOM; theunitcounter = theunitcounter+1; SIMULATION_ATOM *= priority; unit->sim_atom_multiplier = priority; double aa = queryTime(); unit->ExecuteAI(); double bb = queryTime(); unit->ResetThreatLevel(); //FIXME "firstframe"-- assume no more than 2 physics updates per frame. unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0, 0, 0 ), priority == 1 ? firstframe : true, &this->gravitationalUnits(), unit ); double cc = queryTime(); aitime += bb-aa; phytime += cc-bb; SIMULATION_ATOM = backup; unit->predicted_priority = predprior; } } catch (const boost::python::error_already_set) { if ( PyErr_Occurred() ) { PyErr_Print(); PyErr_Clear(); fflush( stderr ); fflush( stdout ); } throw; } double c0 = queryTime(); Bolt::UpdatePhysics( this ); double cc = queryTime(); last_collisions.clear(); double fl0 = queryTime(); collidemap[Unit::UNIT_BOLT]->flatten(); if (Unit::NUM_COLLIDE_MAPS > 1) collidemap[Unit::UNIT_ONLY]->flatten( *collidemap[Unit::UNIT_BOLT] ); flattentime = queryTime()-fl0; Unit *unit; for (un_iter iter = physics_buffer[current_sim_location].createIterator(); (unit = *iter);) { int priority = unit->sim_atom_multiplier; float backup = SIMULATION_ATOM; SIMULATION_ATOM *= priority; unsigned int newloc = (current_sim_location+priority)%SIM_QUEUE_SIZE; unit->CollideAll(); SIMULATION_ATOM = backup; if (newloc == current_sim_location) ++iter; else iter.moveBefore( physics_buffer[newloc] ); } double dd = queryTime(); collidetime += dd-cc; bolttime += cc-c0; current_sim_location = (current_sim_location+1)%SIM_QUEUE_SIZE; ++physicsframecounter; totalprocessed += theunitcounter; theunitcounter = 0; } } else { Unit *unit = NULL; for (un_iter iter = getUnitList().createIterator(); (unit = *iter); ++iter) { unit->ExecuteAI(); last_collisions.clear(); unit->UpdatePhysics( identity_transformation, identity_matrix, Vector( 0, 0, 0 ), firstframe, &this->gravitationalUnits(), unit ); unit->CollideAll(); } } }
//client void StarSystem::Update( float priority, bool executeDirector ) { bool firstframe = true; double pythontime = 0; ///this makes it so systems without players may be simulated less accurately for (unsigned int k = 0; k < _Universe->numPlayers(); ++k) if (_Universe->AccessCockpit( k )->activeStarSystem == this) priority = 1; float normal_simulation_atom = SIMULATION_ATOM; SIMULATION_ATOM /= ( priority/getTimeCompression() ); ///just be sure to restore this at the end time += GetElapsedTime(); _Universe->pushActiveStarSystem( this ); //WARNING PERFORMANCE HACK!!!!! if (time > 2*SIMULATION_ATOM) time = 2*SIMULATION_ATOM; double bolttime = 0; if ( time/SIMULATION_ATOM >= (1./PHY_NUM) ) { //Chew up all SIMULATION_ATOMs that have elapsed since last update while ( time/SIMULATION_ATOM >= (1./PHY_NUM) ) { if (current_stage == MISSION_SIMULATION) { TerrainCollide(); UpdateAnimatedTexture(); Unit::ProcessDeleteQueue(); double pythonidea = queryTime(); if ( (run_only_player_starsystem && _Universe->getActiveStarSystem( 0 ) == this) || !run_only_player_starsystem ) if (executeDirector) ExecuteDirector(); pythontime = queryTime()-pythonidea; static int dothis = 0; if ( this == _Universe->getActiveStarSystem( 0 ) ) if ( (++dothis)%2 == 0 ) AUDRefreshSounds(); for (unsigned int i = 0; i < active_missions.size(); ++i) //waste of farkin time active_missions[i]->BriefingUpdate(); current_stage = PROCESS_UNIT; } else if (current_stage == PROCESS_UNIT) { UpdateUnitPhysics( firstframe ); UpdateMissiles(); //do explosions collidetable->Update(); if ( this == _Universe->getActiveStarSystem( 0 ) ) UpdateCameraSnds(); bolttime = queryTime(); bolttime = queryTime()-bolttime; current_stage = MISSION_SIMULATION; firstframe = false; } time -= (1./PHY_NUM)*SIMULATION_ATOM; } unsigned int i = _Universe->CurrentCockpit(); for (unsigned int j = 0; j < _Universe->numPlayers(); ++j) if (_Universe->AccessCockpit( j )->activeStarSystem == this) { _Universe->SetActiveCockpit( j ); _Universe->AccessCockpit( j )->updateAttackers(); if ( _Universe->AccessCockpit( j )->Update() ) { SIMULATION_ATOM = normal_simulation_atom; _Universe->SetActiveCockpit( i ); _Universe->popActiveStarSystem(); return; } } _Universe->SetActiveCockpit( i ); } if ( sigIter.isDone() ) sigIter = drawList.createIterator(); else ++sigIter; while ( !sigIter.isDone() && !UnitUtil::isSignificant( *sigIter) ) ++sigIter; //If it is done, leave it NULL for this frame then. //WARNING cockpit does not get here... SIMULATION_ATOM = normal_simulation_atom; //WARNING cockpit does not get here... _Universe->popActiveStarSystem(); }
//#define UPDATEDEBUG //for hard to track down bugs void GameStarSystem::Draw(bool DrawCockpit) { double starttime=queryTime(); GFXEnable (DEPTHTEST); GFXEnable (DEPTHWRITE); saved_interpolation_blend_factor=interpolation_blend_factor = (1./PHY_NUM)*((PHY_NUM*time)/SIMULATION_ATOM+current_stage); GFXColor4f(1,1,1,1); if (DrawCockpit) { AnimatedTexture::UpdateAllFrame(); } for (unsigned int i=0;i<contterrains.size();++i) { contterrains[i]->AdjustTerrain(this); } Unit * par; bool alreadysetviewport=false; if ((par=_Universe->AccessCockpit()->GetParent())==NULL) { _Universe->AccessCamera()->UpdateGFX (GFXTRUE); } else { if (!par->isSubUnit()) { //now we can assume world is topps par-> cumulative_transformation = linear_interpolate (par->prev_physical_state,par->curr_physical_state,interpolation_blend_factor); Unit * targ = par->Target(); if (targ&&!targ->isSubUnit()) { targ-> cumulative_transformation = linear_interpolate (targ->prev_physical_state,targ->curr_physical_state,interpolation_blend_factor); } _Universe->AccessCockpit()->SetupViewPort(true); alreadysetviewport=true; } } double setupdrawtime=queryTime(); { cam_setup_phase=true; //int numships=0; Unit * saveparent=_Universe->AccessCockpit()->GetSaveParent(); Unit * targ=NULL; if (saveparent) { targ=saveparent->Target(); } //Array containing the two interesting units, so as not to have to copy-paste code Unit * camunits[2]={saveparent,targ}; float backup=SIMULATION_ATOM; unsigned int cur_sim_frame = _Universe->activeStarSystem()->getCurrentSimFrame(); for(int i=0;i<2;++i) { Unit *unit=camunits[i]; // Make sure unit is not null; if(unit&&!unit->isSubUnit()) { interpolation_blend_factor=calc_blend_factor(saved_interpolation_blend_factor,unit->sim_atom_multiplier,unit->cur_sim_queue_slot,cur_sim_frame); SIMULATION_ATOM = backup*unit->sim_atom_multiplier; ((GameUnit<Unit> *)unit)->GameUnit<Unit>::Draw(); } } interpolation_blend_factor=saved_interpolation_blend_factor; SIMULATION_ATOM=backup; //printf("Number of insystem ships: %d (%d FPS)\n",numships,(int)(1.f/GetElapsedTime())); ///this is the final, smoothly calculated cam _Universe->AccessCockpit()->SetupViewPort(true); cam_setup_phase=false; } setupdrawtime=queryTime()-setupdrawtime; GFXDisable (LIGHTING); bg->Draw(); double drawtime=queryTime(); double maxdrawtime=0; //Ballpark estimate of when an object of configurable size first becomes one pixel QVector drawstartpos=_Universe->AccessCamera()->GetPosition(); Collidable key_iterator(0,1,drawstartpos); UnitWithinRangeOfPosition<UnitDrawer> drawer(game_options.precull_dist,0,key_iterator); //Need to draw really big stuff (i.e. planets, deathstars, and other mind-bogglingly big things that shouldn't be culled despited extreme distance Unit* unit; if ((drawer.action.parent=_Universe->AccessCockpit()->GetParent())!=NULL) { drawer.action.parenttarget=drawer.action.parent->Target(); } for(un_iter iter=this->GravitationalUnits.createIterator();(unit=*iter)!=NULL;++iter) { float distance = (drawstartpos-unit->Position()).Magnitude()-unit->rSize(); if(distance < game_options.precull_dist) { drawer.action.grav_acquire(unit); } else { drawer.action.draw(unit); } } // Need to get iterator to approx camera position CollideMap::iterator parent=collidemap[Unit::UNIT_ONLY]->lower_bound(key_iterator); findObjectsFromPosition(this->collidemap[Unit::UNIT_ONLY],parent,&drawer,drawstartpos,0,true); drawer.action.drawParents();//draw units targeted by camera //FIXME maybe we could do bolts & units instead of unit only--and avoid bolt drawing step #if 0 for (unsigned int sim_counter=0;sim_counter<=SIM_QUEUE_SIZE;++sim_counter) { double tmp=queryTime(); Unit *unit; UnitCollection::UnitIterator iter = physics_buffer[sim_counter].createIterator(); float backup=SIMULATION_ATOM; unsigned int cur_sim_frame = _Universe->activeStarSystem()->getCurrentSimFrame(); while((unit = iter.current())!=NULL) { interpolation_blend_factor=calc_blend_factor(saved_interpolation_blend_factor,unit->sim_atom_multiplier,unit->cur_sim_queue_slot,cur_sim_frame); //if (par&&par->Target()==unit) { //printf ("i:%f s:%f m:%d c:%d l:%d\n",interpolation_blend_factor,saved_interpolation_blend_factor,unit->sim_atom_multiplier,sim_counter,current_sim_location); //} SIMULATION_ATOM = backup*unit->sim_atom_multiplier; ((GameUnit<Unit> *)unit)->Draw(); iter.advance(); } interpolation_blend_factor=saved_interpolation_blend_factor; SIMULATION_ATOM=backup; tmp=queryTime()-tmp; if (tmp>maxdrawtime)maxdrawtime=tmp; } #endif drawtime=queryTime()-drawtime; WarpTrailDraw(); GFXFogMode (FOG_OFF); GFXColor tmpcol (0,0,0,1); GFXGetLightContextAmbient(tmpcol); double processmesh=queryTime(); if (!game_options.draw_near_stars_in_front_of_planets) stars->Draw(); Mesh::ProcessZFarMeshes(); if (game_options.draw_near_stars_in_front_of_planets) stars->Draw(); GFXEnable (DEPTHTEST); GFXEnable (DEPTHWRITE); //need to wait for lights to finish GamePlanet::ProcessTerrains(); Terrain::RenderAll(); Mesh::ProcessUndrawnMeshes(true); processmesh=queryTime()-processmesh; Nebula * neb; Matrix ident; Identity(ident); //Atmosphere::ProcessDrawQueue(); GFXPopGlobalEffects(); GFXLightContextAmbient(tmpcol); if ((neb = _Universe->AccessCamera()->GetNebula())) { neb->SetFogState(); } Beam::ProcessDrawQueue(); Bolt::Draw(); // if (_Universe->AccessCamera()->GetNebula()!=NULL) GFXFogMode (FOG_OFF); Animation::ProcessDrawQueue(); Halo::ProcessDrawQueue(); particleTrail.DrawAndUpdate(); GameStarSystem::DrawJumpStars(); ConditionalCursorDraw(false); // static bool doInputDFA = XMLSupport::parse_bool (vs_config->getVariable ("graphics","MouseCursor","false")); if (DrawCockpit) { _Universe->AccessCockpit()->Draw(); // if (doInputDFA) { // GFXHudMode (true); // systemInputDFA->Draw(); // GFXHudMode (false); // } } double fintime=queryTime()-starttime; if (debugPerformance()) { printf("draw: %f setup %f units %f maxunit %f processmesh %f ",fintime,setupdrawtime,drawtime,maxdrawtime,processmesh); } }