| 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 |  *      Reto Grieder | 
|---|
| 24 |  *   Co-authors: | 
|---|
| 25 |  *      ... | 
|---|
| 26 |  * | 
|---|
| 27 |  */ | 
|---|
| 28 |  | 
|---|
| 29 | #include "OrxonoxStableHeaders.h" | 
|---|
| 30 | #include "PhysicsTest.h" | 
|---|
| 31 |  | 
|---|
| 32 | #include <OgreStaticGeometry.h> | 
|---|
| 33 | #include <OgreSceneManager.h> | 
|---|
| 34 | #include <OgreEntity.h> | 
|---|
| 35 | #include "ogreode/OgreOde_Core.h" | 
|---|
| 36 | #include "ogreode/OgreOdeGeometry.h" | 
|---|
| 37 | #include "util/Convert.h" | 
|---|
| 38 | #include "core/CoreIncludes.h" | 
|---|
| 39 | #include "core/ConfigValueIncludes.h" | 
|---|
| 40 | #include "core/XMLPort.h" | 
|---|
| 41 | #include "GraphicsEngine.h" | 
|---|
| 42 | #include "Scene.h" | 
|---|
| 43 |  | 
|---|
| 44 | namespace orxonox | 
|---|
| 45 | { | 
|---|
| 46 |     CreateFactory(PhysicsTest); | 
|---|
| 47 |  | 
|---|
| 48 |     PhysicsTest::PhysicsTest(BaseObject* creator) | 
|---|
| 49 |         : BaseObject(creator) | 
|---|
| 50 |         , odeWorld_(0) | 
|---|
| 51 |         , odeSpace_(0) | 
|---|
| 52 |         , odeStepper_(0) | 
|---|
| 53 |         , odeGround_(0)    | 
|---|
| 54 |         , odeBody_(0) | 
|---|
| 55 |         , odeGeom_(0) | 
|---|
| 56 |         , sceneNode_(0) | 
|---|
| 57 |         , entity_(0) | 
|---|
| 58 |         , bRunning_(false) | 
|---|
| 59 |     { | 
|---|
| 60 |         RegisterObject(PhysicsTest); | 
|---|
| 61 |         setConfigValues(); | 
|---|
| 62 |         ModifyConfigValue(bRunning_, tset, false); | 
|---|
| 63 |     } | 
|---|
| 64 |  | 
|---|
| 65 |     PhysicsTest::~PhysicsTest() | 
|---|
| 66 |     { | 
|---|
| 67 |     } | 
|---|
| 68 |  | 
|---|
| 69 |     void PhysicsTest::setConfigValues() | 
|---|
| 70 |     { | 
|---|
| 71 |         SetConfigValue(bRunning_, false); | 
|---|
| 72 |     } | 
|---|
| 73 |  | 
|---|
| 74 |     /** | 
|---|
| 75 |     @brief | 
|---|
| 76 |         XML loading and saving. | 
|---|
| 77 |     @param | 
|---|
| 78 |         xmlelement The XML-element | 
|---|
| 79 |     @param | 
|---|
| 80 |         loading Loading (true) or saving (false) | 
|---|
| 81 |     @return | 
|---|
| 82 |         The XML-element | 
|---|
| 83 |     */ | 
|---|
| 84 |     void PhysicsTest::XMLPort(Element& xmlelement, XMLPort::Mode mode) | 
|---|
| 85 |     { | 
|---|
| 86 |         SUPER(PhysicsTest, XMLPort, xmlelement, mode); | 
|---|
| 87 |  | 
|---|
| 88 |         Ogre::SceneManager* sceneMgr = this->getScene()->getSceneManager(); | 
|---|
| 89 |  | 
|---|
| 90 |         // set up OgreOde | 
|---|
| 91 |  | 
|---|
| 92 |         odeWorld_ = new OgreOde::World(sceneMgr); | 
|---|
| 93 |         odeWorld_->setGravity(Vector3(0,-9.80665,0)); | 
|---|
| 94 |         odeWorld_->setCFM(10e-5); | 
|---|
| 95 |         odeWorld_->setERP(0.8); | 
|---|
| 96 |         odeWorld_->setAutoSleep(true); | 
|---|
| 97 |         odeWorld_->setAutoSleepAverageSamplesCount(10); | 
|---|
| 98 |         odeWorld_->setContactCorrectionVelocity(1.0); | 
|---|
| 99 |         odeSpace_ = odeWorld_->getDefaultSpace(); | 
|---|
| 100 |  | 
|---|
| 101 |  | 
|---|
| 102 |         // set up stepper | 
|---|
| 103 |  | 
|---|
| 104 |         const Ogre::Real _time_step = 0.5;http://isg.ee.ethz.ch/ | 
|---|
| 105 |         const Ogre::Real time_scale = Ogre::Real(1.7); | 
|---|
| 106 |         const Ogre::Real max_frame_time = Ogre::Real(1.0 / 4); | 
|---|
| 107 |         odeStepper_ = new OgreOde::StepHandler(odeWorld_, OgreOde::StepHandler::QuickStep, _time_step, | 
|---|
| 108 |             max_frame_time, time_scale); | 
|---|
| 109 |  | 
|---|
| 110 |  | 
|---|
| 111 |         // create a plane in x-z dimensions. | 
|---|
| 112 |  | 
|---|
| 113 |         odeGround_ = new OgreOde::InfinitePlaneGeometry(Ogre::Plane(Ogre::Vector3(0,1,0),0), | 
|---|
| 114 |             odeWorld_, odeWorld_->getDefaultSpace()); | 
|---|
| 115 |  | 
|---|
| 116 |         CollidingObject* collidingObject = new CollidingObject(); | 
|---|
| 117 |         odeGround_->setUserObject(static_cast<CollisionTestedObject*>(collidingObject)); | 
|---|
| 118 |  | 
|---|
| 119 |         // Use a load of meshes to represent the floor | 
|---|
| 120 |         int i = 0; | 
|---|
| 121 |         Ogre::StaticGeometry* floor; | 
|---|
| 122 |         floor = sceneMgr->createStaticGeometry("StaticFloor"); | 
|---|
| 123 |         floor->setRegionDimensions(Ogre::Vector3(160.0, 100.0, 160.0)); | 
|---|
| 124 |         // Set the region origin so the center is at 0 world | 
|---|
| 125 |         floor->setOrigin(Ogre::Vector3::ZERO); | 
|---|
| 126 |         for (Real z = -80.0; z <= 80.0; z += 20.0) | 
|---|
| 127 |         { | 
|---|
| 128 |             for (Real x = -80.0; x <= 80.0; x += 20.0) | 
|---|
| 129 |             { | 
|---|
| 130 |                 std::string name = std::string("Ground") + convertToString(i++); | 
|---|
| 131 |                 Ogre::Entity* entity = sceneMgr->createEntity(name, "plane.mesh"); | 
|---|
| 132 |                 entity->setQueryFlags (1<<4); | 
|---|
| 133 |                 entity->setUserObject(odeGround_); | 
|---|
| 134 |                 entity->setCastShadows(false); | 
|---|
| 135 |                 floor->addEntity(entity, Ogre::Vector3(x,0,z)); | 
|---|
| 136 |             } | 
|---|
| 137 |         }        | 
|---|
| 138 |  | 
|---|
| 139 |         floor->build(); | 
|---|
| 140 |  | 
|---|
| 141 |  | 
|---|
| 142 |         // create a hanging crate | 
|---|
| 143 |  | 
|---|
| 144 |         entity_ = sceneMgr->createEntity("crate","crate.mesh"); | 
|---|
| 145 |         entity_->setQueryFlags (1<<2); | 
|---|
| 146 |         sceneNode_ = sceneMgr->getRootSceneNode()->createChildSceneNode("crate"); | 
|---|
| 147 |         sceneNode_->attachObject(entity_); | 
|---|
| 148 |         entity_->setNormaliseNormals(true); | 
|---|
| 149 |         entity_->setCastShadows(true); | 
|---|
| 150 |  | 
|---|
| 151 |         odeBody_ = new OgreOde::Body(odeWorld_); | 
|---|
| 152 |         sceneNode_->attachObject(odeBody_); | 
|---|
| 153 |  | 
|---|
| 154 |          | 
|---|
| 155 |         // set size and mass of the crate | 
|---|
| 156 |  | 
|---|
| 157 |         Vector3 size(10.0, 10.0, 10.0); | 
|---|
| 158 |         odeMass_ = OgreOde::BoxMass(0.5, size); | 
|---|
| 159 |         odeMass_.setDensity(5.0, size); | 
|---|
| 160 |         odeGeom_ = new OgreOde::BoxGeometry(size, odeWorld_, odeSpace_); | 
|---|
| 161 |         sceneNode_->setScale(size.x * 0.1, size.y * 0.1, size.z * 0.1); | 
|---|
| 162 |         odeBody_->setMass(odeMass_); | 
|---|
| 163 |         odeGeom_->setBody(odeBody_); | 
|---|
| 164 |         entity_->setUserObject(odeGeom_); | 
|---|
| 165 |         odeGeom_->setUserObject(static_cast<CollisionTestedObject*>(this)); | 
|---|
| 166 |  | 
|---|
| 167 |  | 
|---|
| 168 |         odeBody_->setOrientation(Quaternion(Degree(30.0), Vector3(0,0,0))); | 
|---|
| 169 |         odeBody_->setPosition(Vector3(0,120,-20)); | 
|---|
| 170 |  | 
|---|
| 171 |     } | 
|---|
| 172 |  | 
|---|
| 173 |     void PhysicsTest::tick(float dt) | 
|---|
| 174 |     { | 
|---|
| 175 |         // only update physics in a certain interval | 
|---|
| 176 |         if (this->bRunning_ && odeStepper_->step(dt)) | 
|---|
| 177 |             odeWorld_->synchronise(); | 
|---|
| 178 |     } | 
|---|
| 179 |  | 
|---|
| 180 |     bool PhysicsTest::collision(OgreOde::Contact* contact) | 
|---|
| 181 |     { | 
|---|
| 182 |         // Check for collisions between things that are connected and ignore them | 
|---|
| 183 |         OgreOde::Geometry * const g1 = contact->getFirstGeometry(); | 
|---|
| 184 |         OgreOde::Geometry * const g2 = contact->getSecondGeometry(); | 
|---|
| 185 |  | 
|---|
| 186 |         if (g1 && g2) | 
|---|
| 187 |         { | 
|---|
| 188 |             const OgreOde::Body * const b1 = g2->getBody(); | 
|---|
| 189 |             const OgreOde::Body * const b2 = g1->getBody(); | 
|---|
| 190 |             if (b1 && b2 && OgreOde::Joint::areConnected(b1, b2))  | 
|---|
| 191 |                 return false;  | 
|---|
| 192 |         } | 
|---|
| 193 |  | 
|---|
| 194 |         //set contact parameters: | 
|---|
| 195 |         contact->setBouncyness(1.0); | 
|---|
| 196 |         contact->setCoulombFriction(OgreOde::Utility::Infinity); | 
|---|
| 197 |         contact->setForceDependentSlip(1.0); | 
|---|
| 198 |         contact->setAdditionalFDS(1.0); | 
|---|
| 199 |  | 
|---|
| 200 |         // we have 2 collidable objects from our object system, if one of the Collide function returns false, e return false in this method, too, else we return true, so ode computes a normal collision. | 
|---|
| 201 |         // true means ode will treat this like a normal collison => rigid body behavior | 
|---|
| 202 |         // false means ode will not treat this collision at all => objects ignore each other | 
|---|
| 203 |  | 
|---|
| 204 |         bool res = true; | 
|---|
| 205 |  | 
|---|
| 206 |         if (g1->getUserObject()) | 
|---|
| 207 |             if (!static_cast<CollisionTestedObject*>(g1->getUserObject())->collide(true, contact)) | 
|---|
| 208 |                 res = false; | 
|---|
| 209 |  | 
|---|
| 210 |         if (g2->getUserObject()) | 
|---|
| 211 |             if (!static_cast<CollisionTestedObject*>(g2->getUserObject())->collide(false, contact)) | 
|---|
| 212 |                 res = false; | 
|---|
| 213 |  | 
|---|
| 214 |         return res; | 
|---|
| 215 |     } | 
|---|
| 216 |  | 
|---|
| 217 |     bool CollidingObject::Collide(bool MineIsFirst, OgreOde::Contact* contact) | 
|---|
| 218 |     { | 
|---|
| 219 |         contact->setForceDependentSlip(contact->getForceDependentSlip() * ForceDependentSlip); | 
|---|
| 220 |         contact->setAdditionalFDS(contact->getForceDependentSlip2() * ForceDependentSlip); | 
|---|
| 221 |         contact->setCoulombFriction(contact->getCoulombFrictionMu() * Friction); | 
|---|
| 222 |         contact->setBouncyness(contact->getBouncyness() * Bouncyness, contact->getBouncynessVelocity() * BounceVelocity); | 
|---|
| 223 |         return true; | 
|---|
| 224 |     } | 
|---|
| 225 |  | 
|---|
| 226 | } | 
|---|