00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreStableHeaders.h" 00026 #include "OgreRenderTarget.h" 00027 #include "OgreGuiElement.h" 00028 #include "OgreGuiManager.h" 00029 #include "OgreStringConverter.h" 00030 00031 #include "OgreViewport.h" 00032 #include "OgreException.h" 00033 #include "OgreLogManager.h" 00034 #include "OgreRenderTargetListener.h" 00035 #include "OgrePlatformManager.h" 00036 #include "OgreRoot.h" 00037 00038 namespace Ogre { 00039 00040 RenderTarget::RenderTarget() 00041 { 00042 // Default to no stats display 00043 mStatFlags = SF_NONE; 00044 mActive = true; 00045 mPriority = OGRE_DEFAULT_RT_GROUP; 00046 mTimer = Root::getSingleton().getTimer(); 00047 resetStatistics(); 00048 } 00049 00050 RenderTarget::~RenderTarget() 00051 { 00052 // Delete viewports 00053 for (ViewportList::iterator i = mViewportList.begin(); 00054 i != mViewportList.end(); ++i) 00055 { 00056 delete (*i).second; 00057 } 00058 00059 00060 // Write closing message 00061 LogManager::getSingleton().logMessage( 00062 LML_NORMAL, 00063 "Render Target '%s' Average FPS: %f Best FPS: %f Worst FPS: %f", 00064 mName.c_str(), mStats.avgFPS, mStats.bestFPS, mStats.worstFPS ); 00065 00066 } 00067 00068 const String& RenderTarget::getName(void) const 00069 { 00070 return mName; 00071 } 00072 00073 00074 void RenderTarget::getMetrics(unsigned int& width, unsigned int& height, unsigned int& colourDepth) 00075 { 00076 width = mWidth; 00077 height = mHeight; 00078 colourDepth = mColourDepth; 00079 } 00080 00081 unsigned int RenderTarget::getWidth(void) const 00082 { 00083 return mWidth; 00084 } 00085 unsigned int RenderTarget::getHeight(void) const 00086 { 00087 return mHeight; 00088 } 00089 unsigned int RenderTarget::getColourDepth(void) const 00090 { 00091 return mColourDepth; 00092 } 00093 00094 void RenderTarget::update(void) 00095 { 00096 00097 // notify listeners (pre) 00098 firePreUpdate(); 00099 00100 mStats.triangleCount = 0; 00101 // Go through viewports in Z-order 00102 // Tell each to refresh 00103 ViewportList::iterator it = mViewportList.begin(); 00104 while (it != mViewportList.end()) 00105 { 00106 fireViewportPreUpdate((*it).second); 00107 (*it).second->update(); 00108 mStats.triangleCount += (*it).second->_getNumRenderedFaces(); 00109 fireViewportPostUpdate((*it).second); 00110 ++it; 00111 } 00112 00113 // notify listeners (post) 00114 firePostUpdate(); 00115 00116 // Update statistics (always on top) 00117 updateStats(); 00118 00119 00120 } 00121 00122 Viewport* RenderTarget::addViewport(Camera* cam, int ZOrder, float left, float top , 00123 float width , float height) 00124 { 00125 // Check no existing viewport with this Z-order 00126 ViewportList::iterator it = mViewportList.find(ZOrder); 00127 00128 if (it != mViewportList.end()) 00129 { 00130 char msg[256]; 00131 sprintf(msg, "Can't create another viewport for %s with Z-Order %i " 00132 " because a viewport exists with this Z-Order already.", 00133 this->getName().c_str(), ZOrder); 00134 Except(9999, msg, "RenderTarget::addViewport"); 00135 } 00136 // Add viewport to list 00137 // Order based on Z-Order 00138 Viewport* vp = new Viewport(cam, this, left, top, width, height, ZOrder); 00139 00140 mViewportList.insert(ViewportList::value_type(ZOrder, vp)); 00141 00142 return vp; 00143 } 00144 00145 void RenderTarget::removeViewport(int ZOrder) 00146 { 00147 ViewportList::iterator it = mViewportList.find(ZOrder); 00148 00149 if (it != mViewportList.end()) 00150 { 00151 delete (*it).second; 00152 mViewportList.erase(ZOrder); 00153 } 00154 } 00155 00156 void RenderTarget::removeAllViewports(void) 00157 { 00158 00159 00160 for (ViewportList::iterator it = mViewportList.begin(); it != mViewportList.end(); ++it) 00161 { 00162 delete (*it).second; 00163 } 00164 00165 mViewportList.clear(); 00166 00167 } 00168 void RenderTarget::setStatsDisplay(StatFlags sf) 00169 { 00170 mStatFlags = sf; 00171 } 00172 00173 void RenderTarget::getStatistics(float& lastFPS, float& avgFPS, 00174 float& bestFPS, float& worstFPS) const 00175 { 00176 00177 // Note - the will have been updated by the last render 00178 lastFPS = mStats.lastFPS; 00179 avgFPS = mStats.avgFPS; 00180 bestFPS = mStats.bestFPS; 00181 worstFPS = mStats.worstFPS; 00182 00183 00184 } 00185 00186 const RenderTarget::FrameStats& RenderTarget::getStatistics(void) const 00187 { 00188 return mStats; 00189 } 00190 00191 float RenderTarget::getLastFPS() const 00192 { 00193 return mStats.lastFPS; 00194 } 00195 float RenderTarget::getAverageFPS() const 00196 { 00197 return mStats.avgFPS; 00198 } 00199 float RenderTarget::getBestFPS() const 00200 { 00201 return mStats.bestFPS; 00202 } 00203 float RenderTarget::getWorstFPS() const 00204 { 00205 return mStats.worstFPS; 00206 } 00207 00208 size_t RenderTarget::getTriangleCount(void) const 00209 { 00210 return mStats.triangleCount; 00211 } 00212 00213 float RenderTarget::getBestFrameTime() const 00214 { 00215 return mStats.bestFrameTime; 00216 } 00217 00218 float RenderTarget::getWorstFrameTime() const 00219 { 00220 return mStats.worstFrameTime; 00221 } 00222 00223 void RenderTarget::resetStatistics(void) 00224 { 00225 mStats.avgFPS = 0.0; 00226 mStats.bestFPS = 0.0; 00227 mStats.lastFPS = 0.0; 00228 mStats.worstFPS = 999.0; 00229 mStats.triangleCount = 0; 00230 mStats.bestFrameTime = 999999; 00231 mStats.worstFrameTime = 0; 00232 00233 mLastTime = mTimer->getMilliseconds(); 00234 mLastSecond = mLastTime; 00235 mFrameCount = 0; 00236 } 00237 00238 void RenderTarget::updateStats(void) 00239 { 00240 ++mFrameCount; 00241 unsigned long thisTime = mTimer->getMilliseconds(); 00242 00243 // check frame time 00244 unsigned long frameTime = thisTime - mLastTime ; 00245 mLastTime = thisTime ; 00246 00247 mStats.bestFrameTime = std::min(mStats.bestFrameTime, frameTime); 00248 mStats.worstFrameTime = std::max(mStats.worstFrameTime, frameTime); 00249 00250 // check if new second (update only once per second) 00251 if (thisTime - mLastSecond > 1000) 00252 { 00253 // new second - not 100% precise 00254 mStats.lastFPS = (float)mFrameCount / (float)(thisTime - mLastSecond) * 1000.0; 00255 00256 if (mStats.avgFPS == 0) 00257 mStats.avgFPS = mStats.lastFPS; 00258 else 00259 mStats.avgFPS = (mStats.avgFPS + mStats.lastFPS) / 2; // not strictly correct, but good enough 00260 00261 mStats.bestFPS = std::max(mStats.bestFPS, mStats.lastFPS); 00262 mStats.worstFPS = std::min(mStats.worstFPS, mStats.lastFPS); 00263 00264 mLastSecond = thisTime ; 00265 mFrameCount = 0; 00266 00267 } 00268 00269 } 00270 00271 void RenderTarget::getCustomAttribute(const String& name, void* pData) 00272 { 00273 Except(Exception::ERR_INVALIDPARAMS, "Attribute not found.", "RenderTarget::getCustomAttribute"); 00274 } 00275 //----------------------------------------------------------------------- 00276 void RenderTarget::setDebugText(const String& text) 00277 { 00278 mDebugText = text; 00279 } 00280 //----------------------------------------------------------------------- 00281 const String & RenderTarget::getDebugText() const 00282 { 00283 return mDebugText; 00284 } 00285 //----------------------------------------------------------------------- 00286 void RenderTarget::addListener(RenderTargetListener* listener) 00287 { 00288 mListeners.push_back(listener); 00289 } 00290 //----------------------------------------------------------------------- 00291 void RenderTarget::removeListener(RenderTargetListener* listener) 00292 { 00293 RenderTargetListenerList::iterator i; 00294 for (i = mListeners.begin(); i != mListeners.end(); ++i) 00295 { 00296 if (*i == listener) 00297 { 00298 mListeners.erase(i); 00299 break; 00300 } 00301 } 00302 00303 } 00304 //----------------------------------------------------------------------- 00305 void RenderTarget::removeAllListeners(void) 00306 { 00307 mListeners.clear(); 00308 } 00309 //----------------------------------------------------------------------- 00310 void RenderTarget::firePreUpdate(void) 00311 { 00312 RenderTargetEvent evt; 00313 evt.source = this; 00314 00315 RenderTargetListenerList::iterator i, iend; 00316 i = mListeners.begin(); 00317 iend = mListeners.end(); 00318 for(; i != iend; ++i) 00319 { 00320 (*i)->preRenderTargetUpdate(evt); 00321 } 00322 00323 00324 } 00325 //----------------------------------------------------------------------- 00326 void RenderTarget::firePostUpdate(void) 00327 { 00328 RenderTargetEvent evt; 00329 evt.source = this; 00330 00331 RenderTargetListenerList::iterator i, iend; 00332 i = mListeners.begin(); 00333 iend = mListeners.end(); 00334 for(; i != iend; ++i) 00335 { 00336 (*i)->postRenderTargetUpdate(evt); 00337 } 00338 } 00339 //----------------------------------------------------------------------- 00340 unsigned short RenderTarget::getNumViewports(void) const 00341 { 00342 return (unsigned short)mViewportList.size(); 00343 00344 } 00345 //----------------------------------------------------------------------- 00346 Viewport* RenderTarget::getViewport(unsigned short index) 00347 { 00348 assert (index < mViewportList.size() && "Index out of bounds"); 00349 00350 ViewportList::iterator i = mViewportList.begin(); 00351 while (index--) 00352 ++i; 00353 return i->second; 00354 } 00355 //----------------------------------------------------------------------- 00356 bool RenderTarget::isActive() const 00357 { 00358 return mActive; 00359 } 00360 //----------------------------------------------------------------------- 00361 void RenderTarget::setActive( bool state ) 00362 { 00363 mActive = state; 00364 } 00365 //----------------------------------------------------------------------- 00366 void RenderTarget::fireViewportPreUpdate(Viewport* vp) 00367 { 00368 RenderTargetViewportEvent evt; 00369 evt.source = vp; 00370 00371 RenderTargetListenerList::iterator i, iend; 00372 i = mListeners.begin(); 00373 iend = mListeners.end(); 00374 for(; i != iend; ++i) 00375 { 00376 (*i)->preViewportUpdate(evt); 00377 } 00378 } 00379 //----------------------------------------------------------------------- 00380 void RenderTarget::fireViewportPostUpdate(Viewport* vp) 00381 { 00382 RenderTargetViewportEvent evt; 00383 evt.source = vp; 00384 00385 RenderTargetListenerList::iterator i, iend; 00386 i = mListeners.begin(); 00387 iend = mListeners.end(); 00388 for(; i != iend; ++i) 00389 { 00390 (*i)->postViewportUpdate(evt); 00391 } 00392 } 00393 00394 String RenderTarget::writeContentsToTimestampedFile(const String& filenamePrefix, const String& filenameSuffix) 00395 { 00396 struct tm *pTime; 00397 time_t ctTime; time(&ctTime); 00398 pTime = localtime( &ctTime ); 00399 std::ostringstream oss; 00400 oss << std::setw(2) << std::setfill('0') << pTime->tm_mon 00401 << std::setw(2) << std::setfill('0') << pTime->tm_mday 00402 << std::setw(2) << std::setfill('0') << pTime->tm_year 00403 << "_" << std::setw(2) << std::setfill('0') << pTime->tm_hour 00404 << std::setw(2) << std::setfill('0') << pTime->tm_min 00405 << std::setw(2) << std::setfill('0') << pTime->tm_sec 00406 << std::setw(3) << std::setfill('0') << (mTimer->getMilliseconds() % 1000); 00407 String filename = filenamePrefix + String(oss.str()) + filenameSuffix; 00408 writeContentsToFile(filename); 00409 return filename; 00410 00411 } 00412 }
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:25 2004