Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/designtools/ScreenshotManager.cc @ 8406

Last change on this file since 8406 was 8406, checked in by dafrick, 13 years ago

Quick fix for ScreenshotManager, such that it only needs memory when it is actually used.

  • Property svn:eol-style set to native
File size: 10.5 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/ConfigValueIncludes.h"
45#include "core/GraphicsManager.h"
46#include "core/PathConfig.h"
47#include "core/Resource.h"
48#include "core/command/ConsoleCommand.h"
49#include "util/ScopedSingletonManager.h"
50#include "util/StringUtils.h"
51
52#include "CameraManager.h"
53#include "graphics/Camera.h"
54
55// #include <X11/Xlib.h> TODO: Needed?
56
57namespace orxonox
58{
59
60    SetConsoleCommand("printScreenHD", &ScreenshotManager::makeScreenshot_s);
61   
62    ManageScopedSingleton(ScreenshotManager, ScopeID::Graphics, false);
63
64    /**
65    @brief
66        Constructor.
67    */
68    ScreenshotManager::ScreenshotManager()
69    {
70        RegisterRootObject(ScreenshotManager);
71       
72        this->setConfigValues();
73
74        // Flag for overlay rendering
75        this->disableOverlays_ = true;
76    }
77
78    ScreenshotManager::~ScreenshotManager()
79    {
80       
81    }
82   
83    /**
84    @brief
85        Sets some config values.
86    */
87    void ScreenshotManager::setConfigValues(void)
88    {
89        // Set file extension for the Screenshot files.
90        SetConfigValue(fileExtension_, ".png");
91        // The grid size.
92        SetConfigValue(gridSize_, 3);
93    }
94
95    /**
96    @brief
97        Update internal parameters.
98    */
99    void ScreenshotManager::update(void)
100    {
101        Ogre::RenderWindow* pRenderWindow = GraphicsManager::getInstance().getRenderWindow();
102
103        // If the window size has changed
104        if(this->windowWidth_ != pRenderWindow->getWidth() || this->windowHeight_ != pRenderWindow->getHeight())
105        {
106            // Update current window size
107            this->windowWidth_   = pRenderWindow->getWidth();
108            this->windowHeight_  = pRenderWindow->getHeight();
109
110            // Create temporary texture
111            this->tempTexture_ = Ogre::TextureManager::getSingleton().createManual("ScreenShotTex",
112                Resource::getDefaultResourceGroup(), Ogre::TEX_TYPE_2D, this->windowWidth_,
113                this->windowHeight_, 0, Ogre::PF_B8G8R8, Ogre::TU_RENDERTARGET);
114
115            // Get the current render target of the temporary texture
116            this->renderTarget_ = this->tempTexture_->getBuffer()->getRenderTarget();
117
118            // HardwarePixelBufferSharedPtr to the buffer of the temporary texture
119            this->buffer_ = this->tempTexture_->getBuffer();
120
121            // Create PixelBox
122            this->data_ = new uint8_t[(this->windowWidth_ * this->gridSize_) * (this->windowHeight_ * this->gridSize_) * 3];
123            this->finalPicturePB_ = Ogre::PixelBox(this->windowWidth_ * this->gridSize_, this->windowHeight_ * this->gridSize_, 1, Ogre::PF_B8G8R8, this->data_);
124        }
125    }
126
127
128    /**
129    @brief
130        Make a screenshot.
131        The screenshot is saved in the log folder.
132    */
133    void ScreenshotManager::makeScreenshot()
134    {
135        // Get the screenshot.
136        Ogre::Image* finalImage = getScreenshot();
137        if(finalImage != NULL)
138        {
139            // Save it.
140            finalImage->save(PathConfig::getInstance().getLogPathString() + "screenshot_" + getTimestamp() + this->fileExtension_);
141            delete finalImage;
142            COUT(3) << "Finished taking " << this->gridSize_*this->windowWidth_ << "x" << this->gridSize_*this->windowHeight_ << " pixel HD screenshot. Storing in log/." << endl;
143        }
144        else
145        {
146            COUT(1) << "There needs to be an active camera to make screenshots." << endl;
147            return;
148        }
149    }
150
151    /**
152    @brief
153        Creates a screenshot and returns it.
154    @return
155        Returns a pointer to an Ogre::Image with the screenshot.
156    */
157    Ogre::Image* ScreenshotManager::getScreenshot()
158    {
159        if(CameraManager::getInstance().getActiveCamera() == NULL )
160            return NULL;
161        return this->getScreenshot(CameraManager::getInstance().getActiveCamera()->getOgreCamera());
162    }
163
164    /**
165    @brief
166        Creates a screenshot with the given camera and returns it.
167    @param camera
168        A pointer to the camera the screenshot should be taken with.
169    @return
170        Returns a pointer to an Ogre::Image with the screenshot.
171    */
172    Ogre::Image* ScreenshotManager::getScreenshot(Ogre::Camera* camera)
173    {
174        if(camera == NULL)
175            return NULL;
176       
177        // Update the internal parameters.
178        this->update();
179
180        // Add the camera as viewport.
181        this->renderTarget_->removeAllViewports();
182        this->renderTarget_->addViewport(camera);
183
184        // Set the viewport settings
185        Ogre::Viewport *vp = renderTarget_->getViewport(0);
186        vp->setClearEveryFrame(true);
187        vp->setOverlaysEnabled(false);
188
189        // Remind current overlay flag
190        bool enableOverlayFlag = GraphicsManager::getInstance().getViewport()->getOverlaysEnabled();
191       
192        // We disable overlay rendering if it is set in config file and the viewport setting is enabled
193        if(this->disableOverlays_ && enableOverlayFlag)
194            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(false);
195       
196        Ogre::Image* finalImage = new Ogre::Image();
197       
198        if(this->gridSize_ <= 1)
199        {
200            // Simple case where the contents of the screen are taken directly
201            // Also used when an invalid value is passed within gridSize (zero or negative grid size)
202            this->renderTarget_->update(); // Render
203           
204            finalImage = &finalImage->loadDynamicImage(static_cast<unsigned char*>(finalPicturePB_.data), finalPicturePB_.getWidth(), finalPicturePB_.getHeight(),Ogre::PF_B8G8R8);
205        }
206        else
207        {
208            // Define the original frustum extents variables
209            Ogre::Real originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom;
210            // Set the original Frustum extents
211            camera->getFrustumExtents(originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom);
212           
213            // Compute the Stepsize for the grid
214            Ogre::Real frustumGridStepHorizontal  = (originalFrustumRight * 2) / this->gridSize_;
215            Ogre::Real frustumGridStepVertical  = (originalFrustumTop * 2) / this->gridSize_;
216           
217            // Process each grid
218            Ogre::Real frustumLeft, frustumRight, frustumTop, frustumBottom;
219            for (unsigned int nbScreenshots = 0; nbScreenshots < this->gridSize_ * this->gridSize_; nbScreenshots++)
220            {
221                int y = nbScreenshots / this->gridSize_;
222                int x = nbScreenshots - y * this->gridSize_;
223               
224                // Shoggoth frustum extents setting
225                // Compute the new frustum extents
226                frustumLeft    = originalFrustumLeft + frustumGridStepHorizontal * x;
227                frustumRight  = frustumLeft + frustumGridStepHorizontal;
228                frustumTop    = originalFrustumTop - frustumGridStepVertical * y;
229                frustumBottom  = frustumTop - frustumGridStepVertical;
230               
231                // Set the frustum extents value to the camera
232                camera->setFrustumExtents(frustumLeft, frustumRight, frustumTop, frustumBottom);
233               
234                // Ignore time duration between frames
235                Ogre::Root::getSingletonPtr()->clearEventTimes();
236                this->renderTarget_->update(); // Render
237               
238                // Define the current box
239                Ogre::Box subBox = Ogre::Box(x* this->windowWidth_,y * this->windowHeight_,x * this->windowWidth_ + this->windowWidth_, y * this->windowHeight_ + this->windowHeight_);
240                // Copy the content from the temp buffer into the final picture PixelBox
241                // Place the tempBuffer content at the right position
242                this->buffer_->blitToMemory(this->finalPicturePB_.getSubVolume(subBox));
243               
244                COUT(4) << "Created screenshot number " << nbScreenshots << " for multi grid HD screenshot." << endl;
245               
246            }
247           
248            // Set frustum extents to previous settings
249            camera->resetFrustumExtents();
250           
251            // Insert the PixelBox data into the Image Object
252            finalImage->loadDynamicImage(static_cast<unsigned char*>(this->finalPicturePB_.data), this->finalPicturePB_.getWidth(), this->finalPicturePB_.getHeight(), 1, Ogre::PF_B8G8R8, false);
253        }
254       
255        // Do we have to re-enable our overlays?
256        if(enableOverlayFlag)
257            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(true);
258       
259        // Reset time since last frame to pause the scene
260        Ogre::Root::getSingletonPtr()->clearEventTimes();
261       
262        return finalImage;
263    }
264
265    /**
266    @brief
267        Set the size of the grid.
268    @param size
269        The size of the grid.
270    */
271    void ScreenshotManager::setGridSize(unsigned int size)
272    {
273        if(size == this->gridSize_)
274            return;
275
276        this->gridSize_ = size;
277        // New PixelBox for the changed size.
278        this->data_ = new uint8_t[(this->windowWidth_ * this->gridSize_) * (this->windowHeight_ * this->gridSize_) * 3];
279        this->finalPicturePB_ = Ogre::PixelBox(this->windowWidth_ * this->gridSize_, this->windowHeight_ * this->gridSize_, 1, Ogre::PF_B8G8R8, this->data_);
280    }
281
282}
Note: See TracBrowser for help on using the repository browser.