Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/designtools/SkyboxGenerator.cc @ 8551

Last change on this file since 8551 was 8413, checked in by dafrick, 14 years ago

This should make the ScreenshotManager a lot more memory efficient.

  • Property svn:eol-style set to native
File size: 11.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 *      Gion-Andri Cantieni
24 *   Co-authors:
25 *      Damian 'Mozork' Frick
26 *
27 */
28
29/**
30    @file SkyboxGenerator.cc
31    @brief Implementation of the SkyboxGenerator class.
32*/
33
34#include "SkyboxGenerator.h"
35
36#include <string>
37#include <OgreRenderWindow.h>
38#include <OgreCamera.h>
39
40#include "util/ScopedSingletonManager.h"
41#include "core/CoreIncludes.h"
42#include "core/ConfigValueIncludes.h"
43#include "core/GraphicsManager.h"
44#include "core/PathConfig.h"
45#include "core/Resource.h"
46#include "core/command/ConsoleCommand.h"
47#include "core/command/CommandExecutor.h"
48
49#include "controllers/HumanController.h"
50#include "graphics/Camera.h"
51#include "worldentities/ControllableEntity.h"
52
53#include "ScreenshotManager.h"
54
55// #include <X11/Xlib.h> TODO: Needed?
56
57namespace orxonox
58{
59
60    SetConsoleCommand("SkyboxGenerator", "createSkybox", &SkyboxGenerator::createSkybox).addShortcut();
61
62    ManageScopedSingleton(SkyboxGenerator, ScopeID::Graphics, false);
63
64    /**
65    @brief
66        Constructor. Registers and initializes the singleton.
67    */
68    SkyboxGenerator::SkyboxGenerator()
69    {
70        RegisterRootObject(SkyboxGenerator);
71
72        this->setConfigValues();
73       
74        this->bGenerateSkybox_ = false;
75        this->bCaptionsRemoved_ = false;
76        this->bSetup_ = true;
77        this->bWait_ = false;
78        this->bCreateFace_ = true;
79        this->bCleanup_ = true;
80        this->faceCounter_ = 0;
81       
82        this->names_.push_back("fr");
83        this->names_.push_back("lf");
84        this->names_.push_back("bk");
85        this->names_.push_back("rt");
86        this->names_.push_back("up");
87        this->names_.push_back("dn");
88       
89        this->rotations_.push_back(std::pair<int, int>(90, 0));
90        this->rotations_.push_back(std::pair<int, int>(90, 0));
91        this->rotations_.push_back(std::pair<int, int>(90, 0));
92        this->rotations_.push_back(std::pair<int, int>(90, 90));
93        this->rotations_.push_back(std::pair<int, int>(0, 180));
94        this->rotations_.push_back(std::pair<int, int>(0, 90));
95    }
96
97    /**
98    @brief
99        Destructor.
100    */
101    SkyboxGenerator::~SkyboxGenerator()
102    {
103
104    }
105
106    /**
107    @brief
108        Sets some config values.
109    */
110    void SkyboxGenerator::setConfigValues( )
111    {
112        SetConfigValue(skyboxPrefix_, "SkyboxFile_");
113        SetConfigValue(imageExtension_, ".png");
114        SetConfigValue(size_, 1024);
115    }
116   
117    /**
118    @brief
119        Generate the 6 faces of a skybox.
120    */
121    void SkyboxGenerator::createSkybox()
122    {
123        // Pause
124        CommandExecutor::execute("pause");
125        // Start the skybox generation process.
126        SkyboxGenerator::getInstance().startSkyboxGeneration();
127    }
128
129    /**
130    @brief
131        This is where the skybox generation happens.
132        Generating a skybox takes several (up to 10) ticks.
133    */
134    void SkyboxGenerator::tick(float dt)
135    {
136        // Whether a skybox is currently being generated.
137        if(this->bGenerateSkybox_)
138        {
139            // Wait one tick.
140            if(this->bWait_)
141            {
142                this->bWait_ = false;
143                return;
144            }
145
146            ControllableEntity* entity = NULL;
147            if(HumanController::getLocalControllerSingleton() != NULL && HumanController::getLocalControllerSingleton()->getControllableEntity() != NULL)
148                entity = HumanController::getLocalControllerSingleton()->getControllableEntity();
149            else
150            {
151                COUT(1) << "You must be in a level to generate a skybox." << endl;
152                this->bGenerateSkybox_ = false;
153                return;
154            }
155            Ogre::Camera* camera = entity->getCamera()->getOgreCamera();
156            Ogre::RenderWindow* renderWindow = GraphicsManager::getInstance().getRenderWindow();
157           
158            // Setup the SkyboxGenerator to generate a skybox.
159            if(this->bSetup_)
160            {
161                // If there are captions being displayed, don't.
162                if(!this->bCaptionsRemoved_)
163                {
164                    CommandExecutor::execute("GametypeStatus displayCaption false");
165                    this->bCaptionsRemoved_ = true;
166                    return;
167                }
168               
169                // Store the settings for the camera.
170                this->fovy_ = camera->getFOVy();
171                this->aspectRatio_ = camera->getAspectRatio();
172                // Setup the render window.
173                this->setupRenderWindow(renderWindow);
174                // Add the log path to the standard resource group.
175                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(PathConfig::getInstance().getLogPathString(), "FileSystem", Resource::getDefaultResourceGroup());
176               
177                COUT(4) << "Setting up SkyboxGenerator..." << endl;
178               
179                this->bSetup_ = false;
180                this->bWait_ = true;
181            }
182            // Create one of the faces. (faceCounter_ decides which)
183            else if(this->bCreateFace_)
184            {
185                // Setup the camera.
186                this->setupCamera(camera);
187                // Take the picture using the ScreenshotManager and save it.
188                this->saveImage(ScreenshotManager::getInstance().getScreenshot(camera), this->skyboxPrefix_+this->names_[this->faceCounter_]+this->imageExtension_);
189                // Rotate the camera to be ready for taking the next picture.
190                std::pair<int, int> rotate = this->rotations_[this->faceCounter_];
191                if(rotate.first != 0)
192                    entity->yaw(Degree((float)rotate.first));
193                if(rotate.second != 0)
194                    entity->pitch(Degree((float)rotate.second));
195               
196                COUT(4) << "Created face number " << this->faceCounter_ << "." << endl;
197                // Check whether we've generated all 6 faces.
198                if(++this->faceCounter_ >= 6)
199                    this->bCreateFace_ = false;
200            }
201            // Cleanup after the successful creation of a skybox.
202            else if(this->bCleanup_)
203            {
204                // Reset the camera parameters.
205                camera->setAspectRatio(this->aspectRatio_);
206                camera->setFOVy(this->fovy_);
207                // Restore the render window.
208                this->restoreRenderWindow(renderWindow);
209                // Remove the log path from the standard resource group.
210                Ogre::ResourceGroupManager::getSingleton().removeResourceLocation(PathConfig::getInstance().getLogPathString(), Resource::getDefaultResourceGroup());
211               
212                // Reset the flow parameters for the next skybox generation.
213                this->bGenerateSkybox_ = false;
214                this->bSetup_ = true;
215                this->bWait_ = false;
216                this->bCreateFace_ = true;
217                this->bCleanup_ = true;
218                this->faceCounter_ = 0;
219               
220                // Display captions again.
221                CommandExecutor::execute("GametypeStatus displayCaption true");
222                this->bCaptionsRemoved_ = false;
223               
224                // Unpause.
225                CommandExecutor::execute("pause");
226               
227                COUT(3) << "Skybox with face size " << this->size_ << "x" << this->size_ << " pixels created. Storing in log/." << endl;
228            }
229        }
230    }
231   
232    /**
233    @brief
234        Set up the input camera to be ready to generate a skybox face.
235    @param camera
236        The camera to be set up.
237    */
238    void SkyboxGenerator::setupCamera(Ogre::Camera* camera)
239    {
240        camera->setFOVy(Degree(90));
241        camera->setAspectRatio(1.0);
242    }
243   
244    /**
245    @brief
246        Setup the input render window to be ready to generate the skybox.
247    @param renderWindow
248        The render window to be set up.
249    */
250    void SkyboxGenerator::setupRenderWindow(Ogre::RenderWindow* renderWindow)
251    {
252        // Store current window properties.
253        this->windowWidth_ = renderWindow->getWidth();
254        this->windowHeight_ = renderWindow->getHeight();
255        this->windowFullScreen_ = renderWindow->isFullScreen();
256        // Store current ScreenshotManager grid size.
257        this->gridSize_ = ScreenshotManager::getInstance().getGridSize();
258       
259        unsigned int size = this->size_;
260       
261        // If the desired skybox face size is bigger than what the current render window can accommodate we find a size that is a multiple of 256, that fits into the current render window adjust the grid size of the ScreenshotManager such that the screenshots generated are at least as big as we need.
262        if(this->windowHeight_ < this->size_ || this->windowWidth_ < this->size_)
263        {
264            unsigned int min = std::min(this->windowHeight_, this->windowWidth_);
265            unsigned int step = 256;
266            assert(min >= step);
267            size = step;
268            while(min >= size+step)
269                size += step;
270           
271            unsigned int gridSize = 1;
272            while(gridSize*size < this->size_)
273                gridSize++;
274           
275            renderWindow->setFullscreen(false, size, size);
276            ScreenshotManager::getInstance().setGridSize(gridSize);
277        }
278        else
279            ScreenshotManager::getInstance().setGridSize(1);
280
281    }
282   
283    /**
284    @brief
285        Restore the render window.
286        Reset the window size, reset the grid size of the ScreenshotManager.
287    @param renderWindow
288        The render window to be restored.
289    */
290    void SkyboxGenerator::restoreRenderWindow(Ogre::RenderWindow* renderWindow)
291    {
292        // Restore window size.
293        renderWindow->setFullscreen(this->windowFullScreen_, this->windowWidth_, this->windowHeight_);
294        // Restore grid size.
295        ScreenshotManager::getInstance().setGridSize(this->gridSize_);
296    }
297   
298    /**
299    @brief
300        Resizes and saves the input image under the input name.
301    @param image
302        A pointer to the image to be saved. The image is deleted afterwards,
303    @param name
304        The desired filename of the image.
305    */
306    void SkyboxGenerator::saveImage(Ogre::Image* image, const std::string& name) const
307    {
308        image->save(PathConfig::getInstance().getLogPathString()+name);
309        delete image;
310        // Loading the resizing, then saving again. This seems stupid, but resizing doesn't seem to work otherwise.
311        // If someone figures this out, feel free to adjust.
312        image = new Ogre::Image();
313        image->load(name, Resource::getDefaultResourceGroup());
314        image->resize(this->size_, this->size_);
315        image->save(PathConfig::getInstance().getLogPathString()+name);
316        delete image;
317        ScreenshotManager::getInstance().cleanup(); // Free memory in ScreenshotManager.
318    }
319}
Note: See TracBrowser for help on using the repository browser.