Optimizing Methods and getWorldTranslation

Hello.
I’ve had an issue for quite some time which has caused me to revert to de-optimizing my application due to strange behaviors.

I have an “AtomSpatial” which is a spatial class, its simply a sphere with a material and texture.
I also have a “MoleculeNode” which is a node. MoleculeNode’s are the parents for the AtomSpatials.

Now if I call AtomSpatial.getWorldTranslation(), everything is fine (as its not optimized).

Method #1:
I change the MoleculeNode to extend from BatchedNode rather than Node, after adding all the AtomSpatials as children, I call MoleculeNode.batch().
This method doesnt seem to do ‘anything’. It doesnt screw up the coordinates of AtomSpatial.getWorldTranslation() and it doesnt increase fps either (if it does it
a minimal increase).

Method #2:
Instead of adding the AtomSpatials directly to the MoleculeNode, I create a new Node which I’ll call (“OptimizedNode”).
The AtomSpatials are then added to the OptimizedNode. Once they are all addeed, GeometryBatchFactory.optimize() is called.
Once the OptimizedNode is optimized, it is then added to the MoleculeNode as a child.
This screws up the AtomSpatial.getWorldTranslation() completly.

Method #3 (Physics Engine Unstable):
Instead of Method #2, I have tried directly adding the AtomSpatials to the MoleculeNode and then calling GeometryBatchFactor.optimize() on the MoleculeNode itself.
This caused unpredictable and odd behaviour when I attached a RigidBodyControl to the MoleculeNode and simulated physics.

I was using Method #2, because it had the best results aside from the coordinate mismatches when I used AtomSpatial.getWorldTranslation(). It seemed that AtomSpatial.getWorldTranlation while being optimized was returned getLocalTranslation instead.
Then I figured, well if I know the local translation of the AtomSpatial and I know the Transform of the parent MoleculeNode, I should be able to calculate the “BatchedWorldTranslation”:

[java]public Vector3f getBatchWorldTranslation() {
//Get the parent compoundNode Position
Vector3f batchedPos = this.getParentMoleculeNode().getWorldTranslation();
//Offset the position with the AtomModels local translation and parent compoundNode Position
Vector3f offset = batchedPos.add(this.getLocalTranslation());
//Get the rotational state of the compoundNode
Quaternion molRot = this.getParentMoleculeNode().getWorldTransform().getRotation();
//Mult the rotation with offset to get position
Vector3f newPos = molRot.mult(offset);

     return newPos;
}[/java]

This seemed to be a fairly decent solution, but its odd. It’s odd because when I try to calculate the distance between 2 atoms using getBatchWorldTranslation() it seemed to give me erratic and illogical results.

Can someone please shed some light on the optimization process and what may be a valid and elegant way to retain the positions of the batched Spatials?
Furthermore can someone please explain why extending from BatchNode and calling batch() does not yield any difference in performance?

Regards,
ostenning

Do all of your children have the same Material instance?

What version of JME are you running?

Do they all have different materials? Only objects with the same material get batched.

As a side note we don’t recommend extending node/etc for most cases. Just use a standard Node/Geometry and then attach controls/add materials/etc to give special behaviour.

<cite>@zarch said:</cite> As a side note we don't recommend extending node/etc for most cases. Just use a standard Node/Geometry and then attach controls/add materials/etc to give special behaviour.

Who is we? O.o I extend Node or Geometry if and when it is the proper/best solution. I think recommending NOT overriding default behavior or don’t expect dev support would be a more accurate statement. Telling someone not to do something without the reason is like saying “Please, if you do nothing else, do this thing here that I just told you not to do.” :stuck_out_tongue:

@t0neg0d said: Who is we? O.o I extend Node or Geometry if and when it is the proper/best solution. I think recommending NOT overriding default behavior or don't expect dev support would be a more accurate statement. Telling someone not to do something without the reason is like saying "Please, if you do nothing else, do this thing here that I just told you not to do." :P

The architecture is designed so that you usually don’t have to extend Node or Spatial. One should generally prefer composition over inheritance and JME provides this through Controls.

Sometimes there is a good reason to do so… but it seemed to me too like OP was doing it just as a general pattern of behavior and not necessarily as an informed design choice.

<cite>@pspeed said:</cite> The architecture is designed so that you usually don't have to extend Node or Spatial. One should generally prefer composition over inheritance and JME provides this through Controls.

Sometimes there is a good reason to do so… but it seemed to me too like OP was doing it just as a general pattern of behavior and not necessarily as an informed design choice.

I agree that this is the case… the point was… telling someone not to do something without at least a hint as to why it may not be the best choice is inviting someone to ignore your suggestion. Now the OP has 2 good reasons to reconsider :wink:

Hello, thanks for the replies.
I have subclassed Node and Spatial because I need each of these to contain information and behave like a struct. I have not overrided any functionality of the Node or Spatial classes, so I didn’t think it would be a dangerous situation. Besides from adhering to JME3 best practices, are there any performance based reasons for not extending Node or Spatial?

Back onto topic:

All the AtomSpatials contain the same shape, a Sphere. The only difference between the types of atoms (Eg, Oxygen and Hydrogen), is the radius
of the sphere and the color.
Therefore for a SimpleApplication that contains hundreds of atoms, they will be 1 of 4 types, Hydrogen, Carbon, Nitrogen or Oxygen.

<cite>@pspeed said:</cite> Do all of your children have the same Material instance?

What version of JME are you running?

So I guess, No, not all the children of the MoleculeNode contain the same Material instance. Infact, they all have a “separate” instance because I re-instantiate the material every time I call the AtomSpatial constructor.
Should I make a static Material instance for each of the 4 materials (H,C,N,O etc) and reuse it?

Running the latest JME3 release candidate 2, but I’ve updated it to the lateste version (Not using nightly builds).

Regards,
ostenning

(P.S, thanks for the help).

If you use different material instances then batching won’t really do anything, actually. So sharing the materials where possible would be one place to start.

Alternately, you could avoid batching and just treat the whole set of atoms like a particle system where the particles never die.

Your example potentially is a good case for why we recommend not extending these classes. You’re doing it to mix your domain model with the visualization… which is usually a bad thing in the long run.

Hey,
Thank you for the architecture advice, I’ll revise mixing the model and visualization. Perhaps ill revert to a more MVC style architecture.

I created a shared instance of each of the 4 materials which represent the 4 atoms and used the BatchNode and batch() method, this didn’t really yield any performance gains once again.

The only notable and realistic optimization is the GeometryBatchFactory.optimize() method which yields outstanding performance results (which is what i’ll have to use).

Are there any techniques to getting the worldTranslation of each individual children inside the optimized Node? Such as the getBatchWorldTranslation() method I described in the first post?

Regards,
ostenning

It seems like for some reason batch node is not doing anything. So something must be wrong with your setup because it internally uses almost the same logic as batch factory optimize except that it keeps the children around.

Then again, are your children loaded up with controls or something? Or do they otherwise do per-frame processing on their updateLogicalState?

I think if you are going to be using something other than batch node then your best bet is to just do everything in world space from the beginning.

@pspeed said: It seems like for some reason batch node is not doing anything. So something must be wrong with your setup because it internally uses almost the same logic as batch factory optimize except that it keeps the children around.

So If i manage to get BatchNode.batch() working properly, I should be able to call childSpatial.getWorldTransform() on a child and get the correct coordinate information?

@ostenning said: So If i manage to get BatchNode.batch() working properly, I should be able to call childSpatial.getWorldTransform() on a child and get the correct coordinate information?

Yep. They would work just like regular children.

Oh… I bet it’s your subclassing that has messed it up since it would only check for proper Geometry objects I bet.