Using your own Classes with scenegraph.io
The scenegraph.io API's will handle the IO for all the core Java3D SceneGraphObjects. However if you create a subclass of one of these objects and add it to your Scene Graph the IO system, by default, will not store any state information specific to your class.
The default behavior when an unrecognised SceneGraphObject class is encountered is to traverse up the superclasses of the object until a recognised Java3D class is located. The data structures for this class are then used for IO. The system does store the class name of the original object.
For example, if I create a class with thus
public class MyBranchGroup extends javax.media.j3d.BranchGroup {
private int myData;
....
}
When the Scene Graph is written to a file and this node is encountered the superclass javax.media.j3d.BranchGroup will be used to store all the state for the object so any children of MyBranchGroup and the capabilities etc will be stored but myData will be lost. When the scene graph is loaded MyBranchGroup will be instantiated and will be populated with all the state from BranchGroup but myData has been lost.
To overcome this the scenegraph.io API provides an interface which you can implement in your own classes which provides the opportunity for you to save the state of your classes during the IO processes. This is the SceneGraphIO interface.
When the scenegraph is saved, the methods of SceneGraphIO are called in this order
createSceneGraphObjectReferences
saveChildren
writeSceneGraphObject
During the load cycle the method call order is
Instantiate Object using default constructor
Populate object with state from superclasses
readSceneGraphObject
restoreSceneGraphObjectReferences
Within each method you need to perform the following actions
createSceneGraphObjectReferences If your object has references to other SceneGraphObjects then you need to obtain an object reference (int) for each reference using the SceneGraphReferenceControl object passed as a parameter to this method. If you don't have references to other SceneGraphObjects then no action is required
saveChildren If your object is a subclass of Group and you want the scenegraph.io package to save the children then this must return true. If it returns false the object will be saved but not it's children
writeSceneGraphObject In this method you must write all the state information for your class, including the object references obtained in createSceneGraphObjectReferences to the DataOutput stream passed into this method
readSceneGraphObject By the time this method is called your class has been instantiated and the state information in the Java3D superclass will have been loaded. You should load all the state information you saved for your class.
restoreSceneGraphObjectReferences is called once all the SceneGraph objects have been loaded and allows you to restore the references to the other SceneGraph objects.
Here are some examples, only the parts of the source pertaining to IO are show....
Behavior
public class BehaviorIO extends javax.media.j3d.Behavior implemented SceneGraphIO
private TransformGroup target; // The TG onwhich this behavior acts
private int targetRef; // Object Reference for target
public void createSceneGraphObjectReferences( SceneGraphObjectReferenceControl ref ) {
targetRef = ref.addReference( target );
}
public void restoreSceneGraphObjectReferences( SceneGraphObjectReferenceControl ref ) {
target = (TransformGroup)ref.resolveReference( targetRef );
}
public void writeSceneGraphObject( java.io.DataOutput out ) throws IOException {
out.writeInt( targetRef );
}
public void readSceneGraphObject( java.io.DataInput in ) throws IOException {
targetRef = in.readInt();
}
public boolean saveChildren() { // This has no effect as this is not a subclass of Group
return true;
}
'BlackBox' Group
This example is a Group node which creates it's subgraph during it's instantiation, an example where you might use this is to represent some geometry which is loaded from an external file format such a OpenFLT.
public class House extends Group implements SceneGraphIO
public House() {
super();
this.addChild( OpenFlightLoader.load( "/dir/house.flt" );
}
public void createSceneGraphObjectReferences( SceneGraphObjectReferenceControl ref ) {
// No references
}
public void restoreSceneGraphObjectReferences( SceneGraphObjectReferenceControl ref ) {
// No references
}
public void writeSceneGraphObject( java.io.DataOutput out ) throws IOException {
// No local state
}
public void readSceneGraphObject( java.io.DataInput in ) throws IOException {
// No local state
}
public boolean saveChildren() {
// Don't save the children as they will be restored by the openflightloader
return false;
}