4. 3D Graphics

Basic geometries: sphere, box, cylinder, capsule and rays

Basic geometries: sphere, box, cylinder, capsule and rays

This is the 4th ODE tutorial.

This ODE tutorial  teaches you about the 3D graphics, i.e., the Drawstuff library. ODE’s demo program shows the good appearance that are beautiful sky with clouds and  the grid-shaped ground.  This is one of the advantage of  ODE .

However, Drawstuff is a very simple 3D graphics library. It is not suitable for a commercial game, but it may be sufficient for simulators of your own works.  Drawstuff works in Windows and Linux.  The alternates of Drawstuff are  Ogre3D and Irrlicht, both work in Windows and Linux.

Drawstuff is implemented on the OpenGL 3D graphics library. Drawstuff is very simple library, so it may be useful for learning OpenGL.

The APIs of Drawstuff start with the small letters ” ds”,  and the API of ODE start with the small letter ‘d’.

Using  Drawstuff

  • Include the header file to use the Drawstuff library.
#include <drawstuff/drawstuff.h>
  • Settings

In order to use Drawstuff, each member of dsFunctions must be set.

// define of dsFunctions structure
typedef struct dsFunctions {
  int version;  /* set DS_VERSION */  
  void (*start)(); 	/* start function before simulation */
  void (*step) (int pause);	/* step function  */
  void (*command) (int cmd); /* command function for keyboard  */
  void (*stop)();	/* stop function after simulation */
  const char *path_to_textures;	/* a path to the texture */
} dsFunctions;
  • Drawstuff related settings
    • Version: DS_VERSION must be assigned
      • fn.version = DS_VERSION
    • Pre-processing functions: the simulation will be called before the start of the simulation loop. Here, the camera viewpoint and gaze direction are set.
      • fn.start = &start;
    • Viewpoint of the camera, eyes
      • dsSetViewpoint (point of view, the gaze direction);
    • Simulation Loop function: the simLoop function is called  in each loop of the Simulation. The function do  almost every  thing in the simulation, such as compute dynamics, collision detection, and visualization. 
      • fn.step = &simLoop;
    • Key processing function: the command function is called when a key pressed. If you do not need this function.  NULL (null pointer) or 0 (zero) must be assignment to it. 
      • fn.command = &command;  // NULL  or 0 (when you do not need)
    • Post-processing function: the function is called after the simulation loop. If you do not need it, set the NULL pointer.
      • fn.stop = &stop; //  NULL   (when you do not need)
    • Texture path
      • fn.path_to_textures = “path”;
  • The Simulation Loop
    • The following API must be called only once in the main function.

      dsSimulationLoop (argc, argv, witdh, height, & fn);

      • argc, argv: main function arguments
      • width: The width of the window
      • height: The height of the window
      • fn: dsFunctions is a structure for Drawstuff

Sample program

/* ODE tutorial  by Kosei Demura */
/* Lesson 4 3D Graphics          */
#include "ode/ode.h"
#include "drawstuff/drawstuff.h"
#ifdef _MSC_VER
#pragma warning(disable:4244 4305)  // Stop VC++ warnings
#endif
#ifdef dDOUBLE
#define dsDrawBox  dsDrawBoxD
#define dsDrawSphere   dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCapsule  dsDrawCapsuleD
#define dsDrawLine     dsDrawLineD
#endif

#define DENSITY (5.0)

struct MyObject {
  dBodyID body;		// a rigid body
};

dReal radius = 0.25; // radius
dReal length = 1.0;  // length
dReal sides[3] = {0.5,0.5,1.0}; // length of edges
static dWorldID world;  // a dynamic world
static MyObject sphere, box, capsule, cylinder; // objects

// start simulation
static void start()
{
  static float xyz[3] = {5,3,0.5};    // view point [m]
  static float hpr[3] = {-180, 0, 0}; // view direction[°]
  dsSetViewpoint (xyz,hpr);           // set a view point and direction
}

// Simulation loop
static void simLoop (int pause)
{
  const dReal *pos1,*R1,*pos2,*R2,*pos3,*R3;    // draw a sphere
  dsSetColor(1,0,0);      // set red color
  dsSetSphereQuality(3);  // set quality of spere. 3 is pretty good
  pos1 = dBodyGetPosition(sphere.body); // get a position
  R1   = dBodyGetRotation(sphere.body); // get an orientation
  dsDrawSphere(pos1,R1,radius);         // draw a sphere

  // draw a cylinder
  dsSetColorAlpha (0,1,0,1);
  pos2 = dBodyGetPosition(cylinder.body);
  R2   = dBodyGetRotation(cylinder.body);
  dsDrawCylinder(pos2,R2,length,radius);
  // draw an capsule   dsSetColorAlpha (1,1,1,1);
  pos2 = dBodyGetPosition(capsule.body);
  R2   = dBodyGetRotation(capsule.body);
  dsDrawCapsule(pos2,R2,length,radius);

  // draw a box
  dsSetColorAlpha (0,0,1,1);
  pos3 = dBodyGetPosition(box.body);
  R3   = dBodyGetRotation(box.body);
  dsDrawBox(pos3,R3,sides);           // draw a line
  dReal posA[3] = {0, 5, 0},  posB[3]={0, 5, 1.9};
  dsDrawLine(posA,posB);
}

int main (int argc, char **argv)
{
  // set drawstuff
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start   = &start;
  fn.step    = &simLoop;
  fn.command = NULL;
  fn.stop    = NULL;
  fn.path_to_textures = "../../drawstuff/textures";

  dInitODE();              // Initialize ODE
  world = dWorldCreate();  // Create a world

  dMass m;                 // mass parameter
  dMassSetZero (&m);  //set mass parameter to zero

  // sphere
  sphere.body = dBodyCreate (world);     //  create a body
  dReal radius = 0.5;       // radius [m]
  dMassSetSphere (&m,DENSITY,radius); // Calcurate mass parameter
  dBodySetMass (sphere.body,&m);  // Set mass parameter to the body
  dBodySetPosition (sphere.body,0,1, 1); // Set a position

  // Box
  box.body = dBodyCreate (world);
  dMassSetBox (&m,DENSITY,sides[0],sides[1],sides[2]);
  dBodySetMass (box.body,&m);
  dBodySetPosition (box.body,0,2,1);

  // Capsule
  capsule.body = dBodyCreate (world);
  dMassSetCapsule(&m,DENSITY,3,radius,length);
  dBodySetMass (capsule.body,&m);
  dBodySetPosition (capsule.body,0,4,1);

  // Cylinder
  cylinder.body = dBodyCreate (world);
  dMassSetCylinder(&m,DENSITY,3,radius,length);
  dBodySetMass (cylinder.body,&m);
  dBodySetPosition (cylinder.body,0,3,1);

  // Simulation loop
  dsSimulationLoop (argc,argv,960,480,&fn);

 dWorldDestroy (world); // destroy the world
  dCloseODE();              // close ODE
  return 0;
}

Download

That’s all. Next time, let’s learn a body and a geometry.