/* * Simbad - Robot Simulator * Copyright (C) 2004 Louis Hugues * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ----------------------------------------------------------------------------- * $Author: sioulseuguh $ * $Date: 2005/03/17 17:49:37 $ * $Revision: 1.7 $ * $Source: /cvsroot/simbad/src/simbad/sim/Eye.java,v $ */ package simbad.sim; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; import javax.media.j3d.Appearance; import javax.media.j3d.Canvas3D; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.ImageComponent; import javax.media.j3d.ImageComponent2D; import javax.media.j3d.Material; import javax.media.j3d.Node; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.swing.JPanel; import javax.vecmath.Color3f; import javax.media.j3d.RestrictedAccessException; import com.sun.j3d.utils.geometry.Sphere; /* * A visual sensor (and its 3d body) used to emulate monoscopic color camera. * Vision image (offscreen rendered) is accessible via copyVisionImage(). * * Implementation: * Vision is rendered offscreen via a j3d viewPlatform. * Calling update() method cause update of the associated buffered Image * The Subclass EyeJPanel is used to display image (in AgentInspector) * */ public class Eye extends SensorDevice { private ViewPlatform viewPlatform; private View view; private OffScreenCanvas3D offscreenCanvas3D; protected int tempRGBABuffer[]; // the rendered offscreen image BufferedImage visionImage; protected int imageWidth ; protected int imageHeight; /* * a JPanel for displaying the eye image in user interface windows. */ public class EyeJPanel extends JPanel{ private static final long serialVersionUID = 1L; BufferedImage bim; public EyeJPanel(){ Dimension d= new Dimension(imageWidth,imageHeight); setPreferredSize(d); setMinimumSize(d); // allocates a bim for capture bim = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); } /* should not be called too often */ protected void paintComponent( Graphics g){ super.paintComponent(g); copyVisionImage(bim); g.drawImage(bim, 0, 0, null); } } /** * An off screen Canvas3D for offscreen rendering of a 3D scene - call render to ask rendering */ private class OffScreenCanvas3D extends Canvas3D { private static final long serialVersionUID = 1L; boolean rendering; public OffScreenCanvas3D(GraphicsConfiguration gconfig) { super(gconfig, true); ImageComponent2D buffer = new ImageComponent2D( ImageComponent.FORMAT_RGB, visionImage); buffer.setCapability(ImageComponent2D.ALLOW_IMAGE_READ); setOffScreenBuffer(buffer); rendering = false; } synchronized void render() { try{ renderOffScreenBuffer(); }catch(RestrictedAccessException e) { // rendering is already in process,but we don't care // System.err.println("Exception caught"+e.getMessage() ); } // } //waitForOffScreenRendering(); } synchronized public void postSwap() { // copy rendered image BufferedImage bim = getOffScreenBuffer().getImage(); visionImage.setData(bim.getData()); rendering = false; } } Eye(float radius,int imageWidth,int imageHeight ) { this.imageWidth = imageWidth; this.imageHeight = imageHeight; // BufferedImage bim = new BufferedImage(imageWidth, imageHeight, // BufferedImage.TYPE_INT_RGB); visionImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); tempRGBABuffer= new int[imageWidth*imageHeight]; create3D(radius); createViewPlatform(); } void create3D(float radius) { super.create3D(true); // body if (radius > 0) { Color3f color = new Color3f(0.8f, 0.8f, 0.0f); Appearance appear = new Appearance(); appear .setMaterial(new Material(color, black, color, white, 100.0f)); Node node = new Sphere(radius, appear); node.setCollidable(false); node.setPickable(false); addChild(node); } } void createViewPlatform(){ // viewplatform viewPlatform = new ViewPlatform(); viewPlatform.setActivationRadius(100f); viewPlatform.setViewAttachPolicy(View.NOMINAL_HEAD); // view view = new View(); view.setProjectionPolicy(View.PERSPECTIVE_PROJECTION); view.setViewPolicy(View.SCREEN_VIEW); view.attachViewPlatform(viewPlatform); // physical body PhysicalBody phyBody = new PhysicalBody(); view.setPhysicalBody(phyBody); // physical environment PhysicalEnvironment phyEnv = new PhysicalEnvironment(); view.setPhysicalEnvironment(phyEnv); // ???? pas compris , pour l'antiliasing GraphicsConfigTemplate3D template = new GraphicsConfigTemplate3D(); template.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED); GraphicsConfiguration config = GraphicsEnvironment .getLocalGraphicsEnvironment().getDefaultScreenDevice() .getBestConfiguration(template); // antialiasing view.setSceneAntialiasingEnable(true); /* to add a onscreen canvas canvas3d = new Canvas3D(config); view.addCanvas3D(canvas3d); */ // attach offscreen canvas to the view offscreenCanvas3D = new OffScreenCanvas3D(config); offscreenCanvas3D.getScreen3D().setSize(imageWidth, imageWidth); offscreenCanvas3D.getScreen3D().setPhysicalScreenHeight(0.5); offscreenCanvas3D.getScreen3D().setPhysicalScreenWidth(0.5); view.addCanvas3D(offscreenCanvas3D); addChild(viewPlatform); // turn canvas in front of X axis rotateY(-Math.PI/2); } /** for allocating a working copy of the vision image */ final public BufferedImage createCompatibleImage() { return new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); } /** for allocating a SensorMatrix compabtible with device dimensions */ final public SensorMatrix createCompatibleSensorMatrix() { return new SensorMatrix(imageWidth, imageHeight); } /** * Request to fill a bufferedImage with last capture. * @param bim - buffered image to be filled. */ final public synchronized void copyVisionImage(BufferedImage bim){ bim.setData(visionImage.getData()); } /** * Request to fill a SensorMatrix with last capture. * @param matrix - to be filled */ final public synchronized void copyVisionImage(SensorMatrix matrix){ visionImage.getRGB(0,0,imageWidth,imageHeight,tempRGBABuffer,0,imageWidth); float array[] = matrix.getArray(); for (int i = 0; i < array.length; i++) { int pix = tempRGBABuffer[i]; int r = (pix >> 16) & 0xff; int g = (pix >> 8) & 0xff; int b = (pix) & 0xff; array[i] = (float) (r + g + b) / (3.0f * 255.0f); } } /** Called by simulator to render a new vision image */ protected void update(){ this.offscreenCanvas3D.render(); } public JPanel createInspectorPanel(){ return new EyeJPanel(); } /** * Returns the width of captured image. * @return width in pixels */ public int getImageWidth(){ return imageWidth; } /** * Returns the height of captured image. * @return height in pixels */ public int getImageHeight(){ return imageHeight; } }