Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 9870 was 9667, checked in by landauf, 11 years ago

merged core6 back to trunk

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