Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10777 was 10624, checked in by landauf, 9 years ago

merged branch core7 back to trunk

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