Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8296 was 8234, checked in by rgrieder, 14 years ago

Removed 6 MSVC warnings about conversions.

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