VRML documentation

The file world.html shows how to an application can use the build-in vrml parser to parse and render a world. However, building up your own world manually (instead of calling the build-in parser) is a little bit more involved.

However, it's pretty easy once you know how it works. I'm therefore demonstrating it in a few, well-documented examples.

# Example 1 : creating a simple scenegraph consisting of 2 gray triangles

    /*
       include all necessary include files
    */
    /* header file declaring the toy::importer class as a sub-class of
     * xrml::importer. */
    #include "importer.H"

    #include "xrml.H"
    #include "IndexedFaceSet.H"
    #include "Group.H"
    #include "Material.H"
    #include "Appearance.H"
    #include "Transform.H"
    #include "Shape.H"
    #include "world.H"

    using namespace xrml;  // so we can omit the xrml:: name space prefix

    // this routine gets called from
    // xrml::world::parse(filename, start_time, toy_importer)
    // if toy_importer points to an object of the class toy::importer
    // being implemented here.
    bool toy::importer::parse(class world* world, char **strpool)
    {
      // builds up an example scenegraph for the specified world
      // this example only creates 2 gray triangles, but already shows
      // most of the important things....

      // The world object being passed has a sceneGraph MFNode array
      // (declared in xrml.H and derived from xrml::array in Array.H).
      MFNode *sg = world->sceneGraph;

      // If you care, you can set the global variables indicating the
      // file name and line number at which a node is parser. This
      // information can be used for error reporting later on.
      xrml::current_filename = "blabla";
      xrml::current_linenr = 1;
      // Of course, this is not very meaningful for this example.

      /*
        generally, for having 2 gray triangles, we basically
        need an indexedfaceset to specify the geometry for the triangles,
        and some gray material for them.
        in order to apply the material to the triangles, we have to pool them
        in a shape node.
      */

      /*
        generate the material that is to be used in the appearance node
        values are always assigned to fields of a vrml-node by calling
        node->assign_ with the appropriate values
      */
      Material *material = new Material; // create a new material
      SFColor gray(.6,.6,.6); // get a color to assign
      material->assign_ambientIntensity(SFFloat(.6));
      material->assign_diffuseColor(gray); // set the diffuse color to gray
      material->assign_emissiveColor(gray);// set the emissive color to gray

      /*
        now, put this material in an appearance node
        materials can only be applied to geometry through appearance nodes...
      */
      Appearance *appearance = new Appearance; // create a new appearance node
      appearance->assign_material(material);   // ... and assign our gray material

      /*
        after having generated the appearance, we're generating the geometry.
        first, we specify the vertices of our triangles.
      */
      float vert_xyz[12] = { 0., 0., 0.,  0., 1., 0.,  1., 0., 0.,  1., 1., 1. };
      MFVec3f coords(4, (SFVec3f*)vert_xyz);

      /*
        create a coordinate node that can hold the vertex positions
        the coords can not be assigned directly, but only through a coordinate
        class. the same applies for normals, texturecoords aso...
      */
      Coordinate *coord = new Coordinate;
      coord->assign_point(coords); // assign our array or vertex positions

      /*
        after having the vertex positions, we have to generate the index-array for the
        faces in basically the same way. specify a MFInt32 field and assign the indices
      */
      SFInt32 indices[8] = { 0, 1, 2, -1, 1, 2, 3, -1 };
      MFInt32 index(8, indices);

      /*
         There are various ways of constructing MFxxx (array) objects. See
         the Array.H include file and the TOOLS/testarrayassign.C code
         fragment.
      */

      /*
         after having both the index array and the coordinate node,
         we can put them together in a new indexedfaceset
      */
      IndexedFaceSet *ifs = new IndexedFaceSet; // create a new indexedfaceset
      ifs->assign_coord(coord);                 // assing our coordinates
      ifs->assign_coordIndex(index);            // assign the index-array

      /*
         now that we have both the appearance and the geometry (the indexedfaceset,
         which is a subclass of geometry), we can put them together with a shape-node.
         basically a shape node is the only way how to bring geometry and materials together...
      */
      Shape *shape = new Shape;             // generate a new shape
      shape->assign_appearance(appearance); // take our previously defined appearance
      shape->assign_geometry(ifs);          // assign our indexedfaceset-geometry

      /*
         we're almost done : just add the newly created shape (our two-triangle-indexfaceset
         with a gray-material-appearance) to the scenegraph...
      */
      sg->append(shape);

      return true;
    }