Improving compatibility with older Xith3D codebase

Good to know.

I left only those public, that can possibly and undagerously be called from outside. At the moment only cullAtoms(Universe, …) is called from outside, but maybe the other two will be in the future. But good to rethink it one more time.

Marvin

Hi,

[quote]But good to rethink it one more time.
[/quote]
Normally I follow the practice of leaving public only neccessary fields and methods - we are free to change it anyway, and it also pushes developers to think what do they call and what risks it has when they want to promote some private methods to public.

I already have Parallel Projection glSelect picking functional (fixed in FrustumCuller and Canvas3D mostly).

Yuri

I’m very for good encapsulation and think of it every time I write some piece of code. And I marked these two additional methods public, since it is totally unrisky to use them from outside and nobody wanting to use it is in charge to first check it. But I’m also happy with making them private. So go ahead :).

Cool. When will you commit it?

Marvin

The BIG advantage of hiding APIs is to prevent [people like me from bitching when things change!!! ;D

Hi,

I plan to commit changes as soon as I have my codebase completelly working with new version of Xith3D (not supposed to be too long).

In the meantime, the I discovered following misbehavior:

  1. Create new everything, except the scene
  2. Render once empty scene
  3. Create scene and attach it (there are A LOT of switches, some are ON, some are OFF)
  4. Render scene once
  5. Sleep for 10 seconds to see the results
  6. Render scene once
  7. Sleep for 10 seconds to see the results

Result seen at 5) shows that scene rendered incorrect with ALL switches turned ON.
Result seen at 7) shows that scene rendered correct (I think) with switches turned as they should be.

This caused by the fact that collectSwitchAtoms(…) in AtomsCollector does not favor the switch states, and cullSwitchAtoms(…) of FrustumCuller is not called at 4) (i.e. on the first frame just after locale modification) due to condition in renderOnce(…) of Renderer (marked with “// if the universe is dirty (e.g. before the first frame) --> collect atoms, cull and sort” comment).

Yuri

Hi,

Here are some thoughts in general.

I just checked in details the current implementation of Switch and associated interaction of modification manager with the switch. It really looks like here is a kind of design flaw: if I change state of the switch on the fly, modification manager does not get notified of such a change (OK, this part is supposed to be here but calls are commented out (or just not completely implemented)). Even more, if I pass BitSet (that is mutable) to setChildMask and after change its bits, there is no way to notify modification manager about such change, so scene will not get re-culled and will be rendered in previous state (this is a case for my app, indeed).

Former version of Xith3D was regenerating a list of atoms for every frame, which has been treated as performance bottleneck (and practically it is), so it even potentially (by-design) had no such problems as handling changes in mutable non-Xith3D objects passed to the rendering core (added to scenegraph) by-reference, so theoretically I could have single BitSet to control mutliple switches over the scene (example: I have multiple items on different levels that show up after I complete some task, availability of all items controlled by same BitSet, besides items themselves reside in different subgraphs).

Practically, introduction of Modification Manager will lead us to the same (by concept) architecture as Java3D, where atom list modifications are driven by events generated on scenegraph changes and delivered to the renderer via kind of delaying queue (i.e. the steps are “collect changes”, “apply changes to the atom list”, “render atom list”), which is beneficial only for relatively static scenes, while highly dynamic scenes (with hundreds or thousands nodes altered per frame) will only loose performance with this. So applications like Quake Benchmark and other walk-through games will sure benefit from the Modification Manager, while some others will degrade in performance.

Java3D is trying to improve this by introducing Rendering Hints (such as “dynamic”, “static”, “can read”, “can write”, etc.).

At the moment, ALL the rendering in new Xith3D core implementation became Modification Manager-centric. I have no problems with all these things, except that it should be a support for no-queue scenegraps also (which is a great benefit for beginner developers also, because of they do not have to worry about of all these mutable/immutable stuff, setting changed flag if the change something, etc.)

Option for apps like mine can be to add a global option that will force scenegraph recull on every frame rendered without even touching modification manager.

[thoghts interrupted by external event :slight_smile: ]

Yuri

Hmm… I didn’t come to the idea, that one is not rendering the scene constantly. I’ll change AtomsCollector to not cull at all and let the FrustumCuller work at the first frame, too. Then this problem should be solved.

Marvin

I don’t know, if you checked out the most recent version. The AtomsCollector now doesn’t do more than generating the RenderAtoms (and culls, but won’t do in a few hours). Culling is done each frame for sure. And it should absolutely honor any change in the scenegraph (even switches). So if you could post an example, where this problem occurrs, it would be very helpful.

The switch-change-events are not needed anymore in the modification manager, since I changed my first plan to update the global atoms list when a change in the scenegraph has been made. I recently removed the global atoms list and went back to the list built by FrustumCuller, since the other way hasn’t proven to be faster.

But when a Node is added or removed to / from the scenegraph the modification manager creates the atoms and handles lights and fogs. This can only be faster than collecting lights and fogs each frame. There’s no need for the end-developer to set any changed-flags, since this is done automatically. It it doesn’t work in any situation, we’ll have to fix it. There’re no queres to collect changes. Any change in the scenegraph is directly applied to the atoms list (and only to the affected part). So there’s no need for any Rendering Hints. Even dynamic sceneres won’t loose performance because of this architecture but will certainly gain performance.

Consider a scene, where a Node is added every 100th frame and one is removed every 100th frame. Then 99 frames are rendered with the pregenerated atoms and only before 1 single frame, the atoms are modified (not completely rebuilt). This is in any case faster, isn’t it? If a TransformGroup changes it’s value, then this change is directly passed through to the atoms without any additional time.

Maybe I’ve overseen something, but I guess this is the fastest possible way.

Marvin

Hi,

Let us go though few cases (some of them are implementation questions, so for me it is most important to understand which changes made with purpose and which are just implementation flaws/questions):

  1. Suppose we change color in Coloring Attributes. This indirectly causes a call of ScenegraphModificationsManager.onNodeComponentChanged(), which is empty and thus scenegraph does not consider to be modified. In renderer confition of modManager.hasAnythingChanged() [in latest version as of morning 25 oct CET] prevents scene to be reculled and, most important in this case, atoms to get resorted.

  2. Suppose you have many shapes having DIFFERENT instances of ColoringAttributes containing EXACTLY the same information. In this case, all the shaders based on these ColoringAttributes will be created by the “master shader” based on ONLY ONE (the first occured) instance of ColoringAttributes using stateId-based replacement mechanism (Optimization Level 1). Now imagine I am changing color in ONE instance of ColoringAttributes. It is supposed to alter the stateId of changed shader, so generating at least two different shading states for those not changed and one changed ColoringAttributes. Yes, I can see the ShapeAtom.updateShaders(…) method, but it never get called, so after ColoringAttributes change we have problem that the State Change Elimination subsystem (located now in RenderAtomPeer.executeShader(…), Optimization Level 2) treat the updated shader as one equal by its stateId with old ones, so gratefully bypasses its execution. Even more interesting, if we by incident change the “master shader” ColoringAttributes, ALL the shapes will change their colors. [there is also a question of checking the TransparencyAttributes in updateShaders(…), but this I believe implementation point.

Marvin, I would appreciate if you will attend these topics so I can clarify for myself what are the major architectural changes in the core except the core re-organization. The questions I am asking arise because of I already have code 100% correctly working on the older version of Xith3D, and because of it is very big and highly interactive code it acts as a very good test for the engine.

Yuri

Well, I had the plan to react on a NodeComponent change in the modification manager. But now it is done a different way (see below). I considered a NodeComponent change as not to be an event to force reculling / resorting. Maybe I was wrong. So please correct be in case.

ShapeAtom.updateShaders(…) actually is called from Appearance.verifyChange(). This method is called from ShapeAtomPeer.renderAtom(). You can easily trace this by visiting the “Call Hierarchy” in Eclipse. If this way to do it is wrong, we can surely change it. I don’t fully understand this shaderId thing. So If I made any mistake, feel free to change it or tell me what I could do better. I certainly want to understant it ;).

What do you mean by “attend”? Should I work on it, or should I explain anything?

Such a test is a great thing. And I must say again, that I’m very happy to see you investigating the core code.

Marvin

Hi,

[quote]What do you mean by “attend”?
[/quote]
I mean just to continue discussion and do not get as personal critics - you did a great job anyway.

I plan to intensively use Xith3D core (maybe, toolkit not too much), so I want to have it production quality on the other hand, but I also do not want to break anybody’s code by introduction of incompatible changes. You know, I prefer minimalistic changes.

So “attend” means “please check if I understood your ideas behind correct and explain if not”.

Yuri

Hi,

[quote]ShapeAtom.updateShaders(…) actually is called from Appearance.verifyChange(). This method is called from ShapeAtomPeer.renderAtom().
[/quote]
Yes, I see, and this explains why I get the result of “only one wrong frame just after the changes”, so 2nd and other subsequent frames are OK.

Updating shaders in renderAtom() is too late - it should be updated BEFORE sorting pass. So if you check the changes I made to CVS now I placed this call immediately when atoms are collected (added) during re-cull.

[quote]I don’t fully understand this shaderId thing.
[/quote]
This thing comes from very first versions of Xith3D, I think I have explained how it works a year or so on this forum. But with great pleasure I will explain you the idea and why updating shaders in renderAtom() is too late.

As you see, for each (in general words) appearance component type there is a shader. For each by-value-unique appearance component the core makes unique stateId which is assigned using a map (StateMap) - when creating a shader, map is looked up for the appearance component and if exactly equal shader has already been created, and if so, take its stateId (creating a new stateId otherwise).

Now, after stateIds are assigned, core on atom-by-atom basis executes the shaders and AFTER (!) calls renderAtom(), so if you update shaders there core will execute shaders at least once with old stateId’s assigned before the change.

The problem is that the core can decide to skip actual shader execution if it sees that the shader of given type with specific stateId was already executed just before, so if two shaders with different characteristics will have the same stateId, one may be skipped while have to be applied in order to get correct rendering result.

Yuri

P.S. we should remove now a call to app.verifyChange( shape ) from renderAtom(…) because of it is redundant…

Yuri

OK. We can either remove it from FrustumCuller or from renderAtom(). Removing it from renderAtom() is ok for me. (so ignore the appropriate post-part int the other thread ;)).

Marvin

Done.

Hi,

So we are more or less re-starting to work community-way. Great to see this.

Yuri

P.S. Unfortunately, I can not stay always on-line, so some responces are a bit delayed.

Indeed. I’m in holiday right now (for one week and a half) maybe I’ll have more time to dig the core.

Yuri, in case you ever disappear again for several weeks/months, could you please write a detailed doc on the core (once it’s stable again, of course) so I and others can get how it works in a way easier than reading 5 classes in parallel to find what comes from where and goes where by which mean and when ? ;D

Hi,

Looks like my chapter to XIN should come… Or so… For those who feel fit to read heavy technical stuff.

Yuri

This would take place in the UTH book (“Under The Hood”), not in the XIN.
XIN is meant to be simple and stupid, UTH is mean to be thorough and exhaustive.