Constrain Objects to 2D

From ODE
Jump to: navigation, search

Constraining Objects to 2D

This page is about constraining an object to 2D, such that the object only moves on the XY axes, with a fixed Z or zero, and the object is only capable of rotating in the Z axis. There are two steps to constraining an object to 2D. Setting up a joint to limit the position to the 2D plane, and then restricting rotation to the Z axis.

Restricting Position To Plane

To limit the position to a 2D plane, add this joint to the object during initialisation. The world ID is the ID of the ODE world, and the body ID is that of the object you want to constrain.

   dJointID planeJointID = dJointCreatePlane2D( odeWorldID, 0);
   dJointAttach( planeJointID, odeBodyID, 0 );

Using Motor Functions

The Plane2D joint restricts movement to the XY plane, but it also provides three motor functions. This allows an object to be powered, and is the same as having a 2D LMotor and a 1D AMotor built in with the joint type. Motor limits are not supported, because they don't make sense in this case. To make an object powered, the motor force must be set to a non-zero value.

   dJointSetPlane2DXParam(joint, param, value)
   dJointSetPlane2DYParam(joint, param, value)
   dJointSetPlane2DAngleParam(joint, param, value)

Restricting Rotation To One Axis

The plane2D stops objects rotating along non-2d axes, but it does not compensate for drift. To prevent angular drift, every time ODE does a time step, we limit the object rotation and angular velocity for each object which needs to be confined to the plane. Use a function similar to the one below for each object, each time step.

void YourGameObj::AlignToZAxis( )
{
   dBodyID bodyID = mOdeBody->id();
   const dReal *rot = dBodyGetAngularVel( bodyID );
   const dReal *quat_ptr;
   dReal quat[4], quat_len;
   quat_ptr = dBodyGetQuaternion( bodyID );
   quat[0] = quat_ptr[0];
   quat[1] = 0;
   quat[2] = 0; 
   quat[3] = quat_ptr[3]; 
   quat_len = sqrt( quat[0] * quat[0] + quat[3] * quat[3] );
   quat[0] /= quat_len;
   quat[3] /= quat_len;
   dBodySetQuaternion( bodyID, quat );
   dBodySetAngularVel( bodyID, 0, 0, rot[2] );
}