Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel3/src/orxonox/graphics/Camera.cc @ 8637

Last change on this file since 8637 was 8079, checked in by landauf, 14 years ago

merged usability branch back to trunk

incomplete summary of the changes in this branch:

  • enhanced keyboard navigation in GUIs
  • implemented new graphics menu and changeable window size at runtime
  • added developer mode
  • HUD shows if game is paused, game pauses if ingame menu is opened
  • removed a few obsolete commands and hid some that are more for internal use
  • numpad works in console and gui
  • faster loading of level info
  • enhanced usage of compositors (Shader class)
  • improved camera handling, configurable FOV and aspect ratio
  • Property svn:eol-style set to native
File size: 7.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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      Benjamin Knecht
26 *
27 */
28
29#include "Camera.h"
30
31#include <algorithm>
32#include <OgreCamera.h>
33#include <OgreSceneManager.h>
34#include <OgreSceneNode.h>
35
36#include "util/Exception.h"
37#include "util/StringUtils.h"
38#include "core/CoreIncludes.h"
39#include "core/ConfigValueIncludes.h"
40#include "core/GameMode.h"
41#include "core/GUIManager.h"
42#include "Scene.h"
43#include "CameraManager.h"
44#include "sound/SoundManager.h"
45
46namespace orxonox
47{
48    CreateFactory(Camera);
49
50    Camera::Camera(BaseObject* creator) : StaticEntity(creator)
51    {
52        RegisterObject(Camera);
53
54        if (!GameMode::showsGraphics())
55            ThrowException(AbortLoading, "Can't create Camera, no graphics.");
56        if (!this->getScene())
57            ThrowException(AbortLoading, "Can't create Camera, no scene.");
58        if (!this->getScene()->getSceneManager())
59            ThrowException(AbortLoading, "Can't create Camera, no scene-manager given.");
60        if (!this->getScene()->getRootSceneNode())
61            ThrowException(AbortLoading, "Can't create Camera, no root-scene-node given.");
62
63        this->camera_ = this->getScene()->getSceneManager()->createCamera(getUniqueNumberString());
64        static_cast<Ogre::MovableObject*>(this->camera_)->setUserAny(Ogre::Any(static_cast<OrxonoxClass*>(this)));
65        this->cameraNode_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
66        this->attachNode(this->cameraNode_);
67        this->cameraNode_->attachObject(this->camera_);
68
69        this->bHasFocus_ = false;
70        this->bDrag_ = false;
71        this->lastDtLagged_ = false;
72
73        this->setSyncMode(0x0);
74
75        this->setConfigValues();
76
77        this->configvaluecallback_changedFovAndAspectRatio();
78        this->configvaluecallback_changedNearClipDistance();
79    }
80
81    Camera::~Camera()
82    {
83        if (this->isInitialized())
84        {
85            this->releaseFocus();
86
87            this->cameraNode_->detachAllObjects();
88            this->getScene()->getSceneManager()->destroyCamera(this->camera_);
89
90            if (this->bDrag_)
91                this->detachNode(this->cameraNode_);
92
93            if (this->getScene()->getSceneManager())
94                this->getScene()->getSceneManager()->destroySceneNode(this->cameraNode_->getName());
95        }
96    }
97
98    void Camera::setConfigValues()
99    {
100        SetConfigValue(fov_, 80.0f)
101            .description("Horizontal field of view in degrees")
102            .callback(this, &Camera::configvaluecallback_changedFovAndAspectRatio);
103        SetConfigValue(aspectRatio_, 1.0f)
104            .description("Aspect ratio of pixels (width / height)")
105            .callback(this, &Camera::configvaluecallback_changedFovAndAspectRatio);
106        SetConfigValue(nearClipDistance_, 1.0f)
107            .description("Distance from the camera where close objects will be clipped")
108            .callback(this, &Camera::configvaluecallback_changedNearClipDistance);
109    }
110
111    /**
112        @brief Update FOV and the aspect ratio of the camera after the config values or the window's size have changed.
113    */
114    void Camera::configvaluecallback_changedFovAndAspectRatio()
115    {
116        // the aspect ratio of the window (width / height) has to be multiplied with the pixels aspect ratio (this->aspectRatio_)
117        float aspectRatio = this->aspectRatio_ * this->getWindowWidth() / this->getWindowHeight();
118        this->camera_->setAspectRatio(aspectRatio);
119
120        // Since we use horizontal FOV, we have to calculate FOVy by dividing by the aspect ratio and using some tangents
121        Radian fovy(2 * atan(tan(Degree(this->fov_).valueRadians() / 2) / aspectRatio));
122        this->camera_->setFOVy(fovy);
123    }
124
125    void Camera::configvaluecallback_changedNearClipDistance()
126    {
127        this->camera_->setNearClipDistance(this->nearClipDistance_);
128    }
129
130    /**
131        @brief Inherited from WindowEventListener.
132    */
133    void Camera::windowResized(unsigned int newWidth, unsigned int newHeight)
134    {
135        this->configvaluecallback_changedFovAndAspectRatio();
136    }
137
138    void Camera::tick(float dt)
139    {
140        SUPER(Camera, tick, dt);
141
142        if (this->bDrag_ && this->getTimeFactor() != 0)
143        {
144            // this stuff here may need some adjustments
145            float poscoeff = 15.0f * dt / this->getTimeFactor();
146            float anglecoeff = 7.0f * dt / this->getTimeFactor();
147            // Only clamp if fps rate is actually falling. Occasional high dts should
148            // not be clamped to reducing lagging effects.
149            if (poscoeff > 1.0f)
150            {
151                if (this->lastDtLagged_)
152                    poscoeff = 1.0f;
153                else
154                    this->lastDtLagged_ = true;
155            }
156            else
157                this->lastDtLagged_ = false;
158
159            if (anglecoeff > 1.0f)
160            {
161                if (this->lastDtLagged_)
162                    anglecoeff = 1.0f;
163                else
164                    this->lastDtLagged_ = true;
165            }
166            else
167                this->lastDtLagged_ = false;
168
169            Vector3 offset = this->getWorldPosition() - this->cameraNode_->_getDerivedPosition();
170            this->cameraNode_->translate(poscoeff * offset);
171
172            this->cameraNode_->setOrientation(Quaternion::Slerp(anglecoeff, this->cameraNode_->_getDerivedOrientation(), this->getWorldOrientation(), true));
173        }
174
175        // Update sound listener transformation
176        if (GameMode::playsSound() && this->bHasFocus_)
177        {
178            SoundManager::getInstance().setListenerPosition(this->getWorldPosition());
179            SoundManager::getInstance().setListenerOrientation(this->getWorldOrientation());
180        }
181    }
182
183    void Camera::requestFocus()
184    {
185        CameraManager::getInstance().requestFocus(this);
186    }
187
188    void Camera::releaseFocus()
189    {
190        CameraManager::getInstance().releaseFocus(this);
191    }
192
193    /**
194        what to do when camera loses focus (do not request focus in this function!!)
195        this is called by the CameraManager singleton class to notify the camera
196    */
197    void Camera::removeFocus()
198    {
199        this->bHasFocus_ = false;
200    }
201
202    void Camera::setFocus()
203    {
204        this->bHasFocus_ = true;
205        CameraManager::getInstance().useCamera(this->camera_);
206    }
207
208    void Camera::setDrag(bool bDrag)
209    {
210        if (bDrag != this->bDrag_)
211        {
212            this->bDrag_ = bDrag;
213
214            if (!bDrag)
215            {
216                this->attachNode(this->cameraNode_);
217                this->cameraNode_->setPosition(Vector3::ZERO);
218                this->cameraNode_->setOrientation(Quaternion::IDENTITY);
219            }
220            else
221            {
222                this->detachNode(this->cameraNode_);
223                this->cameraNode_->setPosition(this->getWorldPosition());
224                this->cameraNode_->setOrientation(this->getWorldOrientation());
225            }
226        }
227    }
228}
Note: See TracBrowser for help on using the repository browser.