Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/physics/src/orxonox/objects/Scene.cc @ 2313

Last change on this file since 2313 was 2313, checked in by rgrieder, 15 years ago

Added body queue to Scene: Physical objects now request to be added to the physical world.

  • Property svn:eol-style set to native
File size: 8.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 *      Reto Grieder (physics)
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "Scene.h"
31
32#include <OgreRoot.h>
33#include <OgreSceneManagerEnumerator.h>
34#include <OgreSceneNode.h>
35#include <OgreLight.h>
36
37#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
38#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
39#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
40#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
41
42#include "core/CoreIncludes.h"
43#include "core/Core.h"
44#include "core/XMLPort.h"
45#include "objects/worldentities/WorldEntity.h"
46
47namespace orxonox
48{
49    CreateFactory(Scene);
50
51    Scene::Scene(BaseObject* creator) : BaseObject(creator), network::Synchronisable(creator)
52    {
53        RegisterObject(Scene);
54
55        this->setScene(this);
56        this->bShadows_ = false;
57
58        if (Core::showsGraphics())
59        {
60            if (Ogre::Root::getSingletonPtr())
61            {
62                this->sceneManager_ = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
63                this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
64            }
65            else
66            {
67                this->sceneManager_ = 0;
68                this->rootSceneNode_ = 0;
69            }
70        }
71        else
72        {
73            // create a dummy SceneManager of our own since we don't have Ogre::Root.
74            this->sceneManager_ = new Ogre::DefaultSceneManager("");
75            this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
76        }
77
78        // No physics for default
79        this->physicalWorld_ = 0;
80
81        // test test test
82        if (Core::showsGraphics() && this->sceneManager_)
83        {
84            Ogre::Light* light;
85            light = this->sceneManager_->createLight("Light-1");
86            light->setType(Ogre::Light::LT_DIRECTIONAL);
87            light->setDiffuseColour(ColourValue(1.0, 0.9, 0.6, 1.0));
88            light->setSpecularColour(ColourValue(1.0, 0.9, 0.6, 1.0));
89            light->setDirection(1, -0.3, 0.3);
90        }
91        // test test test
92
93        this->registerVariables();
94    }
95
96    Scene::~Scene()
97    {
98        if (this->isInitialized())
99        {
100            if (Ogre::Root::getSingletonPtr())
101            {
102                Ogre::Root::getSingleton().destroySceneManager(this->sceneManager_);
103            }
104            else if (!Core::showsGraphics())
105            {
106                delete this->sceneManager_;
107            }
108        }
109    }
110
111    void Scene::XMLPort(Element& xmlelement, XMLPort::Mode mode)
112    {
113        SUPER(Scene, XMLPort, xmlelement, mode);
114
115        XMLPortParam(Scene, "skybox", setSkybox, getSkybox, xmlelement, mode);
116        XMLPortParam(Scene, "ambientlight", setAmbientLight, getAmbientLight, xmlelement, mode).defaultValues(ColourValue(0.2, 0.2, 0.2, 1));
117        XMLPortParam(Scene, "shadow", setShadow, getShadow, xmlelement, mode).defaultValues(true);
118
119        const int defaultMaxWorldSize = 100000;
120        Vector3 worldAabbMin(-defaultMaxWorldSize, -defaultMaxWorldSize, -defaultMaxWorldSize);
121        Vector3 worldAabbMax( defaultMaxWorldSize,  defaultMaxWorldSize,  defaultMaxWorldSize);
122        XMLPortParamVariable(Scene, "negativeWorldRange", worldAabbMin, xmlelement, mode);
123        XMLPortParamVariable(Scene, "positiveWorldRange", worldAabbMax, xmlelement, mode);
124        XMLPortParam(Scene, "hasPhysics", setPhysicalWorld, hasPhysics, xmlelement, mode).defaultValue(0, true).defaultValue(1, worldAabbMin).defaultValue(2, worldAabbMax);
125
126        XMLPortObjectExtended(Scene, BaseObject, "", addObject, getObject, xmlelement, mode, true, false);
127    }
128
129    void Scene::registerVariables()
130    {
131        REGISTERSTRING(this->skybox_,     network::direction::toclient, new network::NetworkCallback<Scene>(this, &Scene::networkcallback_applySkybox));
132        REGISTERDATA(this->ambientLight_, network::direction::toclient, new network::NetworkCallback<Scene>(this, &Scene::networkcallback_applyAmbientLight));
133    }
134
135    void Scene::setPhysicalWorld(bool wantPhysics, const Vector3& worldAabbMin, const Vector3& worldAabbMax)
136    {
137        if (wantPhysics && !hasPhysics())
138        {
139            btVector3 worldAabbMin(worldAabbMin.x, worldAabbMin.y, worldAabbMin.z);
140            btVector3 worldAabbMax(worldAabbMax.x, worldAabbMax.y, worldAabbMax.z);
141
142            btDefaultCollisionConfiguration*     collisionConfig = new btDefaultCollisionConfiguration();
143            btCollisionDispatcher*               dispatcher      = new btCollisionDispatcher(collisionConfig);
144            bt32BitAxisSweep3*                   broadphase      = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax);
145            btSequentialImpulseConstraintSolver* solver          = new btSequentialImpulseConstraintSolver;
146
147            this->physicalWorld_ =  new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfig);
148
149            // Disable Gravity for space
150            this->physicalWorld_->setGravity(btVector3(0,0,0));
151        }
152        else
153        {
154            // TODO: Destroy Bullet physics
155        }
156    }
157
158    void Scene::tick(float dt)
159    {
160        if (physicalWorld_)
161        {
162            if (this->physicsQueue_.size() > 0)
163            {
164                // Add all scheduled WorldEntities
165                for (std::set<btRigidBody*>::const_iterator it = this->physicsQueue_.begin();
166                    it != this->physicsQueue_.end(); ++it)
167                {
168                    if (!(*it)->isInWorld())
169                        this->physicalWorld_->addRigidBody(*it);
170                }
171                this->physicsQueue_.clear();
172            }
173
174            // TODO: This is not stable! If physics cannot be calculated real time anymore,
175            //       framerate will drop exponentially.
176            physicalWorld_->stepSimulation(dt,(int)(dt/0.0166666f + 1.0f));
177        }
178    }
179
180    void Scene::setSkybox(const std::string& skybox)
181    {
182        if (Core::showsGraphics() && this->sceneManager_)
183            this->sceneManager_->setSkyBox(true, skybox);
184
185        this->skybox_ = skybox;
186    }
187
188    void Scene::setAmbientLight(const ColourValue& colour)
189    {
190        if (Core::showsGraphics() && this->sceneManager_)
191            this->sceneManager_->setAmbientLight(colour);
192
193        this->ambientLight_ = colour;
194    }
195
196    void Scene::setShadow(bool bShadow)
197    {
198        if (Core::showsGraphics() && this->sceneManager_)
199        {
200            if (bShadow)
201                this->sceneManager_->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
202            else
203                this->sceneManager_->setShadowTechnique(Ogre::SHADOWTYPE_NONE);
204        }
205
206        this->bShadows_ = bShadow;
207    }
208
209    void Scene::addObject(BaseObject* object)
210    {
211        this->objects_.push_back(object);
212        object->setScene(this);
213    }
214
215    BaseObject* Scene::getObject(unsigned int index) const
216    {
217        unsigned int i = 0;
218        for (std::list<BaseObject*>::const_iterator it = this->objects_.begin(); it != this->objects_.end(); ++it)
219        {
220            if (i == index)
221                return (*it);
222            ++i;
223        }
224        return 0;
225    }
226
227    void Scene::addRigidBody(btRigidBody* body)
228    {
229        if (!this->physicalWorld_)
230            COUT(1) << "Error: Cannot WorldEntity body to physical Scene: No physics." << std::endl;
231        else if (body)
232            this->physicsQueue_.insert(body);
233    }
234
235    void Scene::removeRigidBody(btRigidBody* body)
236    {
237        if (!this->physicalWorld_)
238            COUT(1) << "Error: Cannot WorldEntity body to physical Scene: No physics." << std::endl;
239        else if (body)
240        {
241            this->physicalWorld_->removeRigidBody(body);
242            // Also check queue
243            std::set<btRigidBody*>::iterator it = this->physicsQueue_.find(body);
244            if (it != this->physicsQueue_.end())
245                this->physicsQueue_.erase(it);
246        }
247    }
248}
Note: See TracBrowser for help on using the repository browser.