Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8235 was 8232, checked in by dafrick, 14 years ago

Extending and reorganizing ScreenshotManager and SkyboxGenerator.
The SkyboxGenerator now takes HD screenshots, thus the size of the faces generated by the SkyboxGenerator can now be specified freely (through a config value).

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