1 | /* |
---|
2 | SimpleScenes.cpp |
---|
3 | --------------- |
---|
4 | Code for the base scene class from which the specific scenes are derived |
---|
5 | */ |
---|
6 | #include "SimpleScenes.h" |
---|
7 | |
---|
8 | using namespace Ogre; |
---|
9 | using namespace OgreOde; |
---|
10 | using namespace OgreOde_Prefab; |
---|
11 | using namespace OgreOde_Loader; |
---|
12 | |
---|
13 | const Ogre::Real SimpleScenes::KEY_DELAY = 1.0; |
---|
14 | const Ogre::Real SimpleScenes::STEP_RATE = 0.01; |
---|
15 | |
---|
16 | /* |
---|
17 | Constructor; initailise stuff |
---|
18 | */ |
---|
19 | SimpleScenes::SimpleScenes(OgreOde::World *world) |
---|
20 | { |
---|
21 | _world = world; |
---|
22 | _mgr = _world->getSceneManager(); |
---|
23 | _world->setCollisionListener(this); |
---|
24 | _space = _world->getDefaultSpace(); |
---|
25 | _key_delay = SimpleScenes::KEY_DELAY; |
---|
26 | _last_node = 0; |
---|
27 | |
---|
28 | dotOgreOdeLoader = new OgreOde_Loader::DotLoader (world); |
---|
29 | |
---|
30 | _ragdollFactory = new OgreOde_Prefab::RagdollFactory(); |
---|
31 | Ogre::Root::getSingletonPtr()->addMovableObjectFactory(_ragdollFactory); |
---|
32 | setInfoText(StringUtil::BLANK); |
---|
33 | } |
---|
34 | |
---|
35 | /* |
---|
36 | Called by OgreOde whenever a collision occurs, so |
---|
37 | that we can modify the contact parameters |
---|
38 | */ |
---|
39 | bool SimpleScenes::collision(OgreOde::Contact* contact) |
---|
40 | { |
---|
41 | // Check for collisions between things that are connected and ignore them |
---|
42 | OgreOde::Geometry * const g1 = contact->getFirstGeometry(); |
---|
43 | OgreOde::Geometry * const g2 = contact->getSecondGeometry(); |
---|
44 | |
---|
45 | if (g1 && g2) |
---|
46 | { |
---|
47 | const OgreOde::Body * const b1 = g1->getBody(); |
---|
48 | const OgreOde::Body * const b2 = g2->getBody(); |
---|
49 | if (b1 && b2 && OgreOde::Joint::areConnected(b1, b2)) |
---|
50 | return false; |
---|
51 | } |
---|
52 | |
---|
53 | // Set the friction at the contact |
---|
54 | contact->setCoulombFriction(OgreOde::Utility::Infinity); |
---|
55 | |
---|
56 | contact->setBouncyness(0.1); |
---|
57 | |
---|
58 | //contact->setCoulombFriction(5.0); |
---|
59 | //contact->setFrictionMode(OgreOde::Contact::Flag_SurfaceIsBouncy); |
---|
60 | |
---|
61 | //contact->setCoulombFriction(OgreOde::Utility::Infinity); |
---|
62 | |
---|
63 | // Yes, this collision is valid |
---|
64 | return true; |
---|
65 | } |
---|
66 | |
---|
67 | /* |
---|
68 | Handle key presses |
---|
69 | */ |
---|
70 | #if (OGRE_VERSION_MINOR < 4) |
---|
71 | void SimpleScenes::frameEnded(Real time, InputReader* input) |
---|
72 | #else |
---|
73 | void SimpleScenes::frameEnded(Real time, OIS::Keyboard* input, OIS::Mouse* mouse) |
---|
74 | #endif //OGRE_VERSION not heihort |
---|
75 | { |
---|
76 | _key_delay += time; |
---|
77 | |
---|
78 | std::for_each (RagdollList.begin(), RagdollList.end(), |
---|
79 | std::mem_fun (&OgreOde_Prefab::Ragdoll::update)); |
---|
80 | } |
---|
81 | |
---|
82 | /* |
---|
83 | Utility method to set the information string in the UI |
---|
84 | */ |
---|
85 | void SimpleScenes::setInfoText(const String& text) |
---|
86 | { |
---|
87 | OverlayManager::getSingleton().getOverlayElement("OgreOdeDemos/Info")->setCaption(String("Info: ") + text); |
---|
88 | } |
---|
89 | |
---|
90 | static const String xmlNames[] = { |
---|
91 | "zombie", |
---|
92 | "zombie", |
---|
93 | "ninja", |
---|
94 | "robot" |
---|
95 | }; |
---|
96 | static const String meshNames[] = { |
---|
97 | "zombie_small.mesh", |
---|
98 | "zombie_small.mesh", |
---|
99 | "ninja.mesh", |
---|
100 | "robot.mesh" |
---|
101 | }; |
---|
102 | static const String meshAnimation [] = { |
---|
103 | "Walk1", |
---|
104 | "Walk1", |
---|
105 | "Walk", |
---|
106 | "Walk" |
---|
107 | }; |
---|
108 | static const Ogre::Vector3 meshScale [] = { |
---|
109 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
110 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
111 | Ogre::Vector3(1.0, 1.0, 1.0), |
---|
112 | Ogre::Vector3(1.0, 1.0, 1.0) |
---|
113 | }; |
---|
114 | static const String ragdollFile [] = { |
---|
115 | "zombie.ogreode", |
---|
116 | "zombie_auto.ogreode", |
---|
117 | "ninja.ogreode", |
---|
118 | "robot.ogreode" |
---|
119 | }; |
---|
120 | static int sSelectedMesh = 0; |
---|
121 | static int _ragdoll_count = 0; |
---|
122 | |
---|
123 | /* |
---|
124 | Create a ragdoll |
---|
125 | */ |
---|
126 | void SimpleScenes::createRagDoll() |
---|
127 | { |
---|
128 | if (_key_delay < SimpleScenes::KEY_DELAY) |
---|
129 | return; |
---|
130 | |
---|
131 | _key_delay = 0.0; |
---|
132 | |
---|
133 | |
---|
134 | OgreOde_Prefab::Ragdoll *_ragdoll = static_cast <OgreOde_Prefab::Ragdoll *> (dotOgreOdeLoader->loadObject (ragdollFile[sSelectedMesh], |
---|
135 | xmlNames[sSelectedMesh], |
---|
136 | "zombie" + StringConverter::toString(_ragdoll_count++))); |
---|
137 | |
---|
138 | |
---|
139 | _ragdoll->setCastShadows(true); |
---|
140 | |
---|
141 | SceneNode *_ragdoll_node = _mgr->getRootSceneNode()->createChildSceneNode(_ragdoll->getName() + "Node"); |
---|
142 | _ragdoll_node->attachObject(_ragdoll); |
---|
143 | |
---|
144 | //_ragdoll_node->yaw(Degree(rand() % 360)); |
---|
145 | //_ragdoll_node->pitch(Degree(rand() % 360)); |
---|
146 | |
---|
147 | |
---|
148 | _ragdoll_node->setOrientation(Quaternion(Radian(OgreOde::Utility::randomReal() * 10.0 - 5.0), |
---|
149 | Ogre::Vector3(OgreOde::Utility::randomReal() * 2.0 - 1.0, |
---|
150 | OgreOde::Utility::randomReal() * 2.0 - 1.0, |
---|
151 | OgreOde::Utility::randomReal() * 2.0 - 1.0))); |
---|
152 | |
---|
153 | _ragdoll_node->setPosition(Vector3((OgreOde::Utility::randomReal() * 10.0) - 5.0, |
---|
154 | OgreOde::Utility::randomReal() + 5, |
---|
155 | (OgreOde::Utility::randomReal() * 10.0) - 5.0)); |
---|
156 | |
---|
157 | |
---|
158 | _ragdoll_node->setScale( meshScale[sSelectedMesh]); |
---|
159 | |
---|
160 | |
---|
161 | _ragdoll->getAnimationState(meshAnimation[sSelectedMesh])->setEnabled(false); |
---|
162 | |
---|
163 | |
---|
164 | // Create the ragdoll |
---|
165 | _ragdoll->takePhysicalControl(_world, _space, false); |
---|
166 | _ragdoll->setSelfCollisions(false); |
---|
167 | |
---|
168 | RagdollList.push_back(_ragdoll); |
---|
169 | |
---|
170 | } |
---|
171 | /* |
---|
172 | Create a randomly sized box, sphere or capsule for dropping on things |
---|
173 | */ |
---|
174 | OgreOde::Body* SimpleScenes::createRandomObject(OgreOde::Geometry::Class objectClass) |
---|
175 | { |
---|
176 | if (_key_delay < SimpleScenes::KEY_DELAY) |
---|
177 | return 0; |
---|
178 | |
---|
179 | String typeName = (objectClass == OgreOde::Geometry::Class_Box)?"crate": |
---|
180 | (objectClass == OgreOde::Geometry::Class_Sphere)?"ball": |
---|
181 | (objectClass == OgreOde::Geometry::Class_Capsule)?"capsule": |
---|
182 | (objectClass == OgreOde::Geometry::Class_TriangleMesh)?"gun": |
---|
183 | "unknown"; |
---|
184 | |
---|
185 | // Create the visual representation (the Ogre entity and scene node) |
---|
186 | String name = typeName + StringConverter::toString((unsigned int)_bodies.size()); |
---|
187 | Entity* entity = _mgr->createEntity(name, typeName + ".mesh"); |
---|
188 | entity->setQueryFlags (GEOMETRY_QUERY_MASK); |
---|
189 | |
---|
190 | SceneNode* node = _mgr->getRootSceneNode()->createChildSceneNode(name); |
---|
191 | node->attachObject(entity); |
---|
192 | entity->setNormaliseNormals(true); |
---|
193 | entity->setCastShadows(true); |
---|
194 | |
---|
195 | // Pick a size |
---|
196 | Vector3 size((OgreOde::Utility::randomReal() * 0.5 + 0.1) * 2.0, |
---|
197 | (OgreOde::Utility::randomReal() * 0.5 + 0.1) * 2.0, |
---|
198 | (OgreOde::Utility::randomReal() * 0.5 + 0.1) * 2.0); |
---|
199 | |
---|
200 | // Create a body associated with the node we created |
---|
201 | OgreOde::Body* body = new OgreOde::Body(_world); |
---|
202 | node->attachObject(body); |
---|
203 | |
---|
204 | // Set the mass and geometry to match the visual representation |
---|
205 | OgreOde::Geometry* geom = 0; |
---|
206 | switch (objectClass) |
---|
207 | { |
---|
208 | case OgreOde::Geometry::Class_Box: |
---|
209 | { |
---|
210 | size *= 1.75; |
---|
211 | |
---|
212 | OgreOde::BoxMass mass(1.0,size); |
---|
213 | mass.setDensity(5.0,size); |
---|
214 | |
---|
215 | geom = (OgreOde::Geometry*)new OgreOde::BoxGeometry(size, _world, _space); |
---|
216 | node->setScale(size.x * 0.1,size.y * 0.1,size.z * 0.1); |
---|
217 | body->setMass(mass); |
---|
218 | } |
---|
219 | break; |
---|
220 | |
---|
221 | case OgreOde::Geometry::Class_Sphere: |
---|
222 | { |
---|
223 | OgreOde::SphereMass mass(1.0,size.x); |
---|
224 | mass.setDensity(5.0,size.x); |
---|
225 | |
---|
226 | geom = (OgreOde::Geometry*)new OgreOde::SphereGeometry(size.x, _world, _space); |
---|
227 | node->setScale(size.x * 0.2,size.x * 0.2,size.x * 0.2); |
---|
228 | body->setMass(mass); |
---|
229 | } |
---|
230 | break; |
---|
231 | |
---|
232 | case OgreOde::Geometry::Class_Capsule: |
---|
233 | { |
---|
234 | size.x *= 0.5; |
---|
235 | |
---|
236 | OgreOde::CapsuleMass mass(1.0,size.x,Vector3::UNIT_Z,size.y); |
---|
237 | mass.setDensity(5.0,size.x,Vector3::UNIT_Z,size.y); |
---|
238 | |
---|
239 | geom = (OgreOde::Geometry*)new OgreOde::CapsuleGeometry(size.x,size.y, _world, _space); |
---|
240 | node->setScale(size.x,size.x,(size.y + (size.x * 2.0)) * 0.25); |
---|
241 | body->setMass(mass); |
---|
242 | } |
---|
243 | break; |
---|
244 | |
---|
245 | case OgreOde::Geometry::Class_TriangleMesh: |
---|
246 | { |
---|
247 | OgreOde::EntityInformer ei(entity, node->_getFullTransform()); |
---|
248 | geom = ei.createStaticTriangleMesh( _world, _space); |
---|
249 | |
---|
250 | OgreOde::BoxMass mass(1.0, ei.getSize()); |
---|
251 | mass.setDensity(5.0, ei.getSize()); |
---|
252 | |
---|
253 | //node->setScale(size.x,size.x,(size.y + (size.x * 2.0)) * 0.25); |
---|
254 | body->setMass(mass); |
---|
255 | } |
---|
256 | break; |
---|
257 | } |
---|
258 | |
---|
259 | // Tie the collision geometry to the physical body |
---|
260 | geom->setBody(body); |
---|
261 | entity->setUserObject(geom); |
---|
262 | |
---|
263 | // Keep track of the body |
---|
264 | _bodies.push_back(body); |
---|
265 | _geoms.push_back(geom); |
---|
266 | |
---|
267 | _key_delay = 0.0; |
---|
268 | |
---|
269 | // If we created something position and orient it randomly |
---|
270 | if (body) |
---|
271 | { |
---|
272 | body->setOrientation(Quaternion(Radian(OgreOde::Utility::randomReal() * 10.0 - 5.0), |
---|
273 | Ogre::Vector3(OgreOde::Utility::randomReal() * 2.0 - 1.0, |
---|
274 | OgreOde::Utility::randomReal() * 2.0 - 1.0, |
---|
275 | OgreOde::Utility::randomReal() * 2.0 - 1.0))); |
---|
276 | body->setPosition(Vector3((OgreOde::Utility::randomReal() * 10.0) - 5.0, |
---|
277 | OgreOde::Utility::randomReal() + 5, |
---|
278 | (OgreOde::Utility::randomReal() * 10.0) - 5.0)); |
---|
279 | |
---|
280 | // Set the last body we created to be looked at |
---|
281 | _last_node = static_cast<SceneNode*>(body->getParentNode()); |
---|
282 | } |
---|
283 | |
---|
284 | return body; |
---|
285 | } |
---|
286 | |
---|
287 | /* |
---|
288 | Destructor, delete everything we're keeping track of |
---|
289 | */ |
---|
290 | SimpleScenes::~SimpleScenes(void) |
---|
291 | { |
---|
292 | // Stop listening for collisions |
---|
293 | if (_world->getCollisionListener() == this) |
---|
294 | _world->setCollisionListener(0); |
---|
295 | |
---|
296 | // Delete all the joints |
---|
297 | for (std::vector<OgreOde::Joint*>::iterator i = _joints.begin();i != _joints.end();++i) |
---|
298 | { |
---|
299 | delete (*i); |
---|
300 | } |
---|
301 | |
---|
302 | // Run through the list of bodies we're monitoring |
---|
303 | for (std::vector<OgreOde::Body*>::iterator i = _bodies.begin();i != _bodies.end();++i) |
---|
304 | { |
---|
305 | // Get the node this body controls |
---|
306 | SceneNode* node = static_cast<SceneNode*>((*i)->getParentNode()); |
---|
307 | if (node) |
---|
308 | { |
---|
309 | // Get its name and remember all the things attached to it |
---|
310 | String name = node->getName(); |
---|
311 | int num = node->numAttachedObjects(); |
---|
312 | for (int cur = 0;cur < num; cur++) |
---|
313 | { |
---|
314 | MovableObject* obj = node->getAttachedObject(cur); |
---|
315 | if (obj->getMovableType() != OgreOde::Body::MovableType) |
---|
316 | clearList.push_back(obj); |
---|
317 | } |
---|
318 | |
---|
319 | // Destroy the node by name |
---|
320 | _mgr->getRootSceneNode()->removeAndDestroyChild(name); |
---|
321 | } |
---|
322 | |
---|
323 | // Delete the body |
---|
324 | delete (*i); |
---|
325 | } |
---|
326 | |
---|
327 | // Remove all the entities we found attached to scene nodes we're controlling |
---|
328 | for (std::vector<MovableObject*>::iterator i = clearList.begin();i != clearList.end();++i) |
---|
329 | { |
---|
330 | if ((*i)->getMovableType() == "Entity") |
---|
331 | { |
---|
332 | MovableObject* m = static_cast<MovableObject*>(*i); |
---|
333 | //_mgr->destroyMovableObject(m->getName(), m->); |
---|
334 | _mgr->destroyMovableObject(m); |
---|
335 | } |
---|
336 | else if ((*i)->getMovableType() == "ParticleSystem") |
---|
337 | { |
---|
338 | _mgr->destroyParticleSystem(static_cast<ParticleSystem*>(*i)); |
---|
339 | } |
---|
340 | } |
---|
341 | |
---|
342 | // Delete all the collision geometries |
---|
343 | for (std::vector<OgreOde::Geometry*>::iterator i = _geoms.begin();i != _geoms.end();++i) |
---|
344 | { |
---|
345 | delete (*i); |
---|
346 | } |
---|
347 | // Remove all the entities we found attached to scene nodes we're controlling |
---|
348 | for (std::vector<OgreOde_Prefab::Ragdoll *>::iterator i = RagdollList.begin();i != RagdollList.end();++i) |
---|
349 | { |
---|
350 | |
---|
351 | assert ((*i)->getParentNode ()); |
---|
352 | assert ((*i)->getParentNode ()->getParent()); |
---|
353 | (static_cast<SceneNode*> ((*i)->getParentNode ()->getParent()))->removeAndDestroyChild( |
---|
354 | (*i)->getParentNode ()->getName ()); |
---|
355 | |
---|
356 | _mgr->destroyMovableObject((*i)->getName(), OgreOde_Prefab::RagdollFactory::FACTORY_TYPE_NAME); |
---|
357 | //_mgr->destroyMovableObject(m); |
---|
358 | } |
---|
359 | Ogre::Root::getSingletonPtr()->removeMovableObjectFactory(_ragdollFactory); |
---|
360 | delete _ragdollFactory; |
---|
361 | } |
---|