These tutorials focus mainly on OpenGL, Win32 programming and the ODE physics engine. OpenGL has moved on to great heights and I don't cover the newest features but cover all of the basic concepts you will need with working example programs.
Working with the Win32 API is a great way to get to the heart of Windows and is just as relevant today as ever before. Whereas ODE has been marginalized as hardware accelerated physics becomes more common.
Games and graphics utilities can be made quickly and easily using game engines like Unity so this and Linux development in general will be the focus of my next tutorials.
ODE Constraints/Stops
By Alan Baylis 06/04/2006
Download for Visual Studio 7.0
To demonstrate the use of constraints (or as Russell Smith prefers to call them 'stops') I have put together three objects in this example simulation. The first object is a large upright block which acts as an anchor point for the second object which is joined to it by a hinge joint. The third object is a sphere that I have used to move the hinged object by colliding into it. This tutorial follows on from the common ODE joints tutorial so I will just cover the changes that have been made.
The first change is to increase the number of objects to three in the main.cpp source file.
MyObject Object[3]; // three geom objects
Now we move on to the InitODE routine which has grown quite a bit.
void InitODE() { World = dWorldCreate(); Space = dHashSpaceCreate(0); contactgroup = dJointGroupCreate(0); jointgroup = dJointGroupCreate(0); dCreatePlane(Space, 0, 1, 0, 0); dWorldSetGravity(World, 0, -1.0, 0); dWorldSetCFM(World, 1e-5); dWorldSetERP(World, 0.2); dWorldSetContactMaxCorrectingVel(World, 0.9); dWorldSetContactSurfaceLayer(World, 0); dWorldSetAutoDisableFlag(World, 0); // As we are using both rectangular boxes and a sphere we need variables for initializing both. dReal sides[3]; // dimensions of the boxes dReal radius = 0.3; // radius of the sphere dMass m; dMatrix3 R; VECTOR tempVect(0.0, 0.0, 0.0); // Initialize the three body objects Object[0].Body = dBodyCreate(World); Object[1].Body = dBodyCreate(World); Object[2].Body = dBodyCreate(World); // Create a static object which acts as a solid anchor point for the hinged object. To make the object immovable I have // multiplied its density by 10. I have also rotated it using dRFromAxisAndAngle to make a good anchor point. sides[0] = 1.0; sides[1] = 3.0; sides[2] = 1.0; dBodySetPosition(Object[0].Body, 0, 1.5, -5); dBodySetLinearVel(Object[0].Body, tempVect.x, tempVect.y, tempVect.z); dRFromAxisAndAngle(R, 0, 1, 0, pi / 4); dBodySetRotation(Object[0].Body, R); dMassSetBox(&m, DENSITY * 10, sides[0], sides[1], sides[2]); Object[0].Geom[0] = dCreateBox(Space, sides[0], sides[1], sides[2]); dGeomSetBody(Object[0].Geom[0], Object[0].Body); dBodySetMass(Object[0].Body, &m); // Create the hinged object and position it before connecting it with the hinge joint. sides[0] = 2.0; sides[1] = 1.0; sides[2] = 0.2; dBodySetPosition(Object[1].Body, 1.707106, 2.5, -5.1); dBodySetLinearVel(Object[1].Body, tempVect.x, tempVect.y, tempVect.z); dMassSetBox(&m, DENSITY, sides[0], sides[1], sides[2]); Object[1].Geom[0] = dCreateBox(Space, sides[0], sides[1], sides[2]); dGeomSetBody(Object[1].Geom[0], Object[1].Body); dBodySetMass(Object[1].Body, &m); // Create the sphere object. I have set its initial position and linear velocity so that it will impact the hinged block. dBodySetPosition(Object[2].Body, 2, 2.5, -3); dBodySetLinearVel(Object[2].Body, 0.0, 0.0, -4.0); dRFromAxisAndAngle(R, 1, 0, 0, -(pi / 2)); dBodySetRotation(Object[2].Body, R); dMassSetSphere(&m, DENSITY, radius); Object[2].Geom[0] = dCreateSphere(Space, radius); dGeomSetBody(Object[2].Geom[0], Object[2].Body); dBodySetMass(Object[2].Body, &m); // Create hinge joint between static and hinged objects. Joint = dJointCreateHinge(World, jointgroup); dJointAttach(Joint, Object[0].Body, Object[1].Body); dJointSetHingeAnchor(Joint, 0.707106, 2.5, -5.0); dJointSetHingeAxis(Joint, 0, 1, 0); // This brings us to the main part where we set the lower and upper bounds of the hinge movement. I will discuss // this in more detail below dJointSetHingeParam(Joint, dParamLoStop, -(pi / 8)); dJointSetHingeParam(Joint, dParamHiStop, pi / 8); }
dJointSetHingeParam is just one of the functions that set the constraint/stop and motor parameters (as well as other kinds of parameters) on a joint. There is a seperate function for each type of joint such as dJointSetSliderParam for a slider joint etc. You will find a complete list of them and the possible parameters in section 7.5.1 of the ODE documentation.
From its initial position the dParamLoStop sets the amount of movement available in one direction and dParamHiStop sets the amount of movement in the other direction. So if we take the initial hinge position to be zero then dParamLoStop should range between 0 and -pi and the dParamHiStop should range between 0 and pi. You can see that I have limited the amount of movement of the hinge joint to between -pi/8 and pi/8. One of the other parameters of the joints that may be of interest is the dParamBounce setting, which sets the bounciness of the stops.
The following code snippet is taken from the main.cpp source file and is run when the user presses the space bar. It simply resets the sphere's position, rotation and linear velocity so that it impacts the hinge object again.
// Reset the geom Object if (key[VK_SPACE] && released_key[VK_SPACE] == 0) { dMatrix3 R; dBodyEnable(Object[2].Body); dBodySetPosition(Object[2].Body, 2, 2.5, -3); dBodySetLinearVel(Object[2].Body, 0.0, 0.0, -4.0); dRFromAxisAndAngle(R, 1, 0, 0, -(pi / 2)); dBodySetRotation(Object[2].Body, R); released_key[VK_SPACE] = 1; }
As you can see there isn't much programming required to set the constraints/stops of a joint (just two lines of code in this case). But when dealing with joints this is a very necessary feature to have so that we can control the range of possible movement of the joints. I don't have any set plans for the next tutorial but I will be looking into creating an angular motor (section 7.3.8 of the docs) and may put a tutorial out on this subject.
So until next time I wish you all the best with you ODE simulations.
Alan Baylis