The Source for Java Technology Collaboration

Home » java.net Forums » Java Desktop Technologies » Java 3D

Thread: How to force behavior updates in off-screen mode?

Welcome, Guest Help
Login Login
Guest Settings Guest Settings
This question is answered. Helpful answers available: 2. Correct answers available: 1.

Reply to this Thread Reply to this Thread Search Forum Search Forum Back to Thread List Back to Thread List

Permlink Replies: 1 - Last Post: Jun 30, 2009 5:29 PM by: yena Threads: [ Previous | Next ]
yena

Posts: 13
How to force behavior updates in off-screen mode?
Posted: Jun 26, 2009 10:05 PM
 
  Click to reply to this thread Reply

Dear all,

I'm trying to integrate J3D with JLoox, and I need to do off-screen rendering into an image which I can then copy into the drawing. This already works, but I have noticed that the behaviors are not updated.

I searched the net, and found that AutoOffscreenCanvas3D should enable behavior calculation, but then the renderOffScreenBuffer fails. I've tried to create subclass of Canvas3D that implements AutoOffScreenCanvas3D. Although the renderer seems to be running (using isRendererRunning()), I don't detect any postSwap events, and the getOffscreenBuffer method returns a black image. What am I doing wrong?

Here is my test code. Change from "canvas = new Canvas3D" to "canvas = new InternalCanvas" to test the two cases (ok, but no behavior vs. only black output):
---

import java.awt.event.*;
import java.awt.image.*;
import java.awt.*;
import javax.swing.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.exp.swing.impl.AutoOffScreenCanvas3D;

public class Hello3d extends JPanel
{
private static final int WIDTH = 1280;
private static final int HEIGHT = 1024;
double METERS_PER_PIXEL = 0.0254 / 90.0;

private Canvas3D canvas;
private SimpleUniverse universe;

class InternalCanvas3D extends Canvas3D implements AutoOffScreenCanvas3D
{
public InternalCanvas3D(GraphicsConfiguration config, boolean offscreen) {
super(config, offscreen);
System.out.println("InternalCanvas3D");
}
public void postSwap() {
// This method is never called!!!
System.out.println("postSwap");
}
}

public Hello3d() { }

public void start()
{
GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
canvas = new Canvas3D(config, true);
//canvas = new InternalCanvas3D(config, true);

BufferedImage offScreenImg = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
ImageComponent2D buffer = new ImageComponent2D(ImageComponent.FORMAT_RGB, offScreenImg);
buffer.setCapability(ImageComponent2D.ALLOW_IMAGE_READ);
buffer.setCapability(ImageComponent2D.ALLOW_IMAGE_WRITE);
canvas.setOffScreenBuffer(buffer);
canvas.getScreen3D().setSize(WIDTH, HEIGHT);
canvas.getScreen3D().setPhysicalScreenWidth(((double) WIDTH) * METERS_PER_PIXEL);
canvas.getScreen3D().setPhysicalScreenHeight(((double) HEIGHT) * METERS_PER_PIXEL);

// Add a simple scene
SimpleUniverse u = new SimpleUniverse(canvas);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(createSceneGraph());

canvas.startRenderer();
}

synchronized public BufferedImage takeScreenshot(Canvas3D c){
// just for test, doesn't work well
Screen3D on=c.getScreen3D();
Canvas3D shot=new Canvas3D(c.getGraphicsConfiguration(), true);
c.getView().stopView();
c.getView().addCanvas3D(shot);
c.getView().startView();
Screen3D off=shot.getScreen3D();
off.setSize(on.getSize());
off.setPhysicalScreenHeight(on.getPhysicalScreenHeight());
off.setPhysicalScreenWidth(on.getPhysicalScreenWidth());
shot.setOffScreenLocation(c.getLocationOnScreen());

BufferedImage bi=new BufferedImage(c.getWidth(),c.getHeight(),BufferedImage.TYPE_INT_ARGB);
ImageComponent2D buffer = new ImageComponent2D(ImageComponent.FORMAT_RGBA, bi);
shot.setOffScreenBuffer(buffer);
shot.renderOffScreenBuffer();
shot.waitForOffScreenRendering();
BufferedImage res= shot.getOffScreenBuffer().getImage();
c.getView().removeCanvas3D(shot);
return res;
}

public BranchGroup createSceneGraph() {
// a spinning color cube (if behavior works)
BranchGroup objRoot = new BranchGroup();
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
objTrans.addChild(new ColorCube(0.4));
Transform3D yAxis = new Transform3D();
Alpha rotationAlpha = new Alpha(-1, 4000);
RotationInterpolator rotator = new RotationInterpolator(rotationAlpha, objTrans, yAxis, 0.0f, (float) Math.PI*2.0f);
BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
rotator.setSchedulingBounds(bounds);
objRoot.addChild(rotator);
objRoot.compile();
return objRoot;
}

public Image getImage()
{
//System.out.println("Rendering? "+canvas.isRendererRunning());
if(canvas instanceof InternalCanvas3D) {
// screenshot works, but no behavior updates and will crash X eventually
//return takeScreenshot(canvas);
// this doesn't work, only a black image appears
canvas.waitForOffScreenRendering();
return canvas.getOffScreenBuffer().getImage();
} else {
// works, but no behavior
canvas.renderOffScreenBuffer();
canvas.waitForOffScreenRendering();
return canvas.getOffScreenBuffer().getImage();
}
}

static Hello3d hello3d;
public static void main(String args[])
{
hello3d=new Hello3d();
hello3d.start();
JFrame frame = new JFrame() {
public void paint(java.awt.Graphics g) {
g.drawImage(hello3d.getImage(), 0, 0, null);
repaint(); // force another update
}
};
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}


yena

Posts: 13
Re: How to force behavior updates in off-screen mode?
Posted: Jun 30, 2009 5:29 PM   in response to: yena
 
  Click to reply to this thread Reply

I got it to work. The offscreen Canvas3D has to be added to an active awt container of some sort, doesn't really matter which since it won't be drawn on-screen anyway. You also have to add a "public java.awt.Container getParent()" method that returns the container the Canvas3D is added to. Finally the renderOffScreenBuffer() call should be removed, leaving only waitForOffscreenRendering() and getOffScreenBuffer().getImage()




 XML java.net RSS