This file describes the VRML node class API. You need this API when
writing a renderer. Each renderer callback function receives as an
argument a pointer to a node to be rendered. This file explains,
among other things, how to read the nodes state, how to post
eventOuts while rendering and how to keep track of dynamic changes
in a virtual world.


Each nodes API consists of an automatically generated part and
a specific part. The automatically generated part concerns the
maintainence of the nodes state as defined in the VRML
specifications or in the input scripts to the nodegen program.
It follows the same principles for all nodes.
The specific part is optional, and differs from node class
to node class. It typically implements utility functions for
renderers (for instance, keeping a 4x4 matrix representation for
Transform nodes).


Node state:
==========

The API for every (leaf) node contains:

- an Is<nodeclass>(SFNode*) routine to check whether an SFNode* 
is a pointer to a node of the given class. For instance:

  extern bool IsBillboard(SFNode*);

- int major_version(void), and int minor_version(void) functions
return the major and minor version of the node, as generated
with nodegen. This is used in the parser in order to detect
potentially out-dated node implementations (there should be no
such out-dated code, but you never know one day, when there
will be run-time loadable node classes e.g.)

- bool is_leaf_class(void): returns whether of not the node is
a lead node class or a base node class. The nodes state is only
completely available for leaf nodes. Parent node classes only
contain part of the state shared by subclasses. A VRML input
file can only contain leaf nodes.

- constructors and destructor, SFNode* instantiate(Proto*),
void render(void): not of interest to the renderer programmer.

- state variables: name and type correspond exactly to the
field and exposedField state values described in the VRML
specifications (or nodegen input scripts), with one exception:
MFNode values are arrays of the proper node class, and
SFNode values are also of the proper class for the field
(for instance Material* for SFNode material field of Appearance 
node).

Example:

  // state values:
  // Do not assign directly unless you know very well what you are doing.
  SFVec3f          	axisOfRotation;
  //  array<Children*> 	children;
  //  SFVec3f          	bboxCenter;
  //  SFVec3f          	bboxSize;

The values that are commented out are declared in a parent 
class.

These values can be read at any time and they can be assigned 
to or even deleted if you know what you are doing:
. no value range checking
. no update bit is set
. no eventOuts are generated (when applicable)
. deleting or changing some variables of some nodes may confuse
(and crash) the default renderer callback functions.
Except in very rare cases where you really don't want to do so, 
you should use the assignement functions described below, in 
particular the set_<exposedField> functions for exposedFields.

- a list of eventIns: for example

  // eventIns:
  void             	addChildren(const MFNode&);
  void             	removeChildren(const MFNode&);
  
Just call these functions in order to send the node an eventIn
data message.

- a list of set_<exposedField> eventIns: one for each 
exposedField member of the node. For example:

  // set_<exposedField> eventIns: with forwarding and eventOut generation
  void             	set_axisOfRotation(const SFVec3f&);
  void             	set_children(const MFNode&);

Use these functions in order to assign a value to an exposedField.
The assignement value is properly forwarded to linked
exposedFields in a PROTO node implementation (if any) and
eventOuts are generated appropriately. After succesful assignement,
the exposedField is marked as "has been updated" (see below).

- a list of assign_<field> functions: for instance

  // field assignement: no forwarding or eventOut generation!
  bool             	assign_axisOfRotation(const SFVec3f&);
  bool             	assign_children(const MFNode&);
  bool             	assign_bboxCenter(const SFVec3f&);
  bool             	assign_bboxSize(const SFVec3f&);
  
These routines assign a new value to a field or exposedField.
The field is marked as "has been updated", but no eventOuts
are generated and neither is there any assignement to linked
fields in a PROTO implementation. For exposedFields, you should
use the set_<exposedField> functions instead. For fields: fields
are not supposed to change value after initialisation. This
routine allows to break this rule if you really need to.

- a list of eventOut values and post_<eventOut> functions:

  // eventOuts:
  //  SFBool            	isActive;
  void             	post_isActive(const SFBool& val);
  SFTime            	time;
  void             	post_time(const SFTime& val);

Use the post_<eventOut> functions with proper argument in order
to post an eventOut from the node. The eventOut is routed to
conencted eventIns (if any) next time the vrml_world::newframe()
function is called. The latest posted value can
be read from the corresponding eventOut member variable, which
acts as temporary storage for the posted value. The variable may
appear commented out in the header file. This is the case if 
the variable is declared for a parent node. In order to override
the posted value before calling vrml_world::newframe for instance
in scripts (no scripting language binding has been implemented 
so far [PhB 20010122]), simply call the post_<eventOut> 
function a second time with the new value to be posted.

- update status bit inspection and clear functions for each
field, exposedField and eventOut:

  // update status
  inline bool      	cycleInterval_is_updated(void) { return (status & cycleInterval_updated); }
  inline void      	cycleInterval_clear_update(void) { status &= ~cycleInterval_updated; }
  inline bool      	enabled_is_updated(void) { return (status & enabled_updated); }
  inline void      	enabled_clear_update(void) { status &= ~enabled_updated; }

The <member>_is_updated and <member>_clear_update routines can
be used in order to keep track of dynamic changes in an environment
being rendered.

Use <member>_is_updated() in order to inspect whether the member
has been updated since the last call to <member>_clear_update().
A field member is updated each time it gets assigned a new value 
(with assign_<field> or set_<exposedField>). An eventOut is
updated each time post_<eventOut> is called for the eventOut.


This part of the API is automatically generated, using the
nodegen program. The current description corresponds to
nodegen 0.4, december 2000.


Utility variables and routines:
==============================

Utility members are declared after the

  // utility members
  
comment in the header file.

They differ from node to node and, until more documentation
is available, a programmer will rely on the documentation provided
in the form of comments in the nodes header file. 

Note for node programmers:
-------------------------

By default, a utility constructor void util_init(void),
copy constructor void util_copy(void) and destructor
void util_destruct(void) are provided as protected node
class member functions. These member functions shall be used
in order to initialise utility variables and to dispose of their
memory when the node gets destructed.


Note on VRML data types:
=======================

The standard data types (SFTime, SFRotation, SFVec3f, SFNode,
MFImage, MFNode, ...) are declared in the header file vrml.H,
which is automatically included in all node class header files.
The MFType types are array templates instantiated for the
SFType types. The array implementation is in Array.H. All data
types need to be converted to standard types (for instance:
SFTime -> double) or to your own data types (for instance
SFVec3f to your own 3D vector class) in order to perform
computations.

Other template classes besides array are:
. associative arrays (Assoc.H)
. stacks (Stack.H)
. linked lists (List.H)
Some day, someone should convince me to use the standard
template library (or something else) instead of these custom
implemented data types.


Philippe Bekaert

January 22, 2001

