1 | /* |
---|
2 | PhysicsFrameListener.h |
---|
3 | |
---|
4 | A very simple wrapper class for ODE |
---|
5 | primarily for the example car application |
---|
6 | */ |
---|
7 | #ifndef _PHYSICSFRAMELISTENER_H_ |
---|
8 | #define _PHYSICSFRAMELISTENER_H_ |
---|
9 | |
---|
10 | #include "OgreOdePreReqs.h" |
---|
11 | #include <OgreSceneQuery.h> |
---|
12 | #include <OgreFrameListener.h> |
---|
13 | |
---|
14 | // Uncomment this if you're planning to use the Plane2D joint |
---|
15 | // But you'll have to have modified ODE first! |
---|
16 | // #define INCLUDE_PLANE2D_JOINT |
---|
17 | |
---|
18 | /* |
---|
19 | A physical thing |
---|
20 | */ |
---|
21 | class PhysicalThing : public Ogre::RaySceneQueryListener |
---|
22 | { |
---|
23 | public: |
---|
24 | // Doesn't actually do anything |
---|
25 | PhysicalThing(dSpace *space); |
---|
26 | ~PhysicalThing(void); |
---|
27 | |
---|
28 | // Just create geoms |
---|
29 | void makePlane(Ogre::Real a, Ogre::Real b, Ogre::Real c, Ogre::Real d); // Plane |
---|
30 | void makeBox(Ogre::Real x, Ogre::Real y, Ogre::Real z, Ogre::Real lx, Ogre::Real ly, Ogre::Real lz); // Box |
---|
31 | void makeSphere(Ogre::Real x, Ogre::Real y, Ogre::Real z, Ogre::Real r); // Sphere |
---|
32 | |
---|
33 | // Create bodies and geoms |
---|
34 | void makePlane(dWorld *world, Ogre::SceneNode *node); |
---|
35 | void makeBox(dWorld *world, Ogre::SceneNode *node, Ogre::Real mass = 1, Ogre::Vector3 const &offs = Ogre::Vector3(0,0,0)); |
---|
36 | void makeSphere(dWorld *world, Ogre::SceneNode *node, Ogre::Real mass = 1); |
---|
37 | void makeTerrainTriMesh(dWorld *world, Ogre::SceneManager *mgr, Ogre::Real grid_size, Ogre::Real grid_spacing); |
---|
38 | |
---|
39 | // Callback functions for the ray scene query functionality |
---|
40 | virtual bool queryResult(Ogre::SceneQuery::WorldFragment *fragment, Ogre::Real distance); |
---|
41 | virtual bool queryResult(Ogre::MovableObject *obj, Ogre::Real distance); |
---|
42 | |
---|
43 | // Update the position and orientation of the scene node we're controlling |
---|
44 | void update(void); |
---|
45 | |
---|
46 | // Utility functions to get at internal stuff |
---|
47 | Ogre::SceneNode *getNode(void); |
---|
48 | dBodyID getBodyID(void); |
---|
49 | dSpaceID getSpaceID(void); |
---|
50 | |
---|
51 | protected: |
---|
52 | dGeom *_geom; |
---|
53 | dBody *_body; |
---|
54 | dSpace *_space; |
---|
55 | Ogre::SceneNode *_node; |
---|
56 | |
---|
57 | std::list<Ogre::Vector3> _frag; |
---|
58 | |
---|
59 | dVector3 *_vertices; |
---|
60 | int *_indices; |
---|
61 | }; |
---|
62 | |
---|
63 | /* |
---|
64 | A Frame listener that implements the physics |
---|
65 | */ |
---|
66 | class PhysicsFrameListener : public Ogre::FrameListener |
---|
67 | { |
---|
68 | protected: |
---|
69 | // All the stuff we need for ODE |
---|
70 | dWorld *world; |
---|
71 | dHashSpace *space; |
---|
72 | dJointGroup *contactgroup; |
---|
73 | dSpace *current_space; |
---|
74 | bool paused; |
---|
75 | |
---|
76 | // Keep track of anything we've created |
---|
77 | std::list<PhysicalThing*> things; |
---|
78 | std::list<dSimpleSpace*> spaces; |
---|
79 | std::list<dJoint*> joints; |
---|
80 | |
---|
81 | // Adjustable variables |
---|
82 | Ogre::Real total_time,step_size; |
---|
83 | Ogre::Real k_spring,k_damper,k_tyre,k_mu,k_erp,k_cfm; |
---|
84 | |
---|
85 | // Utility function to find the physical thing associated with an Ogre scene node |
---|
86 | dBodyID getBodyID(Ogre::SceneNode *node); |
---|
87 | |
---|
88 | public: |
---|
89 | // Standard constructor/destructor |
---|
90 | PhysicsFrameListener(void); |
---|
91 | ~PhysicsFrameListener(void); |
---|
92 | |
---|
93 | // Tell us when every frame's about to be started |
---|
94 | bool frameStarted(const Ogre::FrameEvent& evt); |
---|
95 | void pause(bool p = true); |
---|
96 | |
---|
97 | // Mainly so we can access internal stuff from the collision callback |
---|
98 | dWorld *getWorld(void){return world;}; |
---|
99 | dSpace *getSpace(void){return space;}; |
---|
100 | dJointGroup *getContactGroup(void){return contactgroup;}; |
---|
101 | |
---|
102 | // Create things manually, no physical bodies |
---|
103 | // so they won't move, but things will collide with them |
---|
104 | PhysicalThing *createPlane(Ogre::Real a,Ogre::Real b,Ogre::Real c,Ogre::Real d); |
---|
105 | PhysicalThing *createBox(Ogre::Real x,Ogre::Real y,Ogre::Real z,Ogre::Real lx,Ogre::Real ly,Ogre::Real lz); |
---|
106 | PhysicalThing *createSphere(Ogre::Real x,Ogre::Real y,Ogre::Real z,Ogre::Real r); |
---|
107 | |
---|
108 | // Create objects based on Ogre nodes, these nodes will then |
---|
109 | // come under control of the physics simulation and will move about |
---|
110 | // as if by magic! |
---|
111 | // Except for the plane, which can't actually be a physical body |
---|
112 | // and the trimesh which we're not going to allow to be a physical body |
---|
113 | PhysicalThing *createPlane(Ogre::SceneNode *node); |
---|
114 | PhysicalThing *createBox(Ogre::SceneNode *node,Ogre::Real mass = 1,Ogre::Vector3 const &offs = Ogre::Vector3(0,0,0)); |
---|
115 | PhysicalThing *createSphere(Ogre::SceneNode *node,Ogre::Real mass = 1); |
---|
116 | PhysicalThing *createTerrainTriMesh(Ogre::SceneManager *mgr,Ogre::Real grid_size,Ogre::Real grid_spacing); |
---|
117 | |
---|
118 | // Create and activate a new space inside the standard hash space |
---|
119 | // Things won't collide within a space so (for example) the objects |
---|
120 | // that make up a car won't collide with each other |
---|
121 | dSimpleSpace *createSpace(void); |
---|
122 | |
---|
123 | // Create joints between the nodes specified |
---|
124 | // The order of n1/n2 does matter; n1 is what you want attaching |
---|
125 | // and n2 is what you want it attaching to |
---|
126 | dJoint *createHinge2(Ogre::SceneNode *n1,Ogre::SceneNode *n2,const Ogre::Vector3 &suspension = Ogre::Vector3(0,1,0),const Ogre::Vector3 &axle = Ogre::Vector3(1,0,0)); |
---|
127 | dJoint *createHinge(Ogre::SceneNode *n1,Ogre::SceneNode *n2,const Ogre::Vector3 &axis = Ogre::Vector3(1,0,0)); |
---|
128 | dJoint *createSlider(Ogre::SceneNode *n1,Ogre::SceneNode *n2,const Ogre::Vector3 &axis = Ogre::Vector3(0,1,0)); |
---|
129 | dJoint *createBall(Ogre::SceneNode *n1,Ogre::SceneNode *n2); |
---|
130 | #ifdef INCLUDE_PLANE2D_JOINT |
---|
131 | dJoint *createPlane2D(Ogre::SceneNode *n); |
---|
132 | #endif |
---|
133 | |
---|
134 | // Apply forces to a body under our control |
---|
135 | void addTorque(Ogre::SceneNode *n,const Ogre::Vector3 &force); |
---|
136 | |
---|
137 | // Set the parameters used for the CFM/ERP joint parameters |
---|
138 | void setSuspension(Ogre::Real spring,Ogre::Real damper); |
---|
139 | |
---|
140 | // Set the acceleration due to gravity |
---|
141 | void setGravity(Ogre::Real g); |
---|
142 | |
---|
143 | // Get our constants |
---|
144 | Ogre::Real getTyre(void){return k_tyre;}; |
---|
145 | Ogre::Real getMu(void){return k_mu;}; |
---|
146 | Ogre::Real getCFM(void){return k_cfm;}; |
---|
147 | Ogre::Real getERP(void){return k_erp;}; |
---|
148 | |
---|
149 | // Static function for ODE to call when collisions (potentially) occur |
---|
150 | static void collisionCallback(void *data,dGeomID o1,dGeomID o2); |
---|
151 | }; |
---|
152 | |
---|
153 | #endif |
---|
154 | |
---|
155 | |
---|