package org.jcae.viewer3d.test; import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics; import java.awt.GraphicsConfigTemplate; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.net.URL; import javax.media.j3d.Alpha; import javax.media.j3d.AudioDevice; import javax.media.j3d.Background; import javax.media.j3d.BoundingSphere; import javax.media.j3d.Bounds; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DepthComponent; import javax.media.j3d.DepthComponentInt; import javax.media.j3d.GraphicsConfigTemplate3D; import javax.media.j3d.Group; import javax.media.j3d.ImageComponent; import javax.media.j3d.ImageComponent2D; import javax.media.j3d.Locale; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.Raster; import javax.media.j3d.RotationInterpolator; import javax.media.j3d.Shape3D; import javax.media.j3d.Transform3D; import javax.media.j3d.TransformGroup; import javax.media.j3d.View; import javax.media.j3d.ViewPlatform; import javax.media.j3d.VirtualUniverse; import javax.vecmath.Color3f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3d; //import RasterTest.RasterCanvas3D; import com.sun.j3d.audioengines.javasound.JavaSoundMixer; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; /******************************************************************************* * Copyright (C) 2001 Daniel Selman * * First distributed with the book "Java 3D Programming" by Daniel Selman and * published by Manning Publications. http://manning.com/selman * * 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, version 2. * * 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. * * The license can be found on the WWW at: http://www.fsf.org/copyleft/gpl.html * * Or by writing to: Free Software Foundation, Inc., 59 Temple Place - Suite * 330, Boston, MA 02111-1307, USA. * * Authors can be contacted at: Daniel Selman: daniel@selman.orgThis e-mail address is being protected from spam bots, you need JavaScript enabled to view it * * If you make changes you think others would like, please contact one of the * authors or someone at the www.j3d.org web site. ******************************************************************************/ //***************************************************************************** /** * Java3dApplet * * Base class for defining a Java 3D applet. Contains some useful methods for * defining views and scenegraphs etc. * * @author Daniel Selman * @version 1.0 */ //***************************************************************************** /** * This example illustrates how to: <br> * 1. Draw an image into the 3D view as a Raster object. <br> * 2. Read the depth components of the 3D scene <br> * 3. Dynamically update a Raster object inside the postSwap method <br> * 4. Render a view of the depth components as a dynamic raster <br> */ public class RasterTest extends Java3dApplet implements ActionListener { // size of the window, and hence size of the depth component array private static int m_kWidth = 400; private static int m_kHeight = 400; // the Raster used to store depth components private Raster m_DepthRaster = null; // the Raster used to render an image into the 3D view private Raster m_RenderRaster = null; // an array of integer values for the depth components private int[] m_DepthData = null; public RasterTest() { // create the image to be rendered using a Raster BufferedImage bufferedImage = new BufferedImage(128, 128, BufferedImage.TYPE_INT_RGB); ImageComponent2D imageComponent2D = new ImageComponent2D( ImageComponent2D.FORMAT_RGB, bufferedImage); imageComponent2D.setCapability(ImageComponent.ALLOW_IMAGE_READ); imageComponent2D.setCapability(ImageComponent.ALLOW_SIZE_READ); // create the depth component to store the 3D depth values DepthComponentInt depthComponent = new DepthComponentInt(m_kWidth, m_kHeight); depthComponent.setCapability(DepthComponent.ALLOW_DATA_READ); // create the Raster for the image m_RenderRaster = new Raster(new Point3f(0.0f, 0.0f, 0.0f), Raster.RASTER_COLOR, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), imageComponent2D, null); m_RenderRaster.setCapability(Raster.ALLOW_IMAGE_WRITE); m_RenderRaster.setCapability(Raster.ALLOW_SIZE_READ); // create the Raster for the depth components m_DepthRaster = new Raster(new Point3f(0.0f, 0.0f, 0.0f), Raster.RASTER_COLOR_DEPTH, 0, 0, m_kWidth, m_kHeight, new ImageComponent2D(ImageComponent.FORMAT_RGB,m_kWidth, m_kHeight), depthComponent); initJava3d(); } public void actionPerformed(ActionEvent event) { } protected Canvas3D createCanvas3D() { // create a custom Canvas3D with postSwap overidden GraphicsConfigTemplate3D gc3D = new GraphicsConfigTemplate3D(); gc3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED); GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment() .getScreenDevices(); RasterCanvas3D c3d = new RasterCanvas3D(this, gd[0] .getBestConfiguration(gc3D)); c3d.setSize(getCanvas3dWidth(c3d), getCanvas3dHeight(c3d)); return c3d; } protected BranchGroup createSceneBranchGroup() { // create some simple geometry (a rotating ColorCube) // and a Shape3D object for the Raster containing the Image BranchGroup objRoot = super.createSceneBranchGroup(); TransformGroup objTrans = new TransformGroup(); objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); Transform3D yAxis = new Transform3D(); yAxis.rotX(0.6); Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, 4000, 0, 0, 0, 0, 0); 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); objTrans.addChild(rotator); // wrap the Raster in a Shape3D Shape3D shape = new Shape3D(m_RenderRaster); objRoot.addChild(shape); objTrans.addChild(new ColorCube(1.0)); objRoot.addChild(objTrans); return objRoot; } protected int getCanvas3dWidth(Canvas3D c3d) { return m_kWidth; } protected int getCanvas3dHeight(Canvas3D c3d) { return m_kHeight; } public Raster getDepthRaster() { return m_DepthRaster; } public void updateRenderRaster() { // takes the Depth Raster and updates the Render Raster // containing the image based on the depth values stored in // the Depth Raster. // create a temporary BufferedImage for the depth components BufferedImage tempBufferedImage = new BufferedImage(m_DepthRaster .getDepthComponent().getWidth(), m_DepthRaster .getDepthComponent().getHeight(), BufferedImage.TYPE_INT_RGB); // allocate an array of ints to store the depth components from the // Depth Raster if (m_DepthData == null) m_DepthData = new int[m_DepthRaster.getDepthComponent().getWidth() * m_DepthRaster.getDepthComponent().getHeight()]; // copy the depth values from the Raster into the int array ((DepthComponentInt) m_DepthRaster.getDepthComponent()) .getDepthData(m_DepthData); // assign the depth values to the temporary image, the integer depths // will be // interpreted as integer rgb values. tempBufferedImage.setRGB(0, 0, m_DepthRaster.getDepthComponent() .getWidth(), m_DepthRaster.getDepthComponent().getHeight(), m_DepthData, 0, m_DepthRaster.getDepthComponent().getWidth()); // get a graphics device for the image Graphics g = tempBufferedImage.getGraphics(); Dimension size = new Dimension(); m_RenderRaster.getSize(size); // because the Depth Raster is a different size to the Render Raster, // i.e. the Depth Raster is canvas width by canvas height and the Render // Raster // is of aritrary size, we rescale the image here. g.drawImage(tempBufferedImage, 0, 0, (int) size.getWidth(), (int) size .getHeight(), null); // finally, assign the scaled image to the RenderRaster m_RenderRaster.setImage(new ImageComponent2D( BufferedImage.TYPE_INT_RGB, tempBufferedImage)); } public static void main(String[] args) { RasterTest rasterTest = new RasterTest(); rasterTest.saveCommandLineArguments(args); new MainFrame(rasterTest, m_kWidth, m_kHeight); } // Canvas3D overide to read the depth components of the 3D view // into a Raster object and notify the Applet public class RasterCanvas3D extends Canvas3D { RasterTest m_RasterTest = null; public RasterCanvas3D(RasterTest rasterTest, GraphicsConfiguration graphicsConfiguration) { super(graphicsConfiguration); m_RasterTest = rasterTest; } public void postSwap() { super.postSwap(); getGraphicsContext3D().readRaster(m_RasterTest.getDepthRaster()); // notify the applet to update the render object // used to display the depth values m_RasterTest.updateRenderRaster(); } } } abstract class Java3dApplet extends Applet { public static int m_kWidth = 300; public static int m_kHeight = 300; protected String[] m_szCommandLineArray = null; protected VirtualUniverse m_Universe = null; protected BranchGroup m_SceneBranchGroup = null; protected Bounds m_ApplicationBounds = null; // protected com.tornadolabs.j3dtree.Java3dTree m_Java3dTree = null; public Java3dApplet() { } public boolean isApplet() { try { System.getProperty("user.dir"); System.out.println("Running as Application."); return false; } catch (Exception e) { } System.out.println("Running as Applet."); return true; } public URL getWorkingDirectory() throws java.net.MalformedURLException { URL url = null; try { File file = new File(System.getProperty("user.dir")); System.out.println("Running as Application:"); System.out.println(" " + file.toURL()); return file.toURL(); } catch (Exception e) { } System.out.println("Running as Applet:"); System.out.println(" " + getCodeBase()); return getCodeBase(); } public VirtualUniverse getVirtualUniverse() { return m_Universe; } //public com.tornadolabs.j3dtree.Java3dTree getJ3dTree() { //return m_Java3dTree; // } public Locale getFirstLocale() { java.util.Enumeration e = m_Universe.getAllLocales(); if (e.hasMoreElements() != false) return (Locale) e.nextElement(); return null; } protected Bounds getApplicationBounds() { if (m_ApplicationBounds == null) m_ApplicationBounds = createApplicationBounds(); return m_ApplicationBounds; } protected Bounds createApplicationBounds() { m_ApplicationBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); return m_ApplicationBounds; } protected Background createBackground() { Background back = new Background(new Color3f(0.9f, 0.9f, 0.9f)); back.setApplicationBounds(createApplicationBounds()); return back; } public void initJava3d() { // m_Java3dTree = new com.tornadolabs.j3dtree.Java3dTree(); m_Universe = createVirtualUniverse(); Locale locale = createLocale(m_Universe); BranchGroup sceneBranchGroup = createSceneBranchGroup(); ViewPlatform vp = createViewPlatform(); BranchGroup viewBranchGroup = createViewBranchGroup( getViewTransformGroupArray(), vp); createView(vp); Background background = createBackground(); if (background != null) sceneBranchGroup.addChild(background); // m_Java3dTree.recursiveApplyCapability(sceneBranchGroup); // m_Java3dTree.recursiveApplyCapability(viewBranchGroup); locale.addBranchGraph(sceneBranchGroup); addViewBranchGroup(locale, viewBranchGroup); onDoneInit(); } protected void onDoneInit() { // m_Java3dTree.updateNodes(m_Universe); } protected double getScale() { return 1.0; } public TransformGroup[] getViewTransformGroupArray() { TransformGroup[] tgArray = new TransformGroup[1]; tgArray[0] = new TransformGroup(); // move the camera BACK a little... // note that we have to invert the matrix as // we are moving the viewer Transform3D t3d = new Transform3D(); t3d.setScale(getScale()); t3d.setTranslation(new Vector3d(0.0, 0.0, -20.0)); t3d.invert(); tgArray[0].setTransform(t3d); return tgArray; } protected void addViewBranchGroup(Locale locale, BranchGroup bg) { locale.addBranchGraph(bg); } protected Locale createLocale(VirtualUniverse u) { return new Locale(u); } protected BranchGroup createSceneBranchGroup() { m_SceneBranchGroup = new BranchGroup(); return m_SceneBranchGroup; } protected View createView(ViewPlatform vp) { View view = new View(); PhysicalBody pb = createPhysicalBody(); PhysicalEnvironment pe = createPhysicalEnvironment(); AudioDevice audioDevice = createAudioDevice(pe); if (audioDevice != null) { pe.setAudioDevice(audioDevice); audioDevice.initialize(); } view.setPhysicalEnvironment(pe); view.setPhysicalBody(pb); if (vp != null) view.attachViewPlatform(vp); view.setBackClipDistance(getBackClipDistance()); view.setFrontClipDistance(getFrontClipDistance()); Canvas3D c3d = createCanvas3D(); view.addCanvas3D(c3d); addCanvas3D(c3d); return view; } protected PhysicalBody createPhysicalBody() { return new PhysicalBody(); } protected AudioDevice createAudioDevice(PhysicalEnvironment pe) { JavaSoundMixer javaSoundMixer = new JavaSoundMixer(pe); if (javaSoundMixer == null) System.out.println("create of audiodevice failed"); return javaSoundMixer; } protected PhysicalEnvironment createPhysicalEnvironment() { return new PhysicalEnvironment(); } protected float getViewPlatformActivationRadius() { return 100; } protected ViewPlatform createViewPlatform() { ViewPlatform vp = new ViewPlatform(); vp.setViewAttachPolicy(View.RELATIVE_TO_FIELD_OF_VIEW); vp.setActivationRadius(getViewPlatformActivationRadius()); return vp; } protected Canvas3D createCanvas3D() { GraphicsConfigTemplate3D gc3D = new GraphicsConfigTemplate3D(); gc3D.setSceneAntialiasing(GraphicsConfigTemplate.PREFERRED); GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment() .getScreenDevices(); Canvas3D c3d = new Canvas3D(gd[0].getBestConfiguration(gc3D)); c3d.setSize(getCanvas3dWidth(c3d), getCanvas3dHeight(c3d)); return c3d; } protected int getCanvas3dWidth(Canvas3D c3d) { return m_kWidth; } protected int getCanvas3dHeight(Canvas3D c3d) { return m_kHeight; } protected double getBackClipDistance() { return 100.0; } protected double getFrontClipDistance() { return 1.0; } protected BranchGroup createViewBranchGroup(TransformGroup[] tgArray, ViewPlatform vp) { BranchGroup vpBranchGroup = new BranchGroup(); if (tgArray != null && tgArray.length > 0) { Group parentGroup = vpBranchGroup; TransformGroup curTg = null; for (int n = 0; n < tgArray.length; n++) { curTg = tgArray[n]; parentGroup.addChild(curTg); parentGroup = curTg; } tgArray[tgArray.length - 1].addChild(vp); } else vpBranchGroup.addChild(vp); return vpBranchGroup; } protected void addCanvas3D(Canvas3D c3d) { setLayout(new BorderLayout()); add(c3d, BorderLayout.CENTER); doLayout(); } protected VirtualUniverse createVirtualUniverse() { return new VirtualUniverse(); } protected void saveCommandLineArguments(String[] szArgs) { m_szCommandLineArray = szArgs; } protected String[] getCommandLineArguments() { return m_szCommandLineArray; } }