[21] | 1 | /* |
---|
| 2 | SimpleScenes_RagDoll.h |
---|
| 3 | --------------------- |
---|
| 4 | A demo RagDoll shooting demo, showing ragdolls and ray intersections. |
---|
| 5 | */ |
---|
| 6 | #ifndef _SIMPLESCENES_ZOMBIE_H_ |
---|
| 7 | #define _SIMPLESCENES_ZOMBIE_H_ |
---|
| 8 | |
---|
| 9 | static const String xmlNames[] = { |
---|
| 10 | "zombie", |
---|
| 11 | "zombie", |
---|
| 12 | "ninja", |
---|
| 13 | "robot", |
---|
| 14 | "GingerBreadMan" |
---|
| 15 | }; |
---|
| 16 | static const String meshNames[] = { |
---|
| 17 | "zombie_small.mesh", |
---|
| 18 | "zombie_small.mesh", |
---|
| 19 | "ninja.mesh", |
---|
| 20 | "robot.mesh", |
---|
| 21 | "GingerBreadMan.mesh" |
---|
| 22 | }; |
---|
| 23 | static const String meshAnimation [] = { |
---|
| 24 | "Walk1", |
---|
| 25 | "Walk1", |
---|
| 26 | "Walk", |
---|
| 27 | "Walk", |
---|
| 28 | "Walk1" |
---|
| 29 | }; |
---|
| 30 | static const Ogre::Vector3 meshScale [] = { |
---|
| 31 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
| 32 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
| 33 | Ogre::Vector3(0.02, 0.02, 0.02), |
---|
| 34 | Ogre::Vector3(0.05, 0.05, 0.05), |
---|
| 35 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
| 36 | }; |
---|
| 37 | static const String ragdollFile [] = { |
---|
| 38 | "zombie.ogreode", |
---|
| 39 | "zombie_auto.ogreode", |
---|
| 40 | "ninja.ogreode", |
---|
| 41 | "robot.ogreode", |
---|
| 42 | "gingerbreadman.ogreode" |
---|
| 43 | }; |
---|
| 44 | static size_t sSelectedMesh = 4; |
---|
| 45 | |
---|
| 46 | #ifdef _DEBUG |
---|
| 47 | static size_t sMaxRagdoll = 10; |
---|
| 48 | #else //_DEBUG |
---|
| 49 | static size_t sMaxRagdoll = 30; |
---|
| 50 | #endif //_DEBUG |
---|
| 51 | |
---|
| 52 | /* |
---|
| 53 | The zombie demo extends the base test class |
---|
| 54 | */ |
---|
| 55 | class SimpleScenes_Zombie:public SimpleScenes |
---|
| 56 | { |
---|
| 57 | private: |
---|
| 58 | typedef std::list<OgreOde_Prefab::Ragdoll *> RagDollList; |
---|
| 59 | |
---|
| 60 | struct ragDollData |
---|
| 61 | { |
---|
| 62 | int sSelectedMesh; |
---|
| 63 | Ogre::Real timeSinceBirth; |
---|
| 64 | Ogre::Real timeSincePhysical; |
---|
| 65 | }; |
---|
| 66 | |
---|
| 67 | public: |
---|
| 68 | void createRagDoll() |
---|
| 69 | { |
---|
| 70 | |
---|
| 71 | _last_ragdoll = 0.0; |
---|
| 72 | |
---|
| 73 | OgreOde_Prefab::Ragdoll *ragdoll = static_cast <OgreOde_Prefab::Ragdoll *> (dotOgreOdeLoader->loadObject(ragdollFile[sSelectedMesh], |
---|
| 74 | xmlNames[sSelectedMesh], |
---|
| 75 | "zombie" + StringConverter::toString(_ragdoll_count++))); |
---|
| 76 | |
---|
| 77 | |
---|
| 78 | |
---|
| 79 | ragdoll->setCastShadows(true); |
---|
| 80 | ragdoll->setQueryFlags (ZOMBIE_QUERY_MASK); |
---|
| 81 | |
---|
| 82 | Any a = ragdoll->getUserAny (); |
---|
| 83 | assert (a.isEmpty ()); |
---|
| 84 | { |
---|
| 85 | ragDollData *b = new ragDollData (); |
---|
| 86 | |
---|
| 87 | b->timeSinceBirth = 0.0f; |
---|
| 88 | b->timeSincePhysical = 0.0f; |
---|
| 89 | b->sSelectedMesh = sSelectedMesh; |
---|
| 90 | |
---|
| 91 | |
---|
| 92 | Any *newA = new Any(b); |
---|
| 93 | ragdoll->setUserAny (*newA); |
---|
| 94 | } |
---|
| 95 | |
---|
| 96 | |
---|
| 97 | // Add entity to the scene node |
---|
| 98 | SceneNode *ragdoll_node = _mgr->getRootSceneNode()->createChildSceneNode(ragdoll->getName() + "Node"); |
---|
| 99 | ragdoll_node->attachObject(ragdoll); |
---|
| 100 | ragdoll_node->yaw(Degree(rand() % 360)); |
---|
| 101 | ragdoll_node->setPosition(0.0,0.0,0); |
---|
| 102 | ragdoll_node->setScale( meshScale[sSelectedMesh]); |
---|
| 103 | |
---|
| 104 | _last_node = ragdoll_node; |
---|
| 105 | |
---|
| 106 | |
---|
| 107 | ragdoll->getAnimationState(meshAnimation[sSelectedMesh])->setEnabled(true); |
---|
| 108 | |
---|
| 109 | myRagDolls.push_back (ragdoll); |
---|
| 110 | |
---|
| 111 | |
---|
| 112 | //sSelectedMesh = (sSelectedMesh + 1) % 4; |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | // Constructor |
---|
| 116 | SimpleScenes_Zombie(OgreOde::World *world) : |
---|
| 117 | SimpleScenes(world) |
---|
| 118 | { |
---|
| 119 | _over = (Overlay*)OverlayManager::getSingleton().getByName("OgreOdeDemos/Target"); |
---|
| 120 | _over->show(); |
---|
| 121 | |
---|
| 122 | _gun = _mgr->createEntity("gun","gun.mesh"); |
---|
| 123 | _gun->setCastShadows(false); |
---|
| 124 | |
---|
| 125 | _gun_node = _mgr->getRootSceneNode()->createChildSceneNode("gun"); |
---|
| 126 | _gun_node->attachObject(_gun); |
---|
| 127 | |
---|
| 128 | _camera = _mgr->getCamera("PlayerCam"); |
---|
| 129 | |
---|
| 130 | _animation_speed = 1.0; |
---|
| 131 | _ragdoll_count = 0; |
---|
| 132 | createRagDoll(); |
---|
| 133 | |
---|
| 134 | _shot_time = 0.0; |
---|
| 135 | |
---|
| 136 | myOdeRay = new OgreOde::RayGeometry(1000.0, _world, _space); |
---|
| 137 | mRayQuery = _mgr->createRayQuery(Ray()); |
---|
| 138 | mRayQuery->setQueryMask (ZOMBIE_QUERY_MASK); |
---|
| 139 | mRayQuery->setQueryTypeMask(SceneManager::ENTITY_TYPE_MASK); |
---|
| 140 | } |
---|
| 141 | |
---|
| 142 | // Destructor |
---|
| 143 | virtual ~SimpleScenes_Zombie() |
---|
| 144 | { |
---|
| 145 | for ( RagDollList::iterator zE = myRagDolls.begin(); |
---|
| 146 | zE != myRagDolls.end(); ++zE) |
---|
| 147 | { |
---|
| 148 | assert ((*zE)->getParentNode ()); |
---|
| 149 | assert ((*zE)->getParentNode ()->getParent()); |
---|
| 150 | (static_cast<SceneNode*> ((*zE)->getParentNode ()->getParent()))->removeAndDestroyChild( |
---|
| 151 | (*zE)->getParentNode ()->getName ()); |
---|
| 152 | _mgr->destroyMovableObject((*zE)->getName(), OgreOde_Prefab::RagdollFactory::FACTORY_TYPE_NAME); |
---|
| 153 | |
---|
| 154 | } |
---|
| 155 | delete myOdeRay; |
---|
| 156 | |
---|
| 157 | _over->hide(); |
---|
| 158 | _mgr->destroySceneNode("gun"); |
---|
| 159 | _mgr->destroyEntity("gun"); |
---|
| 160 | _mgr->destroyQuery (mRayQuery); |
---|
| 161 | } |
---|
| 162 | |
---|
| 163 | // Return our name for the test application to display |
---|
| 164 | virtual const String& getName() |
---|
| 165 | { |
---|
| 166 | static String name = "RagDoll Shooting Gallery"; |
---|
| 167 | return name; |
---|
| 168 | } |
---|
| 169 | |
---|
| 170 | // Return a description of the keys that the user can use in this test |
---|
| 171 | virtual const String& getKeys() |
---|
| 172 | { |
---|
| 173 | static String keys = "X - Shoot"; |
---|
| 174 | return keys; |
---|
| 175 | } |
---|
| 176 | |
---|
| 177 | |
---|
| 178 | #if (OGRE_VERSION_MINOR < 4) |
---|
| 179 | virtual void frameStarted(Real time, InputReader* input) |
---|
| 180 | #else |
---|
| 181 | virtual void frameStarted(Real time, OIS::Keyboard* input, OIS::Mouse* mouse) |
---|
| 182 | #endif //OGRE_VERSION not heihort |
---|
| 183 | { |
---|
| 184 | _last_ragdoll += time; |
---|
| 185 | |
---|
| 186 | // Do default key handling |
---|
| 187 | #if (OGRE_VERSION_MINOR < 4) |
---|
| 188 | SimpleScenes::frameEnded(time, input); |
---|
| 189 | #else |
---|
| 190 | SimpleScenes::frameEnded(time, input, mouse); |
---|
| 191 | #endif //OGRE_VERSION not heihort |
---|
| 192 | |
---|
| 193 | _gun_node->setOrientation(_camera->getOrientation()); |
---|
| 194 | _gun_node->setPosition(_camera->getPosition() + (_camera->getOrientation() * Ogre::Vector3(0.3,-0.15,-1.1))); |
---|
| 195 | |
---|
| 196 | for ( RagDollList::iterator zE = myRagDolls.begin(); |
---|
| 197 | zE != myRagDolls.end(); |
---|
| 198 | ++zE) |
---|
| 199 | { |
---|
| 200 | ragDollData *b = any_cast<ragDollData *> ((*zE)->getUserAny()); |
---|
| 201 | if ((*zE)->isPhysical()) |
---|
| 202 | { |
---|
| 203 | if (!(*zE)->isStatic()) |
---|
| 204 | { |
---|
| 205 | |
---|
| 206 | b->timeSincePhysical += time; |
---|
| 207 | (*zE)->update();// RagDoll Activated |
---|
| 208 | } |
---|
| 209 | } |
---|
| 210 | else |
---|
| 211 | { |
---|
| 212 | (*zE)->getAnimationState(meshAnimation[b->sSelectedMesh])->addTime(time * _animation_speed); |
---|
| 213 | |
---|
| 214 | (*zE)->getParentNode ()->translate( |
---|
| 215 | (*zE)->getParentNode ()->getOrientation() * (Vector3::UNIT_Z * time * 2.5)); |
---|
| 216 | |
---|
| 217 | } |
---|
| 218 | } |
---|
| 219 | |
---|
| 220 | } |
---|
| 221 | |
---|
| 222 | |
---|
| 223 | #if (OGRE_VERSION_MINOR < 4) |
---|
| 224 | // Handle the user's key presses |
---|
| 225 | virtual void frameEnded(Real time,InputReader* input) |
---|
| 226 | { |
---|
| 227 | // Do default key handling |
---|
| 228 | SimpleScenes::frameEnded(time,input); |
---|
| 229 | #else |
---|
| 230 | |
---|
| 231 | virtual void frameEnded(Real time, OIS::Keyboard* input, OIS::Mouse* mouse) |
---|
| 232 | { |
---|
| 233 | // Do default processing |
---|
| 234 | SimpleScenes::frameEnded(time, input, mouse); |
---|
| 235 | #endif |
---|
| 236 | _shot_time -= time; |
---|
| 237 | |
---|
| 238 | if (_key_delay > 0 && |
---|
| 239 | input->isKeyDown(KC_C)) |
---|
| 240 | { |
---|
| 241 | for ( RagDollList::iterator zE = myRagDolls.begin(); |
---|
| 242 | zE != myRagDolls.end(); |
---|
| 243 | ++zE) |
---|
| 244 | { |
---|
| 245 | if ((*zE)->isPhysical()) |
---|
| 246 | { |
---|
| 247 | (*zE)->releasePhysicalControl(); |
---|
| 248 | ragDollData *b = any_cast<ragDollData *> ((*zE)->getUserAny()); |
---|
| 249 | (*zE)->getAnimationState(meshAnimation[b->sSelectedMesh])->setEnabled(true); |
---|
| 250 | } |
---|
| 251 | } |
---|
| 252 | |
---|
| 253 | _key_delay = SimpleScenes::KEY_DELAY; |
---|
| 254 | } |
---|
| 255 | |
---|
| 256 | |
---|
| 257 | |
---|
| 258 | if (_shot_time <= 0.0 && |
---|
| 259 | #if (OGRE_VERSION_MINOR < 4) |
---|
| 260 | (input->isKeyDown(KC_X) || input->getMouseButton (0))) |
---|
| 261 | #else |
---|
| 262 | ( input->isKeyDown(KC_X) || mouse->getMouseState().buttonDown(OIS::MB_Left))) |
---|
| 263 | #endif |
---|
| 264 | { |
---|
| 265 | |
---|
| 266 | Ray pickRay = _camera->getCameraToViewportRay(0.5, 0.5); |
---|
| 267 | myOdeRay->setDefinition(pickRay.getOrigin(), pickRay.getDirection()); |
---|
| 268 | |
---|
| 269 | _shot_time = 0.2; |
---|
| 270 | |
---|
| 271 | mRayQuery->setRay (pickRay); |
---|
| 272 | const RaySceneQueryResult& result = mRayQuery->execute(); |
---|
| 273 | if (!result.empty()) |
---|
| 274 | { |
---|
| 275 | RaySceneQueryResult::const_iterator i = result.begin(); |
---|
| 276 | |
---|
| 277 | //mRayQuery->setSortByDistance (true, 1);//only one hit |
---|
| 278 | myOdeRay->enable (); |
---|
| 279 | while((i != result.end())) |
---|
| 280 | { |
---|
| 281 | |
---|
| 282 | _last_ragdoll = 5.0; |
---|
| 283 | |
---|
| 284 | OgreOde_Prefab::Ragdoll * const radgoll = |
---|
| 285 | static_cast<OgreOde_Prefab::Ragdoll *> (i->movable); |
---|
| 286 | |
---|
| 287 | // uncomment to see nice debug mesh of animated mesh |
---|
| 288 | //#define _TESTTRIMESH |
---|
| 289 | #ifdef _TESTTRIMESH |
---|
| 290 | |
---|
| 291 | // ray cast could be tested against that instead of ragdoll. |
---|
| 292 | // depending on complexity of mesh could be simpler |
---|
| 293 | OgreOde::EntityInformer ei((*zE), (*zE)->getParentNode ()->_getFullTransform()); |
---|
| 294 | _geoms.push_back(ei.createStaticTriangleMesh(_space)); |
---|
| 295 | #else //_TESTTRIMESH |
---|
| 296 | bool wasPhysical = radgoll->isPhysical (); |
---|
| 297 | if (!wasPhysical) |
---|
| 298 | { |
---|
| 299 | ragDollData * const b = any_cast<ragDollData *> (radgoll->getUserAny()); |
---|
| 300 | radgoll->getAnimationState(meshAnimation[b->sSelectedMesh])->setEnabled(false); |
---|
| 301 | |
---|
| 302 | |
---|
| 303 | // Create the ragdoll |
---|
| 304 | radgoll->takePhysicalControl(_world, _space, false); |
---|
| 305 | radgoll->setSelfCollisions(false); |
---|
| 306 | |
---|
| 307 | } |
---|
| 308 | |
---|
| 309 | |
---|
| 310 | OgreOde::Body *hit_body; |
---|
| 311 | Ogre::Vector3 hit_point; |
---|
| 312 | |
---|
| 313 | bool is_hit = false; |
---|
| 314 | if (radgoll->pick(myOdeRay, hit_body, hit_point)) |
---|
| 315 | { |
---|
| 316 | if (hit_body) |
---|
| 317 | { |
---|
| 318 | hit_body->addForceAt(pickRay.getDirection() * 250000, hit_point); |
---|
| 319 | is_hit = true; |
---|
| 320 | ragDollData *b = any_cast<ragDollData *> (radgoll->getUserAny()); |
---|
| 321 | b->timeSincePhysical = 0.0f; |
---|
| 322 | } |
---|
| 323 | } |
---|
| 324 | |
---|
| 325 | if (!is_hit&& !wasPhysical) |
---|
| 326 | { |
---|
| 327 | radgoll->releasePhysicalControl(); |
---|
| 328 | ragDollData *b = any_cast<ragDollData *> (radgoll->getUserAny()); |
---|
| 329 | radgoll->getAnimationState(meshAnimation[b->sSelectedMesh])->setEnabled(true); |
---|
| 330 | } |
---|
| 331 | #endif //_TESTTRIMESH |
---|
| 332 | |
---|
| 333 | ++i; |
---|
| 334 | } // if results. |
---|
| 335 | } |
---|
| 336 | myOdeRay->disable (); |
---|
| 337 | } |
---|
| 338 | |
---|
| 339 | |
---|
| 340 | for ( RagDollList::iterator zE = myRagDolls.begin(); |
---|
| 341 | zE != myRagDolls.end(); ) |
---|
| 342 | { |
---|
| 343 | |
---|
| 344 | OgreOde_Prefab::Ragdoll * const radgoll = (*zE); |
---|
| 345 | ragDollData *b = any_cast<ragDollData *> (radgoll->getUserAny()); |
---|
| 346 | b->timeSinceBirth += time; |
---|
| 347 | |
---|
| 348 | // turn to stone to improve fps, |
---|
| 349 | // better way to do that would be to tweak |
---|
| 350 | // simulation parameters to be less jitty. |
---|
| 351 | // better auto sleep |
---|
| 352 | if (radgoll->isPhysical() |
---|
| 353 | && !radgoll->isStatic() |
---|
| 354 | && radgoll->isAwake() |
---|
| 355 | && b->timeSincePhysical > 5.0) |
---|
| 356 | { |
---|
| 357 | //radgoll->turnToStone(); |
---|
| 358 | radgoll->sleep(); |
---|
| 359 | } |
---|
| 360 | |
---|
| 361 | |
---|
| 362 | if ( b->timeSinceBirth > sMaxRagdoll) |
---|
| 363 | { |
---|
| 364 | (static_cast<SceneNode*> (radgoll->getParentNode ()->getParent()))->removeAndDestroyChild( |
---|
| 365 | radgoll->getParentNode ()->getName ()); |
---|
| 366 | _mgr->destroyMovableObject(radgoll->getName(), OgreOde_Prefab::RagdollFactory::FACTORY_TYPE_NAME); |
---|
| 367 | zE = myRagDolls.erase(zE); |
---|
| 368 | } |
---|
| 369 | else |
---|
| 370 | { |
---|
| 371 | ++zE; |
---|
| 372 | } |
---|
| 373 | } |
---|
| 374 | if (_last_ragdoll > 5.0 && |
---|
| 375 | myRagDolls.size() < static_cast<size_t>(sMaxRagdoll)) |
---|
| 376 | createRagDoll(); |
---|
| 377 | |
---|
| 378 | } |
---|
| 379 | |
---|
| 380 | protected: |
---|
| 381 | RagDollList myRagDolls; |
---|
| 382 | RaySceneQuery *mRayQuery; |
---|
| 383 | |
---|
| 384 | Real _animation_speed; |
---|
| 385 | |
---|
| 386 | Entity *_gun; |
---|
| 387 | SceneNode *_gun_node; |
---|
| 388 | |
---|
| 389 | OgreOde::RayGeometry *myOdeRay; |
---|
| 390 | |
---|
| 391 | Camera* _camera; |
---|
| 392 | Overlay* _over; |
---|
| 393 | |
---|
| 394 | Real _shot_time; |
---|
| 395 | |
---|
| 396 | Real _last_ragdoll; |
---|
| 397 | int _ragdoll_count; |
---|
| 398 | }; |
---|
| 399 | |
---|
| 400 | #endif |
---|