Introduction
  Configuration
  Graphical Modeling
  Dynamics Modeling
  Vehicle
  Obstacles
  Integration
  Resources

Modeling the Obstacles

In this portion of the tutorial we will create a few movable obstacles in the environment which the vehicle we modeled in the previous section will be able to interact with (crash into). Specifically, we will create a wall out of boxes and a ball. Additionally, we will introduce how OSG allows us to add textures to objects - both rectangular and spherical. Much of the obstacle modeling will be identical to the vehicle model. That is, we will again create transforms, shapes, bodies, and update callbacks. The obstacle creation is implemented in the makeObstacles() method and returns an OSG Node containing all obstacles which may be added to the scene graph.

The first task will be to build the wall, and the first subtask will be to specify the texture that we will use to cover the individual boxes which make up the wall. This code creats a StateSet object which will contain a particular OpenGL state that will apply to the objects to which we assign it. We then create a Texture object that we will add to the StateSet and apply to the faces of our objects. In this case, we use the osgDB module to read a JPEG file called "green002.jpg" and then set how the texture is applied. Here, we use the "REPEAT" option rather than the "CLAMP" option. This is will cause the image to be repeated over the surface until the entire surface is covered rather than attempting to stretch or shrink the image to fit.

dstate = new osg::StateSet;
tex = new osg::Texture2D;

tex->setImage(osgDB::readImageFile("green002.jpg"));
tex->setWrap( osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT );
tex->setWrap( osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT );

dstate->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON );
dstate->setTextureAttribute(0, new osg::TexEnv );
The following loop produces each box making up the wall using the same procedures as we have used before. The wall is built with boxes which are each the same size (WBOXSIZE on each side) into a wall the height and width specified in WALLHEIGHT and WALLWIDTH.
bool offset = false;
for (dReal z = WBOXSIZE/2.0; z <= WALLHEIGHT; z+=WBOXSIZE)
{
   offset = !offset;
   for (dReal y = (-WALLWIDTH+z)/2; y <= (WALLWIDTH-z)/2; y+=WBOXSIZE)
   {
      wall_bodies[wb] = dBodyCreate (world);
      dBodySetPosition (wall_bodies[wb],-20,y,z);
      dMassSetBox (&m,1,WBOXSIZE,WBOXSIZE,WBOXSIZE);
      dMassAdjust (&m, WALLMASS);
      dBodySetMass (wall_bodies[wb],&m);
      wall_boxes[wb] = dCreateBox (space,WBOXSIZE,WBOXSIZE,WBOXSIZE);
      dGeomSetBody (wall_boxes[wb],wall_bodies[wb]);

      // add the box to the scene graph
      osg::ref_ptr<osg::PositionAttitudeTransform> pat = 
            new osg::PositionAttitudeTransform;

      osg::ref_ptr<osg::Box> wallBox(new osg::Box (
            osg::Vec3 (0.0, 0.0, 0.0), WBOXSIZE, WBOXSIZE, WBOXSIZE));

      osg::ref_ptr<osg::Geode>wallBoxGeode (new osg::Geode);

      const dReal *p = dBodyGetPosition(wall_bodies[wb]);
      const dReal *r = dBodyGetQuaternion(wall_bodies[wb]);

      osg::Vec3 wallBoxPosition(p[0], p[1], p[2]);
      osg::Quat wallBoxAttitude(*(r+1), *(r+2), *(r+3), *(r+0));

      pat->setPosition(wallBoxPosition);
      pat->setAttitude(wallBoxAttitude);

      osg::ShapeDrawable *sdWallBox = new 
            osg::ShapeDrawable (wallBox.get());

      sdWallBox->setStateSet( dstate );
      wallBoxGeode->addDrawable (sdWallBox);
      pat->addChild (wallBoxGeode.get());

      pat->setUpdateCallback( new UpdateCallback(wall_bodies[wb]));
      tx->addChild( pat.get() );

      wb++;
   }
}
In this loop, we apply the StateSet which contains the definition of our texture to the ShapeDrawable object and then add the ShapeDrawable to the Geode.
osg::ShapeDrawable *sdWallBox = new 
      osg::ShapeDrawable (wallBox.get());
sdWallBox->setStateSet( dstate );
wallBoxGeode->addDrawable (sdWallBox);

The following figure illustrates what the wall looks like with WALLSIZE = 2.0, WALLHEIGHT = 6.0, WALLWIDTH = 20.0.

Using the same code to build the wall boxes, with the exception of the geometry classes used, we can model a textured ball obstacle. The following figure shows the finished product.

Now that the obstacles are modeled, we move onto the Integration step to show how to put all of the elements together into a simulation.

Back to Vehicle Modeling| Proceed to Integration

Copyright © 2006 Brent W. Perteet
Comments? Send E-Mail to brent.perteet _at_ okstate.edu