Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10107 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
RevLine 
[8232]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 */
[7015]29
[8232]30/**
31   @file ScreenshotManager.cc
32   @brief Implementation of the ScreenshotManager class.
33   @ingroup Designtools
34*/
35
[7015]36#include "ScreenshotManager.h"
[7041]37
[8232]38#include <OgreCamera.h>
39#include <OgreRenderTexture.h>
[7015]40#include <OgreRenderWindow.h>
[8232]41#include <OgreRoot.h>
[7015]42#include <OgreViewport.h>
43
[9667]44#include "core/CoreIncludes.h"
45#include "core/config/ConfigValueIncludes.h"
[7015]46#include "core/GraphicsManager.h"
[7041]47#include "core/PathConfig.h"
[8351]48#include "core/Resource.h"
[7284]49#include "core/command/ConsoleCommand.h"
[8232]50#include "util/ScopedSingletonManager.h"
51#include "util/StringUtils.h"
[7015]52
[7041]53#include "CameraManager.h"
54#include "graphics/Camera.h"
[7015]55
[8297]56// #include <X11/Xlib.h> TODO: Needed?
57
[7015]58namespace orxonox
59{
[8232]60
61    SetConsoleCommand("printScreenHD", &ScreenshotManager::makeScreenshot_s);
62   
[7041]63    ManageScopedSingleton(ScreenshotManager, ScopeID::Graphics, false);
[7015]64
[8232]65    /**
66    @brief
67        Constructor.
68    */
[8413]69    ScreenshotManager::ScreenshotManager() : finalPicturePB_(NULL), data_(NULL)
[7015]70    {
[9667]71        RegisterObject(ScreenshotManager);
[8232]72       
73        this->setConfigValues();
74
75        // Flag for overlay rendering
76        this->disableOverlays_ = true;
77    }
78
79    ScreenshotManager::~ScreenshotManager()
80    {
[8413]81        this->cleanup();
[8232]82    }
[8413]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    }
[8232]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    {
[7041]122        Ogre::RenderWindow* pRenderWindow = GraphicsManager::getInstance().getRenderWindow();
123
[8413]124        // Update current window size
125        this->windowWidth_   = pRenderWindow->getWidth();
126        this->windowHeight_  = pRenderWindow->getHeight();
[7076]127
[8413]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);
[7015]130
[8413]131        // Get the current render target of the temporary texture
132        this->renderTarget_ = this->tempTexture_->getBuffer()->getRenderTarget();
[7015]133
[8413]134        // HardwarePixelBufferSharedPtr to the buffer of the temporary texture
135        this->buffer_ = this->tempTexture_->getBuffer();
[7015]136
[8413]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_);
[7015]140    }
141
[8232]142    /**
143    @brief
144        Make a screenshot.
145        The screenshot is saved in the log folder.
146    */
147    void ScreenshotManager::makeScreenshot()
[7015]148    {
[8232]149        // Get the screenshot.
150        Ogre::Image* finalImage = getScreenshot();
151        if(finalImage != NULL)
152        {
153            // Save it.
[8406]154            finalImage->save(PathConfig::getInstance().getLogPathString() + "screenshot_" + getTimestamp() + this->fileExtension_);
[8232]155            delete finalImage;
[8858]156            orxout(user_info) << "Finished taking " << this->gridSize_*this->windowWidth_ << "x" << this->gridSize_*this->windowHeight_ << " pixel HD screenshot. Storing in log/." << endl;
[8232]157        }
158        else
[8858]159            orxout(user_error) << "There needs to be an active camera to make screenshots." << endl;
[8413]160
161        this->cleanup();
[7015]162    }
163
[8232]164    /**
165    @brief
166        Creates a screenshot and returns it.
[8413]167        After calling this method the ScreenshotManager should be cleaned using cleanup().
[8232]168    @return
[8413]169        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
[8232]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    }
[7015]177
[8079]178    /**
179    @brief
[8232]180        Creates a screenshot with the given camera and returns it.
[8413]181        After calling this method the ScreenshotManager should be cleaned using cleanup().
[8232]182    @param camera
183        A pointer to the camera the screenshot should be taken with.
184    @return
[8413]185        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
[7015]186    */
[8232]187    Ogre::Image* ScreenshotManager::getScreenshot(Ogre::Camera* camera)
[7015]188    {
[8232]189        if(camera == NULL)
190            return NULL;
191       
192        // Update the internal parameters.
193        this->update();
[7015]194
[8232]195        // Add the camera as viewport.
196        this->renderTarget_->removeAllViewports();
197        this->renderTarget_->addViewport(camera);
[7076]198
[8232]199        // Set the viewport settings
200        Ogre::Viewport *vp = renderTarget_->getViewport(0);
[7076]201        vp->setClearEveryFrame(true);
[7015]202        vp->setOverlaysEnabled(false);
203
[8232]204        // Remind current overlay flag
[7015]205        bool enableOverlayFlag = GraphicsManager::getInstance().getViewport()->getOverlaysEnabled();
[8232]206       
207        // We disable overlay rendering if it is set in config file and the viewport setting is enabled
208        if(this->disableOverlays_ && enableOverlayFlag)
[7015]209            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(false);
[8232]210       
211        Ogre::Image* finalImage = new Ogre::Image();
212       
213        if(this->gridSize_ <= 1)
[7015]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)
[8232]217            this->renderTarget_->update(); // Render
[8414]218
219            this->buffer_->blitToMemory(*this->finalPicturePB_);
[8413]220            finalImage->loadDynamicImage(static_cast<unsigned char*>(finalPicturePB_->data), finalPicturePB_->getWidth(), finalPicturePB_->getHeight(),Ogre::PF_B8G8R8);
[7015]221        }
222        else
223        {
[8232]224            // Define the original frustum extents variables
[7015]225            Ogre::Real originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom;
[8232]226            // Set the original Frustum extents
[7015]227            camera->getFrustumExtents(originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom);
[8232]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
[7015]234            Ogre::Real frustumLeft, frustumRight, frustumTop, frustumBottom;
[8232]235            for (unsigned int nbScreenshots = 0; nbScreenshots < this->gridSize_ * this->gridSize_; nbScreenshots++)
[7076]236            {
[8232]237                int y = nbScreenshots / this->gridSize_;
238                int x = nbScreenshots - y * this->gridSize_;
239               
[7015]240                // Shoggoth frustum extents setting
[8232]241                // Compute the new frustum extents
[7039]242                frustumLeft    = originalFrustumLeft + frustumGridStepHorizontal * x;
243                frustumRight  = frustumLeft + frustumGridStepHorizontal;
244                frustumTop    = originalFrustumTop - frustumGridStepVertical * y;
245                frustumBottom  = frustumTop - frustumGridStepVertical;
[8232]246               
247                // Set the frustum extents value to the camera
[7015]248                camera->setFrustumExtents(frustumLeft, frustumRight, frustumTop, frustumBottom);
[8232]249               
250                // Ignore time duration between frames
[7015]251                Ogre::Root::getSingletonPtr()->clearEventTimes();
[8232]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
[8413]258                this->buffer_->blitToMemory(this->finalPicturePB_->getSubVolume(subBox));
[8232]259               
[8858]260                orxout(internal_info) << "Created screenshot number " << nbScreenshots << " for multi grid HD screenshot." << endl;
[8232]261               
[7015]262            }
[8232]263           
264            // Set frustum extents to previous settings
[7015]265            camera->resetFrustumExtents();
[8232]266           
267            // Insert the PixelBox data into the Image Object
[8413]268            finalImage->loadDynamicImage(static_cast<unsigned char*>(this->finalPicturePB_->data), this->finalPicturePB_->getWidth(), this->finalPicturePB_->getHeight(), 1, Ogre::PF_B8G8R8, false);
[7015]269        }
[8232]270       
271        // Do we have to re-enable our overlays?
[7015]272        if(enableOverlayFlag)
273            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(true);
[8232]274       
275        // Reset time since last frame to pause the scene
[7015]276        Ogre::Root::getSingletonPtr()->clearEventTimes();
[8232]277       
278        return finalImage;
[7015]279    }
280
[8079]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    {
[8232]289        if(size == this->gridSize_)
[8079]290            return;
291
[8232]292        this->gridSize_ = size;
[8079]293    }
294
[7015]295}
Note: See TracBrowser for help on using the repository browser.