thanks for providing us with this engine.
In order to learn about the engine and to get a feel of how it works, I am currently skimming through the code and, naturally, I stumbled over BillboardControl and controls in general.
While I absolutely believe that controls are a very useful concept, I also find some issues in the existing architecture/code that I think could be improved upon.
Perhaps you might want to discuss the below proposals.
First, controls are basically behavioural strategies of some sort. This is what I think of them when comparing the existing controls and the information presented in the wiki. As such, I think that these controls should be made stateless and thus should be made reentrant singletons in order to save “tons” of valuable memory on limited devices. The state itself could be externalized to the spatial. The spatial would then be passed as an argument to all methods called during calls to update/render/postrender and so on.
Adding controls to or removing controls from existing spatials would then be as easy as spatial.addControl(MyControl.class) and there would be no longer a need for cloning an instance of a control, effectfully reducing existing code. Of course, there would be the trade off having to look up the instance of the control via a control registry, but I think that this is negligible when comparing it to the fact that there will be much less instances of these controls floating around in the system. Especially when considering the GC overhead.
Second, when I look at the fixRefreshFlags() method of the BillboardControl, which in turn gets called by all of the rotate*() methods which in turn are invoked bycontrolRender() via a call to rotateBillboard(), I find that it calls upon spatial.updateGeometricState() every time the control is rendered. And it will then determine the root node from the spatial and make it update its world bounds. While this is correct, it adds tremendous call overhead when using “thousands” of billboards in a scene.
Even more so when considering that updateGeometricState() and getWorldBounds() will already be called by SimpleApplication#update() after that all spatials have been updated recursively.
What I propose is that the existing code found in BillboardControl#controlRender be moved to BillboardControl#controlUpdate so that it can be called during the update phase.
This would then allow you to simply remove the BillboardControl#fixRefreshFlags() method, as the geometric state and the world bounds will be updated during the call to the SimpleApplication#update() method prior to that RenderManager#render() is called.
But perhaps I have overlooked something and there is a good reason for having BillboardControl making all these redundant calls?