Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8411 was 8406, checked in by dafrick, 14 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
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
[8232]44#include "core/ConfigValueIncludes.h"
[7015]45#include "core/GraphicsManager.h"
[7041]46#include "core/PathConfig.h"
[8351]47#include "core/Resource.h"
[7284]48#include "core/command/ConsoleCommand.h"
[8232]49#include "util/ScopedSingletonManager.h"
50#include "util/StringUtils.h"
[7015]51
[7041]52#include "CameraManager.h"
53#include "graphics/Camera.h"
[7015]54
[8297]55// #include <X11/Xlib.h> TODO: Needed?
56
[7015]57namespace orxonox
58{
[8232]59
60    SetConsoleCommand("printScreenHD", &ScreenshotManager::makeScreenshot_s);
61   
[7041]62    ManageScopedSingleton(ScreenshotManager, ScopeID::Graphics, false);
[7015]63
[8232]64    /**
65    @brief
66        Constructor.
67    */
[7041]68    ScreenshotManager::ScreenshotManager()
[7015]69    {
[8232]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    {
[7041]101        Ogre::RenderWindow* pRenderWindow = GraphicsManager::getInstance().getRenderWindow();
102
[8232]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();
[7076]109
[8232]110            // Create temporary texture
[8351]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);
[7015]114
[8232]115            // Get the current render target of the temporary texture
116            this->renderTarget_ = this->tempTexture_->getBuffer()->getRenderTarget();
[7015]117
[8232]118            // HardwarePixelBufferSharedPtr to the buffer of the temporary texture
119            this->buffer_ = this->tempTexture_->getBuffer();
[7015]120
[8232]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        }
[7015]125    }
126
127
[8232]128    /**
129    @brief
130        Make a screenshot.
131        The screenshot is saved in the log folder.
132    */
133    void ScreenshotManager::makeScreenshot()
[7015]134    {
[8232]135        // Get the screenshot.
136        Ogre::Image* finalImage = getScreenshot();
137        if(finalImage != NULL)
138        {
139            // Save it.
[8406]140            finalImage->save(PathConfig::getInstance().getLogPathString() + "screenshot_" + getTimestamp() + this->fileExtension_);
[8232]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        }
[7015]149    }
150
[8232]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    }
[7015]163
[8079]164    /**
165    @brief
[8232]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.
[7015]171    */
[8232]172    Ogre::Image* ScreenshotManager::getScreenshot(Ogre::Camera* camera)
[7015]173    {
[8232]174        if(camera == NULL)
175            return NULL;
176       
177        // Update the internal parameters.
178        this->update();
[7015]179
[8232]180        // Add the camera as viewport.
181        this->renderTarget_->removeAllViewports();
182        this->renderTarget_->addViewport(camera);
[7076]183
[8232]184        // Set the viewport settings
185        Ogre::Viewport *vp = renderTarget_->getViewport(0);
[7076]186        vp->setClearEveryFrame(true);
[7015]187        vp->setOverlaysEnabled(false);
188
[8232]189        // Remind current overlay flag
[7015]190        bool enableOverlayFlag = GraphicsManager::getInstance().getViewport()->getOverlaysEnabled();
[8232]191       
192        // We disable overlay rendering if it is set in config file and the viewport setting is enabled
193        if(this->disableOverlays_ && enableOverlayFlag)
[7015]194            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(false);
[8232]195       
196        Ogre::Image* finalImage = new Ogre::Image();
197       
198        if(this->gridSize_ <= 1)
[7015]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)
[8232]202            this->renderTarget_->update(); // Render
203           
204            finalImage = &finalImage->loadDynamicImage(static_cast<unsigned char*>(finalPicturePB_.data), finalPicturePB_.getWidth(), finalPicturePB_.getHeight(),Ogre::PF_B8G8R8);
[7015]205        }
206        else
207        {
[8232]208            // Define the original frustum extents variables
[7015]209            Ogre::Real originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom;
[8232]210            // Set the original Frustum extents
[7015]211            camera->getFrustumExtents(originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom);
[8232]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
[7015]218            Ogre::Real frustumLeft, frustumRight, frustumTop, frustumBottom;
[8232]219            for (unsigned int nbScreenshots = 0; nbScreenshots < this->gridSize_ * this->gridSize_; nbScreenshots++)
[7076]220            {
[8232]221                int y = nbScreenshots / this->gridSize_;
222                int x = nbScreenshots - y * this->gridSize_;
223               
[7015]224                // Shoggoth frustum extents setting
[8232]225                // Compute the new frustum extents
[7039]226                frustumLeft    = originalFrustumLeft + frustumGridStepHorizontal * x;
227                frustumRight  = frustumLeft + frustumGridStepHorizontal;
228                frustumTop    = originalFrustumTop - frustumGridStepVertical * y;
229                frustumBottom  = frustumTop - frustumGridStepVertical;
[8232]230               
231                // Set the frustum extents value to the camera
[7015]232                camera->setFrustumExtents(frustumLeft, frustumRight, frustumTop, frustumBottom);
[8232]233               
234                // Ignore time duration between frames
[7015]235                Ogre::Root::getSingletonPtr()->clearEventTimes();
[8232]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               
[7015]246            }
[8232]247           
248            // Set frustum extents to previous settings
[7015]249            camera->resetFrustumExtents();
[8232]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);
[7015]253        }
[8232]254       
255        // Do we have to re-enable our overlays?
[7015]256        if(enableOverlayFlag)
257            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(true);
[8232]258       
259        // Reset time since last frame to pause the scene
[7015]260        Ogre::Root::getSingletonPtr()->clearEventTimes();
[8232]261       
262        return finalImage;
[7015]263    }
264
[8079]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    {
[8232]273        if(size == this->gridSize_)
[8079]274            return;
275
[8232]276        this->gridSize_ = size;
[8079]277        // New PixelBox for the changed size.
[8232]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_);
[8079]280    }
281
[7015]282}
Note: See TracBrowser for help on using the repository browser.