Skip to main content

[Terrain Rendering] Attach/detach sons of a BranchGroup

17 replies [Last post]
adrianoaristarco
Offline
Joined: 2007-11-02

Hi, i'm writing a terrain system to handle very large terrain.

Mi terrain is divided into square (called "tile"), in order to load in memory only the tile near the range of the filed of view of the viewer and visualize only the piece of terrain inside the view frustum.

This tile are simple Shape3D but its geometry could change when the camera is moved away or near the tile (it's a LOD based on geomipmapping algorithm).

I've a quadtree to perform fast culling.

The root of the terrain is a BranchGroup.

This Bg holds as son all the tiles that currently visible so I need to continuosly attach/detach son of this BranchGroup.

What is the overhead in doing this?

I ask this because I don't want to load all the tiles in memory (for memory limits reasons) and since I perform frustum culling I don't know why I should leave the tile that are not currently visible attached to the branchgroup that representes the root of the terrain. I think that in this way I save some cpu cycles since the java3d rendering engine don't perform any operation on the object that aren't attached to the scenegraph.
But, if attaching/detaching child of the branchgroup has some overhead maybe I must find another solution.

Hope you can help me.
Many thanks
Adriano Aristarco

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
lamer77
Offline
Joined: 2006-12-22

> I run the construction and compilation of new
> subgraphs in a separate thread, with decreased
> priority. This makes good use of multicore machines
> and avoids the stuttering. You have to do the actual
> attach to the scene from the behavior thread,
> however. I haven't actually benchmarked the benefits
> of compilation, though; is it necessarily a
> noticeable improvement?

Display list are created by Java3D in the rendering thread. All interaction with the driver should be done from a single thread and is how I assume Java3D does it.

weiland
Offline
Joined: 2005-08-05

> Display list are created by Java3D in the rendering
> thread. All interaction with the driver should be
> done from a single thread and is how I assume Java3D
> does it.

Good thought; hasn't posed any problems for me so far (perhaps Java3D is MT safe in the places I've been pushing it), although it would be really nice to have a definitive idea what can and can't be done outside of the behavior thread (generally, that's where you need to operate on the live scenegraph).

Bill

weiland
Offline
Joined: 2005-08-05

A few points:

- If you're using a switch, I don't believe that child nodes should be subject to VFC if they've been switched off
- I use the quadtree approach, it works; I suspect that using a flat switch would actually have complicated my code and possibly reduced performance
- I create new Shape3D's rather than trying to "recycle" them; performance is acceptable; perhaps I could optimize by setting geometry instead, but as you point out, compilation won't work. Note, you might want to try doing all the work of loading coords, building geometries, appearances, shapes, etc. in a separate thread and then attaching it from the behavior thread when ready.
- I have tested both TriangleStripArray as you suggest and IndexedTriangleStripArray (BY_REF, UCIO, BY_REF_INDICES, INTERLEAVED) and have found performance diffs (in terms of the general framerate) to be minimal, but the latter lets you save memory (reuse the index buffers - if your tiles are all structured the same - and of course cuts the size of the vertex buffer). Caveat - I haven't run detailed speed or memory benchmarks on this!

Bill

aces
Offline
Joined: 2003-07-17

Ola, Adriano,

I guess I understand your case now.
You avoid using Switch because you need to detach *and* dispose your Shape3D.
I don't know your geometry data, but if they are more or less the same size, you can update Geometry, instead destroy and create new ones.

By the way, some time ago I wrote a BG sub-class to behave like a Switch. I was in need of easy show/hide Nodes, but also need attach / detach BranchGroup children nodes.
It was wrote (+ or -) this way:

* the class was a BranchGroup sub-class;
* internally it has a Switch, attached to this, and all children were attached to Switch instead BG.
* addChild() , removeChild(), etc, were all overrided to support the new graph;
* Switch methods were all delegated to switch instance, and construtor parameter were use to instantiate the Switch.

Scene -> ( BG -> Switch) -> children

A,

weiland
Offline
Joined: 2005-08-05

Hmm, seems like many people are doing/trying to do the same thing!

I have a system like this working; I'm using switch nodes to control visibility and LOD, _and_ detaching hidden pieces when they have gone unused for some threshold time to conserve memory. This works well; I haven't noticed any significant overhead from doing this, although I haven't benchmarked this hybrid approach against using purely the attach/detach approach.

Bill

adrianoaristarco
Offline
Joined: 2007-11-02

The problem is that I can't use a Shape3D for each LOD but I have one shape3D for each tile while the LOD affects only the shape3D geometries.

The probelm is that with the geomipmapping algorith I must have a "main geometry" that representes almost all the tile and 4 geometries that represents its boundary.

The main geometry level depends only by the distance of the tile from the viewer while the boundary geometries level depends by the level of the main geometry and the level of the neighbourg of the tile...

Please look at this image:
http://www.flickr.com/photos/26280288@N05/2988916994/

it shows tiles with different levels and the varius boundaries...

Is there a way to enable/disable the visibilty of a shape3d attached to the scenegraph without changing its appearance?
Thanks to all.
Cheers

adrianoaristarco
Offline
Joined: 2007-11-02

aces: I cannot use only the Switch nodes because I must handle very large terrain. So I can't have one Switch for each tile because potentially I could have hundreds of tiles...
Thank you.
Cheers.

aces
Offline
Joined: 2003-07-17

Hi Adriano

Perhaps you can use a single (or few) Switch group(s), with hundreds of children attached to it. You can choose what to show / hide by setting your Switch to use CHILD_MASK and a BitSet.

adrianoaristarco
Offline
Joined: 2007-11-02

Hi aces,
thanks for your answer.

Use a switch with a bit mask is the first thing I've tried but the problem is that I must handle a virtually infinite terrain.

Using a switch would make the algoritm O(n) where n is the number of the tile. This could be a memory issue.

I need to do something like: takes the heightmap of the whole earth from the nasa website, put them in an oracle/postgres database sets my position on the earth and the render the scene. This should not be a problem since the field of view is limited to few kilometers so only a small (very small) of the terrain data should be loaded and renderd (like every other terrain system)
Using a dinamically arranged quadtree makes things very fast.

When I move on the earth the tile that are far away from the view are completely discarded from memory (the shape3D and all its geometries are deferenced so the garbage collector can clean this area from memory) while the tile where the viewer is getting nearer (I'm sorry for my bad english) is loaded using a low priority thread.
The tiles that are already visibile will be adjusted to the correct level of detail.

I can't use a Switch because I can't attach/detach sons dinamically, it is possible only on BranchGroup (RestrictedAccessException - if this group node is part of live or compiled scene graph and the child node being added is not a BranchGroup node)

However, very thanks for your help.
Best regards
Adriano Aristarco

adrianoaristarco
Offline
Joined: 2007-11-02

If someone is interested here are some screenshot of what I've already done:

LOD:
http://www.flickr.com/photos/26280288@N05/2989302125/

With colors and material:
http://www.flickr.com/photos/26280288@N05/2989829906

They don't look good because this project is in a very experimental state and most feature (ex. texture) are missing...

nhouari
Offline
Joined: 2008-10-26

adrianoaristarco :
I use Tile of 1degreex1degree so (360 longitudes x 180 latitudes) for all the earth.
I use DTED (level 0) terrain elevation data.
For one tile, dted level-0 gives (121x121) points (elevations).
See :
http://www.flickr.com/photos/31952448@N05/2994915370/in/photostream/

I already create the tile geometry and add texture with Blue Marble images available on : http://earthobservatory.nasa.gov/Newsroom/BlueMarble/BlueMarble_monthlie...
At this time,
I don't have any LOD algorithm and can't load all the earth geometry.
I can't change texture image because the details images are too big.
So, I create 360x180 tiles with 4 vertex without details levels.

Screenshot :
- http://www.flickr.com/photos/31952448@N05/2994915492/

Idea: I want to create a LODShape class that extends a Shape3D with a center point and my own LODBehavior class that work with my LODShape.
The behavior work like a DistanceLOD but on the shape (not on a switch) and could load the shape geometry and change the texture inside another thread.
For the perfomance, all the geometries and textures will be pooled in texture cache and geometry cache. When the tile will not be visible, it will use its simple default geometry (no attach/detach)

What do you think about this ? Is it the best approch ?

adrianoaristarco
Offline
Joined: 2007-11-02

nhouari:
I think that is a good idea to change the geometry inside a shape3d instead of creating a new shape3d and attaching/detaching it from the scenegraph.
The only thing is that you must assure that, since you will load all the tile, you will create a shape3d for each tile. If the tile number is big then the number of shape3d attached to the scenegraph could potentially be high and this could be a performance problem because java3d must do a frustum culling for each shape3d.

I use a quadtree-based frustum culling in order to reduce this problem.

Another thing is that, since you change the geometry inside the shape, java3d cannot optimize (compile) this part of the scenegraph, I think that is better that you disable the auto-computing of the bounds (you should compute it manually when you create the shape the first time, the level of detail should don't change the bound of tile) and use the TriangleStripArray geometry, BY_REF and INTERLEAVED for maximum performance.

I'm absolutely not a Java3D guru, so what I've write could be wrong, it would be a nice thing if someone that reads this post could confirm (or not) my theory.

Regards
Adriano Aristarco

lamer77
Offline
Joined: 2006-12-22

Compiling a subgraph with static geometry will compile it into a display list. It will give you higher frame rate because the geometry can be uploaded to the card. But it can cause stutter as the time it takes to compile the display list is noticable.

My advise is to have a root BranchGroup with a pool of Shape3D attached. Maybe with a BranchGroup and Switch inbetween so the shape can be shown, hidden and detached. There is also a visibility flag in RenderingAttribtes that can be used to hide shapes. Although picking will still be enabled.

Frustum culling should be fast enough without resorting to a quadtree.

Avoid adding and removing nodes as much as possible. It is slow and Java3D can crash if you add and remove nodes from the same subgraph in the same frame.

weiland
Offline
Joined: 2005-08-05

A few comments in reply:

> Compiling a subgraph with static geometry will
> compile it into a display list. It will give you
> higher frame rate because the geometry can be
> uploaded to the card. But it can cause stutter as the
> time it takes to compile the display list is
> noticable.

I run the construction and compilation of new subgraphs in a separate thread, with decreased priority. This makes good use of multicore machines and avoids the stuttering. You have to do the actual attach to the scene from the behavior thread, however. I haven't actually benchmarked the benefits of compilation, though; is it necessarily a noticeable improvement?

...

> Avoid adding and removing nodes as much as possible.
> It is slow and Java3D can crash if you add and remove
> nodes from the same subgraph in the same frame.
Is this a known/documented bug? I've been doing this for quite some time and haven't encountered this issue.

Bill

adrianoaristarco
Offline
Joined: 2007-11-02

Thank to all for the replies!

>Compiling a subgraph with static geometry will
> compile it into a display list

Even if I unset the isfrequent capability bit? Since I use geomipmapping I have discrete lod so the geometry doesn't change continuosly (is not a CLOD like ROAM).

What you thinks about TriangleStripArray BY_REF and INTERLEAVED? Is true that is the fastest type of geometry?

>Is this a known/documented bug?

I do many attach/detach of shape3D on same branchgroup in the same frame and, until now, java3d never crashes. However, I think that it's right to say that attach a child is a slow operation for java3d, i notice this when in my tests I use a large terrain and, moving very quickly, some tiles are loaded with a little delay. If I disable the "attach/detach policy" it doesn't happens.

Cheers
Adriano Aristarco

mlouka
Offline
Joined: 2004-06-27

>
> >Is this a known/documented bug?
>
> I do many attach/detach of shape3D on same
> branchgroup in the same frame and, until now, java3d
> never crashes. However, I think that it's right to
> say that attach a child is a slow operation for
> java3d, i notice this when in my tests I use a large
> terrain and, moving very quickly, some tiles are
> loaded with a little delay. If I disable the
> "attach/detach policy" it doesn't happens.

There are a few multi-threading bugs that can be found if you search the bug archives.

See for example: https://java3d.dev.java.net/issues/show_bug.cgi?id=193

"It is not MT-safe to attach/detach a branch graph concurrently with changes to
any node or node component in that graph."

Michael.

aces
Offline
Joined: 2003-07-17

Olá Adriano,

You can use Switch to enable / disable BG children. It is much faster and simple to show /hide nodes than attach, detach .

Boa Sorte
A.