Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core7/src/modules/designtools/ScreenshotManager.cc @ 10417

Last change on this file since 10417 was 10407, checked in by landauf, 10 years ago

moved Scope and ScopedSingletonManager from util to core.
TODO I had to disable two tests in ScopeTest.cc because now that it runs in the core library, there are too many singletons which get loaded in graphics scope (with too many dependencies). this should be fixed

  • Property svn:eol-style set to native
File size: 10.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      This code comes from http://www.ogre3d.org/tikiwiki/High+resolution+screenshots which is Public Domain.
24 *   Co-authors:
25 *      Oli Scheuss
26 *      Damian 'Mozork' Frick
27 *
28 */
29
30/**
31   @file ScreenshotManager.cc
32   @brief Implementation of the ScreenshotManager class.
33   @ingroup Designtools
34*/
35
36#include "ScreenshotManager.h"
37
38#include <OgreCamera.h>
39#include <OgreRenderTexture.h>
40#include <OgreRenderWindow.h>
41#include <OgreRoot.h>
42#include <OgreViewport.h>
43
44#include "core/CoreIncludes.h"
45#include "core/config/ConfigValueIncludes.h"
46#include "core/GraphicsManager.h"
47#include "core/PathConfig.h"
48#include "core/Resource.h"
49#include "core/command/ConsoleCommandIncludes.h"
50#include "core/singleton/ScopedSingletonManager.h"
51#include "util/StringUtils.h"
52
53#include "CameraManager.h"
54#include "graphics/Camera.h"
55
56// #include <X11/Xlib.h> TODO: Needed?
57
58namespace orxonox
59{
60
61    SetConsoleCommand("printScreenHD", &ScreenshotManager::makeScreenshot_s);
62   
63    ManageScopedSingleton(ScreenshotManager, ScopeID::Graphics, false);
64
65    RegisterAbstractClass(ScreenshotManager).inheritsFrom<Configurable>();
66
67    /**
68    @brief
69        Constructor.
70    */
71    ScreenshotManager::ScreenshotManager() : finalPicturePB_(NULL), data_(NULL)
72    {
73        RegisterObject(ScreenshotManager);
74       
75        this->setConfigValues();
76
77        // Flag for overlay rendering
78        this->disableOverlays_ = true;
79    }
80
81    ScreenshotManager::~ScreenshotManager()
82    {
83        this->cleanup();
84    }
85
86    /**
87    @brief
88        Frees used memory.
89    */
90    void ScreenshotManager::cleanup(void)
91    {
92        if(this->finalPicturePB_ != NULL)
93        {
94            delete this->finalPicturePB_;
95            this->finalPicturePB_ = NULL;
96        }
97        if(this->data_ != NULL)
98        {
99            delete this->data_;
100            this->data_ = NULL;
101        }
102        if(!this->tempTexture_.isNull())
103            this->tempTexture_.freeMethod();
104    }
105   
106    /**
107    @brief
108        Sets some config values.
109    */
110    void ScreenshotManager::setConfigValues(void)
111    {
112        // Set file extension for the Screenshot files.
113        SetConfigValue(fileExtension_, ".png");
114        // The grid size.
115        SetConfigValue(gridSize_, 3);
116    }
117
118    /**
119    @brief
120        Update internal parameters.
121    */
122    void ScreenshotManager::update(void)
123    {
124        Ogre::RenderWindow* pRenderWindow = GraphicsManager::getInstance().getRenderWindow();
125
126        // Update current window size
127        this->windowWidth_   = pRenderWindow->getWidth();
128        this->windowHeight_  = pRenderWindow->getHeight();
129
130        // Create temporary texture
131        this->tempTexture_ = Ogre::TextureManager::getSingleton().createManual("ScreenShotTex", Resource::getDefaultResourceGroup(), Ogre::TEX_TYPE_2D, this->windowWidth_, this->windowHeight_, 0, Ogre::PF_B8G8R8, Ogre::TU_RENDERTARGET);
132
133        // Get the current render target of the temporary texture
134        this->renderTarget_ = this->tempTexture_->getBuffer()->getRenderTarget();
135
136        // HardwarePixelBufferSharedPtr to the buffer of the temporary texture
137        this->buffer_ = this->tempTexture_->getBuffer();
138
139        // Create PixelBox
140        this->data_ = new uint8_t[(this->windowWidth_ * this->gridSize_) * (this->windowHeight_ * this->gridSize_) * 3];
141        this->finalPicturePB_ = new Ogre::PixelBox(this->windowWidth_ * this->gridSize_, this->windowHeight_ * this->gridSize_, 1, Ogre::PF_B8G8R8, this->data_);
142    }
143
144    /**
145    @brief
146        Make a screenshot.
147        The screenshot is saved in the log folder.
148    */
149    void ScreenshotManager::makeScreenshot()
150    {
151        // Get the screenshot.
152        Ogre::Image* finalImage = getScreenshot();
153        if(finalImage != NULL)
154        {
155            // Save it.
156            finalImage->save(PathConfig::getInstance().getLogPathString() + "screenshot_" + getTimestamp() + this->fileExtension_);
157            delete finalImage;
158            orxout(user_info) << "Finished taking " << this->gridSize_*this->windowWidth_ << "x" << this->gridSize_*this->windowHeight_ << " pixel HD screenshot. Storing in log/." << endl;
159        }
160        else
161            orxout(user_error) << "There needs to be an active camera to make screenshots." << endl;
162
163        this->cleanup();
164    }
165
166    /**
167    @brief
168        Creates a screenshot and returns it.
169        After calling this method the ScreenshotManager should be cleaned using cleanup().
170    @return
171        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
172    */
173    Ogre::Image* ScreenshotManager::getScreenshot()
174    {
175        if(CameraManager::getInstance().getActiveCamera() == NULL )
176            return NULL;
177        return this->getScreenshot(CameraManager::getInstance().getActiveCamera()->getOgreCamera());
178    }
179
180    /**
181    @brief
182        Creates a screenshot with the given camera and returns it.
183        After calling this method the ScreenshotManager should be cleaned using cleanup().
184    @param camera
185        A pointer to the camera the screenshot should be taken with.
186    @return
187        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
188    */
189    Ogre::Image* ScreenshotManager::getScreenshot(Ogre::Camera* camera)
190    {
191        if(camera == NULL)
192            return NULL;
193       
194        // Update the internal parameters.
195        this->update();
196
197        // Add the camera as viewport.
198        this->renderTarget_->removeAllViewports();
199        this->renderTarget_->addViewport(camera);
200
201        // Set the viewport settings
202        Ogre::Viewport *vp = renderTarget_->getViewport(0);
203        vp->setClearEveryFrame(true);
204        vp->setOverlaysEnabled(false);
205
206        // Remind current overlay flag
207        bool enableOverlayFlag = GraphicsManager::getInstance().getViewport()->getOverlaysEnabled();
208       
209        // We disable overlay rendering if it is set in config file and the viewport setting is enabled
210        if(this->disableOverlays_ && enableOverlayFlag)
211            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(false);
212       
213        Ogre::Image* finalImage = new Ogre::Image();
214       
215        if(this->gridSize_ <= 1)
216        {
217            // Simple case where the contents of the screen are taken directly
218            // Also used when an invalid value is passed within gridSize (zero or negative grid size)
219            this->renderTarget_->update(); // Render
220
221            this->buffer_->blitToMemory(*this->finalPicturePB_);
222            finalImage->loadDynamicImage(static_cast<unsigned char*>(finalPicturePB_->data), finalPicturePB_->getWidth(), finalPicturePB_->getHeight(),Ogre::PF_B8G8R8);
223        }
224        else
225        {
226            // Define the original frustum extents variables
227            Ogre::Real originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom;
228            // Set the original Frustum extents
229            camera->getFrustumExtents(originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom);
230           
231            // Compute the Stepsize for the grid
232            Ogre::Real frustumGridStepHorizontal  = (originalFrustumRight * 2) / this->gridSize_;
233            Ogre::Real frustumGridStepVertical  = (originalFrustumTop * 2) / this->gridSize_;
234           
235            // Process each grid
236            Ogre::Real frustumLeft, frustumRight, frustumTop, frustumBottom;
237            for (unsigned int nbScreenshots = 0; nbScreenshots < this->gridSize_ * this->gridSize_; nbScreenshots++)
238            {
239                int y = nbScreenshots / this->gridSize_;
240                int x = nbScreenshots - y * this->gridSize_;
241               
242                // Shoggoth frustum extents setting
243                // Compute the new frustum extents
244                frustumLeft    = originalFrustumLeft + frustumGridStepHorizontal * x;
245                frustumRight  = frustumLeft + frustumGridStepHorizontal;
246                frustumTop    = originalFrustumTop - frustumGridStepVertical * y;
247                frustumBottom  = frustumTop - frustumGridStepVertical;
248               
249                // Set the frustum extents value to the camera
250                camera->setFrustumExtents(frustumLeft, frustumRight, frustumTop, frustumBottom);
251               
252                // Ignore time duration between frames
253                Ogre::Root::getSingletonPtr()->clearEventTimes();
254                this->renderTarget_->update(); // Render
255               
256                // Define the current box
257                Ogre::Box subBox = Ogre::Box(x* this->windowWidth_,y * this->windowHeight_,x * this->windowWidth_ + this->windowWidth_, y * this->windowHeight_ + this->windowHeight_);
258                // Copy the content from the temp buffer into the final picture PixelBox
259                // Place the tempBuffer content at the right position
260                this->buffer_->blitToMemory(this->finalPicturePB_->getSubVolume(subBox));
261               
262                orxout(internal_info) << "Created screenshot number " << nbScreenshots << " for multi grid HD screenshot." << endl;
263               
264            }
265           
266            // Set frustum extents to previous settings
267            camera->resetFrustumExtents();
268           
269            // Insert the PixelBox data into the Image Object
270            finalImage->loadDynamicImage(static_cast<unsigned char*>(this->finalPicturePB_->data), this->finalPicturePB_->getWidth(), this->finalPicturePB_->getHeight(), 1, Ogre::PF_B8G8R8, false);
271        }
272       
273        // Do we have to re-enable our overlays?
274        if(enableOverlayFlag)
275            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(true);
276       
277        // Reset time since last frame to pause the scene
278        Ogre::Root::getSingletonPtr()->clearEventTimes();
279       
280        return finalImage;
281    }
282
283    /**
284    @brief
285        Set the size of the grid.
286    @param size
287        The size of the grid.
288    */
289    void ScreenshotManager::setGridSize(unsigned int size)
290    {
291        if(size == this->gridSize_)
292            return;
293
294        this->gridSize_ = size;
295    }
296
297}
Note: See TracBrowser for help on using the repository browser.