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); } }
|