Adding a new component


The X3D specification contains the ability to add new functionality, such as new "standard" node types through the use of components. Each component is a collection of nodes that represent some common type of functionality - such as terrain modelling, geometry, texturing or scene graph structure. Within each component, there may be multiple levels of support available. These levels are heirarchical in that a higher level includes the complete set of functionality from all the lower levels.

Apart from PROTOs, components are meant to be the smallest level of pluggable functionality that can be added to the VRML scene graph. While protos are used for individual files, a component is used to describe a collection of functionality, that ideally should be supported across multiple browser instances. With this in mind, Xj3D supports components right out of the box and has support built in to all you to easily implement new components.

Profile Management in Xj3D

As a toolkit, Xj3D has to be much more flexible in its management of profile information compared to a traditional browser. The way the end user decides what capabilities are to be used needs to be ignored so that profiles and components always are used. So, to do this, we use dynamically loaded configuration files that tell us where to find everything. No node is hard coded in the system.

The codebase will automatically make use of profiles and components if you use the standard classes. The focus of this handling is the factory classes that produce node instances. The standard factories are used throughout the code, so the effects are consistent across the code. If you decide to use something other than our standard factory mechanism, and implementation, then you are on your own as you will need to implement your own profile/component manangement system.

Within the provided code, the class to focus on is org.web3d.vrml.renderer.DefaultNodeFactory. This implementation of the org.web3d.vrml.nodes.VRMLNodeFactory manages the full profile and component handling within the toolkit. We'll base the rest of this tutorial around how this class describes and works with profiles and components.

Writing a new Component

Working with components is a relatively simple task, but is extremely time consuming. Most of the work goes into implementing all the nodes for that profile for all the different renderers that are available. While you can create a component that is supported by only one renderer, we highly discourage the practice.

Writing a new component implementation starts with defining an extension file. All these files can be found, normally, under the src/config directory in SVN. Under that directory, you'll see sub directories that are defined by specification version. Since nodes, profiles and components change in each revision of the spec, we need to be able keep each set of definitions separate. What may be a custom Xj3D extension in one version, may have moved up to an ISO-approved extension in the next version.

To define the component definition, go to the directory of the spec version that you're going to be working with. Under that you will find a directory called components. Change into that. In there you will find a collection of XML files already defined. Each file is named precisely after the component name. So, say your new extension will be using the label "xj3d_Foo" in the COMPONENT declaration, then you will need to create a file in this directory called xj3d_Foo.xml. Capitalisation is extremely important.

The contents of the XML file are relatively straight forward. Let's start with an example, using our picking extensions as a base point:

  <component name="xj3d_PickingUtilities" title="Xj3D Picking Utilities Extension component" levels="3" url="">
    <nodeLocation type="java3d" package="org.web3d.vrml.renderer.j3d.nodes.picking"/>
    <nodeLocation type="null" package="org.web3d.vrml.renderer.norender.nodes.picking"/>
    <nodeLocation type="ogl" package="org.web3d.vrml.renderer.ogl.nodes.picking"/>
    <componentLevel level="1">
      <node name="PointPicker"/>
      <node name="LinePicker"/>
      <node name="PickableGroup"/>
    <componentLevel level="2">
      <node name="PrimitivePicker"/>
    <componentLevel level="3">
      <node name="VolumePicker"/>
The entire definition is wrapped in the componentConfig element. Underneath that you define the component element and provide a number of informational attributes. The name attribute should match the name of the file and of the component. The title is a basic textual description of the component. You may also provide an optional URL. This has no functional use within Xj3D and will be used only for display purposes. The URL should point to the homepage of the implementation of the component, such as your company or university project.

Finally, there is the level attribute. The value provided is required to be a positive integer that describes the maximum level of conformance to the component. A component may be specificed to have 3 levels, but your implementation only provides two. This property allows you to control what is made available to files that are to be viewed. Note that this should only be defined based on the nodes implemented, not on the maximum required by the specification.

As we mentioned before, there are multiple renderers available within Xj3D. The next series of elements define which packages to look for implementations of the nodes for each renderer type. The element name starts with the renderer type and should be one of four values null,java3d, ogl or mobile. Others could be defined, but only if you are coding up your own renderer should you use different values. There should be one element declaration for each renderer in the system and the value is the package where you can find the implementation classes for that component. Note that our requirement is for all classes for a component to exist in a single package. You cannot spread your implementation over multiple packages, but it is fine for multiple components to place their code in a single package.

Lastly is the definition of exactly which node is available at which level. Most component specifications provide new nodes as you go to higher levels. The componentLevel element defines a list of the nodes that are added at that level. In some components a higher level just adds more capabilities to a node that was introduced at a lower level. There is no need to re-declare the new node there as the factory assumes that nodes are cumulative as you go through the levels.



[ Xj3D Homepage | Xj3D @ Web3d | Screenshots | Dev docs | Dev Releases | Conformance | Contributors | Getting Started ]
Last updated: $Date: 2005-10-12 16:39:28 $