BillboardControl and Controls in General

Get rid of that gay and JME3 will prosper.

Oops, I meant “guy” and not “gay”.

Telling you that you have more to learn on this subject is not trying to insult you. It’s just plain to see. All this thread has shown so far is the lengths you will go to avoid holding state in a control. We already threw the baby out with the bathwater a long time ago when you moved the state into a separate data structure. So at most now you are saving 16 bytes or so (which you use again and then some in the map implementation anyway) all to cling tightly to the “control as singleton” thing… for now, no apparent benefit.

But ok. I will stop what I’m doing and try to explain.

For each Geometry in the scene, (every one of your 1000 billboarded blades of grass), JME must:
-updateLogicalState()
-updateGeometricstate()
-cull it
…presuming it isn’t culled…
-runControlRender
…which updates orientation based on the spatials world location relative to the camera, no shortcuts here
-queue it
-sort it by depth against its 999 brothers
-make sure the current OpenGL state matches its materials
-send its various mesh buffers to the GPU or make them current
-apply material parameters
-draw dispatch to the GPU
x1000

The Billboard update is an insignificantly small part of that. It’s also an insignificantly small amount or RAM compared to everything else there.

You mention “enemies rapidly spawning and despawning” but you fail to mention how storing state in the Spatial has any different lifecycle than storing state in the control. The control is actually a much more efficient way of storing state because a) it’s flat, b) it’s localized, and c) it’s just fields.

And BillboardControl has the least state of pretty much all of the controls, really. AnimControls, MotionTracks, etc. all hold way more data. In those cases it truly is spatial specific.

But since I’m taking the time and you didn’t really take the hints to investigate more, let’s discuss your first post in detail.

@axnsoftware said: 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.

Here is where you propose moving spatial+control-specific state out of the control for some reason. Net memory gain = -external data structure overhead

@axnsoftware said: 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.

Oh, and now you’d have to look up all control+spatial-specific state from an external data structure potentially several times a frame. Net performance gain = -external data structure overhead

@axnsoftware said: 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.

A) it cannot be otherwise. Only in controlRender() has everything else been updated to the point that the billboard can be safely oriented. And because the other updates have already been called, we need to make sure the flags are up to date so we don’t get an error. Note: only spatials that have already passed culling will have their controlRender() methods called.

B) as already discussed, 1000 billboards is already one of the worst scenes you can construct and a sign that the game design needs to be revisited.

@axnsoftware said: Even more so when considering that updateGeometricState() and getWorldBounds() will already be called by SimpleApplication#update() after that all spatials have been updated recursively.

In fact, it was already called before culling… we are much later than that when we recall it to fix the flags.

@axnsoftware said: 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.

It can’t be because all of the updates have to have been called before the billboard can be properly oriented. Otherwise, parent rotations, camera movement, etc. won’t be taken into account.

@axnsoftware said: 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?

Yes, what you overlooked was already explained in the third post in this thread: http://hub.jmonkeyengine.org/forum/topic/billboardcontrol-and-controls-in-general/#post-255562

To answer your line of thinking regarding billboard controls… really don’t use them in your example cases. The whole line of thinking that they should be “first class citizens” is problematic because now you are modifying the architecture for what should be a relatively rarely used class. And then what about the next control that needs to do the same thing?

As already discussed, if you want to billboard 1000 objects then there are way way way more efficient ways to do it that don’t use billboards (or even 1000 geometries) at all.

In telling me that I would have to learn more about implementing games and game engines, you are actually telling me nothing new since I never have implemented any of such kind.
However, when looking at the way billboards are being handled, I see that there is massive potential in optimizing an otherwise great engine.
And, yes, I am rather new to the topic at hand but I know my tools and I detect faults when I see them. And the way that billboards are being handled is utterly wrong.

@axnsoftware said: In telling me that I would have to learn more about implementing games and game engines, you are actually telling me nothing new since I never have implemented any of such kind. However, when looking at the way billboards are being handled, I see that there is massive potential in optimizing an otherwise great engine. And, yes, I am rather new to the topic at hand but I know my tools and I detect faults when I see them. And the way that billboards are being handled is utterly wrong.

I’m not really sure how to explain it any differently. There are good reasons that it is the way it is and the alternatives are much worse. The performance you attempt to gain with these changes will likely not affect framerate even slightly but would complicate the code considerably.

Efficient billboarding can only be done in the shader.

  1. Create class MyStatelessBillBoard
  2. Make it implement the Control interface (https://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/core/com/jme3/scene/control/Control.java)
  3. Implement the class as stateless, feel free to use code from the existing BillboardControl

Then one of the following:
A) It works in the existing design of the engine - benchmark it and try to get people interested in using it, make a plug-in, if it is good eventually it will slowly replace the existing implementation.

B) Realize that the entire engine needs a redesign - fork the code base, make a new engine, benchmark it and try to get people interest in using it.

This thread is hilarious and has been most entertaining :lol:

Ok, i’ll come into this discussion, as it seems to be a fun one. Just sad that i didn’t look at it before.

First of all, let’s throw some semi-troll sentences

“The first rule of program optimization: don’t do it. The second rule of program optimization (for experts only!): don’t do it yet.”

Ok, that said, i’ll also try to give a hint about why the billboard’s update is done in the controlRender method : it’s because you can have more than one viewport in your scene, and, so, more than one point of view. If you want to have a billboard always facing the one looking at it, you have to update it into the rendering step.

Secondly, don’t believe that you are smarter that the compiler. Really. There is tons of optimizations made by the compiler, and use a “stateless” approach for classes without attributes is likely something already optimized. You know, the compiler doesn’t copy all the methods when you create a new object.

Plus, you can already do this if you want. Just create your appstate and put the map in there. Oh, you’ll maybe create some memory leak cause of that, because, you know, as it is now, if you just remove a spatial its controls go out of reach and are gc-able (i think, i didn’t test to be honest). With a map, you’ll maybe create some “fake” references, and prevent the gc.

If you want to save memory, “small” optimizations like this are pointless. You want optimization ? Use the system in doom where textures in black (appearing to be in the dark, shadowed to complete black) doesn’t have texture at all. Improve the culling system to remove from the scene unseeable objects (behind a door etc.). Don’t use thousands of billboards, create a shader.

For your credit, i can say 2 thing :

  1. you tried to push a design pattern, which is a good thing. It means that you are a good student, as most of student don’t care about design patterns (and complain during exams when they don’t know answers about them)
  2. You are a bit right : there is SOME aspect of jme that need optimizations. Not the one you pointed out, however.

i think this conversation over billboards is a little overkill.

i mean seriously, the billboard control is INCREDIBLY lightweight. just about all controls are.

Controls don’t even do anything serious. all they are is a small object that holds a small snippet of code to modify how the spatial is displayed. (for instance rotating it).

The execution time per frame of the control (and most controls) is so small that you probably couldn’t even measure it using System.currentTimeMillis()

controls exist so you dont have to have a variable called “hashMapSpatialsThatBillboard”.

it’s an organizational convenience, and theyre completely optional…

If youre THAT worried about the minor performance details of your application, you probably shouldnt even be coding in java.

After having further analyzed the existing code, I must come to the conclusion that PSPEED was right in his assumption that billboards need to be updated during the rendering phase, since they need to be updated once for each viewports’ camera in order to render them correctly.

However, assuming me to be a troll was simply outrageous and it simply ticked me off.

And, looking through the existing posts on this forum, I see other OPs who had been ticked off by other developer replies.

As such, I presume that ingenious developers should need to take more care when replying to posts on this forum.

What I would have liked from PSPEED, was that he would have hinted me on having a more closer look at the rendering phase, instead of ranting about how inefficient billboards were. Of course he is right in his overall assumption, yet, it left me sort of stranded as I am not too familiar with the engine itself.

What I would also like is that you, as you are very familiar with the overall engine and the site, present more links towards existing content instead of merely relying to, “that it is available in the wiki”.This would be a great help for newcomers, TIA.

Hope no harm was done, and, considering our both mental and physical states at the time of the original posting, I presume that we have since gotten over it :smiley:

In my defense re: the “troll” comment. Each of your responses got longer and longer than the last and for whatever reason, in my mood, I read this bit as a condescending lecture on how “java memory” works.

@axnsoftware said: Actually, in the Java world this might make a difference in that the less short lived objects created, the better the performance and overall memory footprint. Considering a game where a lot of enemies with at least 3 or more controls added to them will be spawned during an intensive fight, the less objects that have to be instantiated and subsequently will have to be deallocated, the more responsive the game would be, or would it not? Even more so on memory limited devices such as Android based phones, tablets or consoles. The same holds true for iOS based phones and tablets, of course.

And, considering these massively spawned enemies, a proficient developer would optimize so that the game’s framework would be reusing existing instances whenever possible.

The last bit about “proficient developer” just threw me over the edge. I was sure at that point you were just trying to get a rise out of me so I asked.

I think my responses up to that point escalated normally in frustration as it became clearer and clearer that you either weren’t understanding what I was saying or weren’t willing to put the research in to check it out. Plus the whole state thing which just kept going further and further down a path. Given the sum of the evidence, the whole stateless thing felt like an attempt to draw out an argument for no other reason than to waste time.

Generally, (not always but mostly) we are respectful to the folks that respect our time as well. I think if you look back at my first few posts you can see that I was trying to tell you what you needed to know but had trouble finding common ground on where the disconnect was.

I think maybe another lesson to take away is that when you walk into a room full of smart people and start telling them they did things wrong then you should have all of the evidence in hand.

@bubuche said: Ok, that said, i'll also try to give a hint about why the billboard's update is done in the controlRender method : it's because you can have more than one viewport in your scene, and, so, more than one point of view. If you want to have a billboard always facing the one looking at it, you have to update it into the rendering step.

Thanks for pointing this out more clearly.

@bubuche said: Secondly, don't believe that you are smarter that the compiler. Really. There is tons of optimizations made by the compiler, and use a "stateless" approach for classes without attributes is likely something already optimized. You know, the compiler doesn't copy all the methods when you create a new object.

Of course not, however, saving on object instances is a rather good pattern. However, considering my “knowledge” about game engines, it seems that I have to learn quite a lot more.

@bubuche said: Plus, you can already do this if you want. Just create your appstate and put the map in there. Oh, you'll maybe create some memory leak cause of that, because, you know, as it is now, if you just remove a spatial its controls go out of reach and are gc-able (i think, i didn't test to be honest). With a map, you'll maybe create some "fake" references, and prevent the gc.

Now you have lost me. I will try to investigate this as soon as I have looked more deeply into AppState and its use in the engine itself.

@pspeed said: In my defense re: the "troll" comment. Each of your responses got longer and longer than the last and for whatever reason, in my mood, I read this bit as a condescending lecture on how "java memory" works.

The last bit about “proficient developer” just threw me over the edge. I was sure at that point you were just trying to get a rise out of me so I asked.

I think my responses up to that point escalated normally in frustration as it became clearer and clearer that you either weren’t understanding what I was saying or weren’t willing to put the research in to check it out. Plus the whole state thing which just kept going further and further down a path. Given the sum of the evidence, the whole stateless thing felt like an attempt to draw out an argument for no other reason than to waste time.

Generally, (not always but mostly) we are respectful to the folks that respect our time as well. I think if you look back at my first few posts you can see that I was trying to tell you what you needed to know but had trouble finding common ground on where the disconnect was.

I think maybe another lesson to take away is that when you walk into a room full of smart people and start telling them they did things wrong then you should have all of the evidence in hand.

As I have said in the original post, the proposal is open for discussion. Yet, and I bet it was based on our then mental and physical state, the replies that I perceived had been sub par and only after that you had received the PM from me, you began to formulate more elaborate replies.

However, as I have already pointed out, I was wrong and you were absolutely right.

@axnsoftware said: Of course not, however, saving on object instances is a rather good pattern. However, considering my "knowledge" about game engines, it seems that I have to learn quite a lot more.

It wasn’t clear how you were saving on object instances since you moved the state out to a Map.Entry or some other data structure. You only traded one nearly empty object for another nearly empty object.

Also note, on modern desktop Java (since 1.4 or so, whenever generational GC was added), short lived objects are nearly free to GC. The shorter the better even. It’s android where the GC tech is still catching up.

…but anyway, whether MyControl holds its state and you have many instances if MyControl or MyControl has put its data in some other object in a central data structure… the same number of objects exist. Actually, you’ll get at least one more per spatial in the stateless case.

An unspoken rule here:

If Momoko_Fan or PSpeed or Normen tell you you’re wrong, you can grumble, you can try to make a case, you can flail and sputter, but you’re more than likely wrong.

If two of these guys say you’re wrong, just shut up and do your homework (read and study the code).

It was fun while it lasted though, I’ll admit it.

@pspeed said: It wasn't clear how you were saving on object instances since you moved the state out to a Map.Entry or some other data structure. You only traded one nearly empty object for another nearly empty object.

Also note, on modern desktop Java (since 1.4 or so, whenever generational GC was added), short lived objects are nearly free to GC. The shorter the better even. It’s android where the GC tech is still catching up.

…but anyway, whether MyControl holds its state and you have many instances if MyControl or MyControl has put its data in some other object in a central data structure… the same number of objects exist. Actually, you’ll get at least one more per spatial in the stateless case.

With modern desktop and server JVMs this holds true. Don’t know how the next Android runtime will handle this, though.

But, if all of the state was combined in a single SpatialState sort of thingy, which then would be attached to the Spatial, then there would be just one state holder, combining all of the available “component/control” state into a single data object, with only one instance of MyControl per a multitude of existing Spatials. And this would even allow multiple controls to operate on the same data, provided that their interdependencies are correctly defined, e.g. AIControl before AnimationControl or “PhysicsControl” and so on.

As I see it, the controls resemble subsystems and they combine data driven behaviour, yet most of them hide their very data from other “components” in the system, preventing other components, or even scripted logic from operating on that same data. And there is no expressed interdependency between these components as to which component needs to be updated/rendered prior to another component, and so on.

But then again, I might be wrong in my overall assumption. And, please, forget about the billboards.

@madjack said: An unspoken rule here:

If Momoko_Fan or PSpeed or Normen tell you you’re wrong, you can grumble, you can try to make a case, you can flail and sputter, but you’re more than likely wrong.

If two of these guys say you’re wrong, just shut up and do your homework (read and study the code).

It was fun while it lasted though, I’ll admit it.

You made my day, madjack. Really.

Did I mention in my OP that I actually was reading and studying (skimming through) the code?

@axnsoftware said: You made my day, madjack. Really.

Did I mention in my OP that I actually was reading and studying (skimming through) the code?

You went there, didn’t you?

If you skim the code then don’t go around flailing your arms about, questioning and “fixing” everything. Read it and UNDERSTAND IT before.

I hope for you that’s a lesson learned.

I’m outta here.

@madjack said: You went there, didn't you?

If you skim the code then don’t go around flailing your arms about, questioning and “fixing” everything. Read it and UNDERSTAND IT before.

I hope for you that’s a lesson learned.

I’m outta here.

Now, if you had read the previous posts, you would already know, or would you not?

@axnsoftware said: But, if all of the state was combined in a single SpatialState sort of thingy, which then would be attached to the Spatial, then there would be just one state holder, combining all of the available "component/control" state into a single data object, with only one instance of MyControl per a multitude of existing Spatials. And this would even allow multiple controls to operate on the same data, provided that their interdependencies are correctly defined, e.g. AIControl before AnimationControl or "PhysicsControl" and so on.

I think when you show what this “combined data structure” looks like then I can show you where you aren’t saving anything and are in fact losing by having extra ‘objects’.

Though in the engine’s terms, the life of a control, spatial, etc. is pretty long relatively speaking.

Multiple controls can already operate on the same data since a control can refer to another control… or in some cases they can tuck data away in the UserData of the spatial (which incurs another object per entry, by the way, nothings free on the irrelevant ‘object count’ scale). AnimControl and SkeletonControl do this already, I think. At any rate, most controls are already independent.