00001 #include "SimulatorThread.h" 00002 #include "ThyrixApplication.h" 00003 #include "ThyrixMainFrame.h" 00004 #include "World.h" 00005 00006 SimulatorThread::SimulatorThread(ThyrixMainFrame *iniFrame) : 00007 wxThread(wxTHREAD_JOINABLE), 00008 frame(iniFrame), 00009 timeFactor(1000), 00010 paused(false), 00011 expectedTime(0){ 00012 setTimeFactor(1); 00013 setFramesPerSecond(30); 00014 } 00015 00016 SimulatorThread::~SimulatorThread(){ 00017 } 00018 00019 void SimulatorThread::step() { 00020 //this is called directly by the parent frame, following a command 00021 //needs mutex sincronization with the thread. 00022 world->advanceTime(); 00023 } 00024 00025 void SimulatorThread::setPause() { 00026 paused = true; 00027 } 00028 00029 void SimulatorThread::setTimeFactor(float newFactor) { 00030 timeFactor = newFactor; 00031 paused = false; 00032 expectedTime = 0; 00033 simulationTimer.Start(); 00034 } 00035 00036 void SimulatorThread::setFramesPerSecond(int fps) { 00037 frameInterval = 1000 / fps; 00038 } 00039 00040 void SimulatorThread::sleepIfAhead() { 00041 00042 //sleep when more than 5ms ahead 00043 static const int kSleepThreshold = 5; 00044 00045 unsigned expectedTimeMs = (unsigned)(expectedTime * 1000); 00046 unsigned realMs = (unsigned)simulationTimer.Time(); 00047 int aheadMs = 0; 00048 if ( expectedTimeMs > realMs) { 00049 aheadMs = expectedTimeMs - realMs; 00050 } 00051 if (aheadMs > kSleepThreshold) { 00052 Sleep(aheadMs); 00053 } 00054 //to avoid timer overflow, reset it once in a while 00055 if (realMs > 100000) { 00056 setTimeFactor(timeFactor); 00057 } 00058 } 00059 00060 void* SimulatorThread::Entry(){ 00061 wxStopWatch displayTimer; 00062 simulationTimer.Start(); //starts the timing of the running time of the simulator 00063 while(!TestDestroy()){ 00064 displayTimer.Start(); //starts the timing of the duration of a frame 00065 frame->paint(); //draws the image 00066 if (paused) { 00067 Sleep(frameInterval); 00068 } else { 00069 00070 //advance simulator time, in a loop, as long a refresh of the display is not needed 00071 do { 00072 00073 //wait if the simulation should not advance yet 00074 sleepIfAhead(); 00075 00076 //advance simulator time 00077 world->advanceTime(); 00078 00079 //computes the real time at which the next simulator timestep should be executed, 00080 //given the desired acceleration factor between real time and simulator time 00081 expectedTime += world->getDt() / timeFactor; 00082 00083 } while (displayTimer.Time() < frameInterval); 00084 00085 } 00086 } 00087 return NULL; 00088 } 00089 00090 void SimulatorThread::OnExit(){ 00091 }
Thyrix homepage Users' guide
(C) Arxia 2004-2005