mjbWorld program - Implementing PROTOs


PROTOs are are a very efficient way to store information where there may be objects that are similar but only differ in a few respects. Examples of such objects might be, animals, plants, manufactured items, buildings, etc. These all tend to be repeated in the world with small differences. Rather than building each instance of these types the PROTO gives us a way to abstract out the common features.

The VRML standard explains that the PROTO statement defines a new node type in terms of already defined (built-in or prototyped) node types. Once defined, prototyped node types may be instantiated in the scene graph exactly like the built-in node types. For me though what is important is not just the ability to define new node types, but that this provides a very efficient and scalable way to store a big 3D model.

The PROTO concept is similar to a subroutine or a procedure call, but without any procedural code.

The PROTO definition object is defined only once, but where parameter values are different for different objects then the parameter value is - IS 'parameter name'.

The diagram below illustrates this, the tree structure on the left contains some small nodes. Each of these nodes only contains 4 parameters, so it is very small and easy to construct and understand. However, as far as the model is concerned, it is as if each of these PROTO calls were replaced by the PROTO definition on the right. This could be any arbitrary size. Most of its parameters will have fixed values, but where the value varies depending on the particular instance then the 'IS' keyword is used map the value, through the interface definition, back to the PROTO call.

Most renderers would work by replacing each PROTO instance with the full structure from the PROTO definition with the appreciate 'IS' values plugged in. However, since mjbWorld is an editor it needs to maintain the original structure. This also hat the advantage of not duplicating all the parameter values in the PROTO definition which are the same for each PROTO call. This does mean that when events are happening, that we need a more complex way of mapping parameter values for the PROTO. The following diagram illustrates how parameter values are mapped in and out of the PROTO when mjbWorld is running:

Most VRML readers would handle PROTOs by creating a complete new copy (instance) of the PROTO every time it occurs in the scenegraph. For instance, if the first node under the PROTO definition is a transformGroup, then when this scene graph is expanded out the tranformGroup under the PROTO definition is replicated everywhere in the scenegraph that the protoCall was (but with any IS values replaced by the values in the protoCall) as follows:

spParam

type:

So when mjbWorld encounters a PROTO and it needs to create a Java3D scenegraph to display in a 3D window, then the Java3D scenegraph will be expanded out as described above. However the internal representation in mjbWorld is not expanded out. This is because mjbWorld is an editor and needs to be able to read and create PROTOs and to save them as PROTOs. Also I think that the PROTO is a very efficient way to store scenegraph information.

Therefore mjbWorld needs to map its internal representation of the scenegraph to the Java3D scenegraph. This mapping of PROTO values is done in the program as follows:

 


Implementation of 'IS' parameter

If a parameter is read inside a PROTO and that parameter has IS value set, then the following sequence of code happens to return the appropriate value:

As an example of this, the above case shows render3d being called on a protoInstance, this results in render3d being called on all the nodes under the PROTO definition.

When get is called on a parameter with is[] non zero, then this links back to the original PROTOInstance as shown.

  1. When render3d is called on a PROTOInstance this calls renderInstance3d on the PROTO
  2. When entering the PROTO then a new instance and max value is pushed onto the top of these arrays,
  3. These values are used when render3d is called on all the subnodes of the PROTO
  4. When a parameter is used in the PROTO and it has 'IS' set use array[instance] value.
  5. If this has not already been set then get value back from PROTO.

Transversing a PROTO in scenegraph

When transversing a scenegraph, say when rendering a scene, and we come to a PROTOInstance then we do not call the sbnodes on the PROTOInstance directly. Instead we call renderInstance3d on the PROTO. If there are any mfnodes or sfnodes with 'IS' values then we jump back to the PROTOInstance.

As an example of this, the above case shows render3d being called on a protoInstance.

When render3d is called on a parameter with is[] non zero, then this links back to the original PROTOInstance as shown.

  1. When render3d is called on a PROTOInstance this calls renderInstance3d on the PROTO
  2. When entering the PROTO then a new instance and max value is pushed onto the top of these arrays,
  3. These values are used when render3d is called on all the subnodes of the PROTO
  4. When a parameter is used in the PROTO and it has 'IS' set use array[instance] value.
  5. Call buildNode on PROTOInstance to start transvering the nodes below the PROTOInstance.

Sequence of events when eventIn received by ProtoCall

 


MFNode and SFNode

MFNode or SFNode passes back control from PROTO definition to the node that called it

So when this is expanded out, each protoCall is replaced by a copy of the transformGroup under the PROTO definition, but the children of each instance of the transform group will be the children of the protoCall that called it.


Example of VRML definition of Proto

For instance if I want lots of spherical objects of different size and colour I could define a PROTO as follows:

PROTO myBlob [field SFFloat.size 3.0 field SFColor.col 1 0 0] {
   Shape {
     appearance Appearance {
       material Material {
         diffuseColor IS col
       }
     }
     geometry Sphere {
       radius IS size
     }
  }
}


myBlob {size 8 col 1 0 1}
myBlob {size 10 col 0 1 1}
myBlob {size 12 col 1 1 0}

How do we implement this? In the case of a program which just displays the scene but does not edit. It is simple just expand out the PROTO calls as follows:

Shape {
   appearance Appearance {
     material Material {
       diffuseColor 1 0 1
     }
   }
   geometry Sphere {
     radius 8
   }
}
Shape {
  appearance Appearance {
    material Material {
      diffuseColor 0 1 1
    }
  }
  geometry Sphere {
    radius 10
  }
}
Shape {
  appearance Appearance {
    material Material {
      diffuseColor 1 1 0
    }
  }
  geometry Sphere {
    radius 12
  }
}

Since this program is an editor we cannot expand out the PROTO when loading the file. This is because we may need to edit the PROTO itself, and also when we save the file we want to keep the PROTO.

Therefore when we load the file we load the information into a set of beans (as described here). The PROTO definition is stored under a protoBean node and calls to the PROTO are stored as protoInstanceBean nodes.

Then then a 3D window is created as set of Java3D nodes has to be created. This is done by traversing the beans, and when a protoInstanceBean is encountered then a copy of the whole structure under the protoBean is created, with Java3D instances, replacing the IS keywords with the appropriate values.


 


nested PROTOs

ProtoCall inside ProtoCall

ProtoCall inside PROTO definition

 

PROTO definition inside ProtoCall

 

PROTO definition inside PROTO definition


metadata block
see also:

VRML

Correspondence about this page

Book Shop - Further reading.

Where I can, I have put links to Amazon for books that are relevant to the subject, click on the appropriate country flag to get more details of the book or to buy it from them.

cover Covers VRML 2 (but not the upcoming X3D standard). A good introduction to all VRML2 node types and how to build them.

cover This book introduces 3D concepts, VRML, Java3D, MPEG4/BIFS, and X3D. It is a very good introduction to the theory, The writers have an in depth knowledge due to their involvement in the standards making. This is a good book to help you choose which 3D open standards to use and to give you a good insight into these standards. It is probably not for those who want a basic introduction to 3D or for these who want a step-by-step programming in 3D book.

Commercial Software Shop

Where I can, I have put links to Amazon for commercial software, not directly related to this site, but related to the subject being discussed, click on the appropriate country flag to get more details of the software or to buy it from them.

 

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2017 Martin John Baker - All rights reserved - privacy policy.