Node construer

I was looking at the could for Node I think that the empty construer should be:

private Node() {}

not:

public Node() {}

No, there are empty constructors in there for things like serialization and so forth… ie. the ability to say Class.forName("…"), etc.

Then I think you should create a instance of children, or you should check if it is null in update ext.

Why, people who write deserialization routines should instantiate children as well since they would have serialized with children.

I mean the object children. You get a hard to fined bug, because children is null, making JME hard to use.

How and why are you using the empty constructor? It’s meant only for serialization, not for developer use.

"renanse" wrote:
No, there are empty constructors in there for things like serialization and so forth... ie. the ability to say Class.forName("...."), etc.

What do you need to serialize Nodes for?
I ask this since I fell into the pit of creating a node by calling it's default constructor and not passing a name, which gives you nice Exceptions when trying to actually do something with it.

I took advantage of the default constructor in my Keyframe controller.


class EmptyTriMesh extends TriMesh{
    public EmptyTriMesh(){
        this.texture=new Vector2f[1][];
    }
    public void setVertices(Vector3f[] storageArray){
        this.vertex=storageArray;
    }
    public void setNormals(Vector3f[] storageArray){
        this.normal=storageArray;
    }
    public void setColors(ColorRGBA[] storageArray){
        this.color=storageArray;
    }
    public void setTextures(Vector2f[] storageArray){
        this.texture[0]=storageArray;
    }
    public void setIndices(int[] storageArray){
        this.indices=storageArray;
    }
}



This way, buffers aren't created for no reason. I also save memory on not having to create translation/rotation/scale object and anything else. I can now use EmptyTriMesh with my KeyframeController that will only take TriMesh objects and everything will be ok because KeyframeController only uses the arrays of a Mesh. I've taken advantage of the default constructor at times but I do agree it can be confusing. It was for me when I first started
"batman.ac" wrote:
What do you need to serialize Nodes for?
Saving a scene to a file?
"batman.ac" wrote:
I ask this since I fell into the pit of creating a node by calling it's default constructor and not passing a name, which gives you nice Exceptions when trying to actually do something with it.
Right, however as the javadoc says "this is for internal use only". Sorry, if I sound a bit annoyed, but why do people ask for more documentation if they don't bother looking at what we already have? :?

Ok, I’ve had a bit of breakfast now and am looking back at this a bit with a more level head. (so be prepared for a long winded post… :)) Empty constructors were added to major scene classes so they could be instantiated by name by loaders that would be responsible for setting important class fields with data. Ideally, such loaders would not have to know about each specific class, what fields it requires, and all about its constructors. Our current XML/Binary readers do need to know that information and thus have to be maintained if these objects change.



From another project I’ve done, I have a class agnostic xml loader and saver that can take any java object and it’s child fields, hashes, vectors, treesets, or whatever and store them to xml. It can also reinstantiate those classes from the xml. To do this though, it obviously requires an empty constructor, otherwise it would have to scout through possible constructors and take a guess at what data to send as arguments (a messy and flaw-prone approach.) I use this xml (de)serializer in my game to store and load terrain in jars… (very fast I might add)



Anyhow, history aside… If there is a call to use these special constructors for other uses, we should go in and have basic fields instantiated on all of them. Just remember though that every object is supposed to have at least a unique name, so we’d have to systemically create names which may look ugly or make it harder to tell scene sections apart – names assigned to a given node could change with each run, for example. Other classes may likewise require a basic set of data to properly construct unless you are prepared to manually set all fields (eg. as in the case of a loader.)

Ideally, such loaders would not have to know about each specific class, what fields it requires, and all about its constructors.


There is an XMLLoadable interface that can be used that allows loading user defined classes without changing the XML load code.

Yep, looks great, but as you see it required an empty constructor.



To be fair, the loader you’ve created has the potential to be more powerful in the jME world since it doesn’t have to be generic, etc. Have you tried saving a terrain object?

"renanse" wrote:
From another project I've done, I have a class agnostic xml loader and saver that can take any java object and it's child fields, hashes, vectors, treesets, or whatever and store them to xml. It can also reinstantiate those classes from the xml. To do this though, it obviously requires an empty constructor...

If empty constructors are needed for this purpose, does that means, that if I would like to use such a mechanism myself, all classes which I derive from Spatial would need such constructors, too?

yes, any class deserialized with the newInstance() method needs to have an empty constructor or you’ll get an InstantiationException.

With reflection, I can create any class I want as long as I have the name of that class. For example, I can take the string "com.jme.scene.node" from a file and create that class. The problem is that just like in real java, reflection needs to know how to construct that class, IE which constructor to call. There are ways to call something besides the default constructor, but signaling how to call what constructor can be complex considering I have to construct the parameters of the constructor as well (which kind of brings us back to square one about the default constructor).

"renanse" wrote:
yes, any class deserialized with the newInstance() method needs to have an empty constructor or you'll get an InstantiationException.

Then having a default constructor for every class derived from spatial should not be considered for internal use only, but a necessary design issue and all classes should provide it or else the serialization/deserialization is broken. Have a look at eg. com.jme.scene.Line.

I agree, it just hasn’t been done yet. Consider that this is a .6 product.

I just had a really strange idea, and have no clue if this would work or not, but what about making the default constructor throw an “InternalUseException”. This way, users will know to definantly not use it. Whenever we want to use it for class instantiation purposes, we’ll just catch and throw that error ignoring it. Just a thought.