Re: Offscreen Rendering

Hi Luke,

> We have been having problems with obtaining BufferedImages from a
> DisplayImplJ3D. Namely if there are any components, dialogs, terminals, etc,
> over the VisAD display these are captured in the image.
>
> After reading through some source code and api's (for both VisAD and Java3D)
> it has become apparent that I should be able to do something along the lines
> of offscreen rendering. I have had a look through the main() in
> VisADCanvasJ3D and it does its offscreen rendering by creating a new display
> and adding some data references to it, this is possible but not ideal as our
> memory usage is already really high.

First, make sure there really is no way to raise your DisplayImpl's
Component (returned by getComponent()) so it is not obscured.

If that's not possible, the try this approach. When you want to
capture a BufferedImage from a DisplayImpl:

1. Remove its Component (returned by getComponent()) from your GUI,
2. Add its Component to a JFrame that you raise so it is
not obscured by any other Components,
3. Call getImage() to capture a BufferedImage,
4. Remove the DisplayImpl's Component from the JFrame and add it
back where it was in your GUI (and destroy the JFrame).

This will be *much* simpler then trying to share a scene graph
between two DisplayImpls.

> So after snooping around in the java3d examples I came across an example for
> offscreen rendering and adapted it for VisAD.
>
> So my question is this. Is there any way to create a DisplayImplJ3D that
> contains the same view as an existing display but uses a different api
> (offscreen)?
>
> I thought the code might look something like...
>
> DisplayRendererJ3D renderer
> (DisplayRendererJ3D)display.getDisplayRenderer();
> DisplayImplJ3D offscreen = new DisplayImplJ3D("offscreen", renderer, 640,
> 480);
> BufferedImage image = offscreen.getImage(true);
>
> where "display" is the display added to our jFrame.
>
> but I get a  "visad.DisplayException: DisplayRenderer.setDisplay: display
> already set" which is fair enough after looking at the source.

Sorry, but sharing a DisplayRenderer between two DisplayImpls
has no relation to sharing scene graphs between two DisplayImpls.

> Other options I have looked at are creating a RemoteSlaveDisplay, or copying
> the java3d offscreen rendering demo (outlined below...)?

RemoteSlaveDisplay uses the same code that capturing BufferedImages
uses, so will be obscured if the BufferedImage is.

> Another issue found was that when running the main() of VisADCanvasJ3D under
> linux we have only had the box and never got a field displayed. Whereas this
> has worked on windows. We get the same results for all linux and all windows
> configurations.

I will look into this.

> This is a nice juicy problem, which will hopefully get you all excited,
> either that, or it is nice and simple and I can go off back into the woods
> and hack code. I am keen to do some work on getting this to work nicely.

Sharing a scene graph between two DisplayImpls will be a huge
effort, and will probably be impossible to make consistent with
VisAD event logic. I strongly suggest trying the two ideas I
presented at the start:

1. Raise the DisplayImpl's Component so it is not obscured.
2. Temporarily remove the DisplayImpl's Component from your
GUI and add it to its own raised JFrame.

If you can't do either of these, I recommend taking the
temprary memory penalty of a second, offscreen DisplayImpl.

Good luck,
Bill