Applied ODE - Computer Architect

Document Sample

```					Applied ODE
Bryan Duggan
Overview!
Car
Gravity Gun
Car Algorithm
Create the mesh for the chassis (a box)
Create the RigidBody (a box)
Set the mass of the rigid body
Set the shape of the rigid body (the geom)
Create 4 wheels at the appropriate positions
   Create a cylinder mesh
   Create the rigid body
   Set the mass of the rigid body
   Set the shape of the rigid body (the geom)
Car Algorithm continued
Create 4 hinges so that the wheels can
rotate
   Create the hinge
   Join the hinge to the chassis using the
hinge
   Set the axis of the hinge to be the positive
Z axis
   Set the anchor of the hinge to be the
centre point of the wheel
Car Algorithm
At each step,
   Step forward the simulation (INTEGRATION)
   Get the position of the rigid body
   Get the quaternion
   Create a transform matrix
   Use it to draw the mesh

ODE
ODE Consists of
   A physics engine
   A collision detection engine
Collision detection
The collision engine is given information
about the shape of each body.
At each time step it figures out which bodies
The user in turn checks to see if the objects
themselves intersect (narrow phase)
It then creates contact joints between bodies
Collision detection
You have to register a callback function
with ODE to handle collisions.
function and register the callback
Your function will get called once for
each pair of bounding boxes that
intersect:
dSpaceCollide(_space, this,
&nearCallback);
void nearCallback(void *data,
dGeomID o0, dGeomID o1)
{
reinterpret_cast<World*>(data)-
>handleCollisionBetween(o0,o1);
}
Your callback function can call a member
function on a class:

void
World::handleCollisionBetween(dGeom
ID o1, dGeomID o2)
Its job is to go through each pair of
bounding boxes (passed in as
parameters) and call dCollide with the 2
bounding boxes
It returns the number of contact points
generated by the collison (which may
be 0)
const int N = 30;
dContact contact[N];
n = dCollide
(o1,o2,N,&contact[0].geom,sizeof(dCo
ntact));
if (n > 0)
\\ process the collisions
Typically,
Generate a contact joint for each pair of collisions that push the objects
apart based on the depth of penetration:
for (i=0; i<n; i++)
{
contact[i].surface.mode = dContactSlip1 |
dContactSlip2 | dContactSoftERP | dContactSoftCFM |
dContactApprox1;
contact[i].surface.mu = dInfinity;
contact[i].surface.slip1 = 0.1f;
contact[i].surface.slip2 = 0.1f;
contact[i].surface.soft_erp = 0.5f;
contact[i].surface.soft_cfm = 0.3f;
dJointID c = dJointCreateContact
(_dWorldID,_contactgroup,&contact[i]);
dJointAttach
(c,dGeomGetBody(contact[i].geom.g1),dGeomGetBody(contact[i].geom.g
2));
Gravity Gun!
Using the collision detection API, we
can make a gravity gun:
When the user presses the mouse button:
   IF they are not already holding something
 Create a ray from the camera origin and look and add
it to the space
 A ray is a geom with no body
   Else
 Calculate the holding position (some units in front of
the camera, say 10): camera pos + camera look *
units
 Calculate a velocity vector to move the held object to
the hold point:
   Take hold point – held object position
   Multiply by power factor of the gun (a scalar)
   If its greater than the max velocity scale it so its at the max
velocity
   Set the held objects linear velocity
if (pickedUp == NULL)
{
ray = dCreateRay(_space, 100);
D3DXVECTOR3 origin = _camera->getPosition();
D3DXVECTOR3 look = _camera->getLook();
D3DXVec3Normalize(& look, & look);
dGeomRaySet(ray, origin.x, origin.y, origin.z, look.x, look.y,
look.z);
}
else
{
float powerfactor = 100;
float maxVel = 50;
float fdistance = 10;
D3DXVECTOR3 holdpos = _camera->getPosition() + _camera->getLook() *
fdistance;
D3DXVECTOR3 v = holdpos - pickedUp->getPosition();
v *= powerfactor; // powerfactor of the GravityGun
if ( D3DXVec3length(&v) > maxVel )
{
v *= maxVel;
}
dBodySetLinearVel( pickedUp->getBody(), v.x, v.y, v.z );
In the collision detection
callback
Check to see if one of the geoms is a
ray, if so its a ray trace and handle it
differently
points, set the other geom to be the
picked up object
In code:
if (o1 == ray)
{
if ((dGeomGetClass(o2) !=
dPlaneClass) && (o2 != _camera->getGeom()))
{
RigidBodyODE * pu =
(RigidBodyODE *) dGeomGetData(o2);
if (pu != NULL)
{
pickedUp = pu;
}
}
return;
}
Things to watch out for!
Check the collision inside the narrow
phase collision test, not the broad
phase collision test.
ODE uses bounding boxes even for
rays!
You may need to swap the order of the
geom parameters to simplify your code
Factory design pattern
The factory method pattern is an object-oriented
design pattern.
It deals with the problem of creating objects
(products) without specifying the exact class of
object that will be created.
The factory method design pattern handles this
problem by defining a separate method for creating
the objects, which subclasses can then override to
specify the derived type of product that will be
created.
More generally, the term factory method is often
used to refer to any method whose main purpose is
Spawning new objects
You can use a factory object to spawn
new objects:

class Spawner
{
private:
World * _world;
IDirect3DDevice9 * _device;

public:
RigidBodyODE * createCube(float x, float y, float z);
RigidBodyODE * createWheel(float radius, float x, float y, float z);
...
...

```
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
 views: 15 posted: 10/21/2010 language: English pages: 23