Java tutorial
/* Essential Java 3D Fast Ian Palmer Publisher: Springer-Verlag ISBN: 1-85233-394-4 */ import java.awt.BorderLayout; import java.awt.Button; import java.awt.Frame; import java.awt.Panel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.media.j3d.AmbientLight; import javax.media.j3d.Appearance; import javax.media.j3d.BackgroundSound; import javax.media.j3d.BoundingLeaf; import javax.media.j3d.BoundingSphere; import javax.media.j3d.BranchGroup; import javax.media.j3d.Canvas3D; import javax.media.j3d.DirectionalLight; import javax.media.j3d.Locale; import javax.media.j3d.Material; import javax.media.j3d.MediaContainer; import javax.media.j3d.PhysicalBody; import javax.media.j3d.PhysicalEnvironment; import javax.media.j3d.PointSound; 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.Point2f; import javax.vecmath.Point3d; import javax.vecmath.Point3f; import javax.vecmath.Vector3f; import com.sun.j3d.audioengines.javasound.JavaSoundMixer; import com.sun.j3d.utils.behaviors.keyboard.KeyNavigatorBehavior; import com.sun.j3d.utils.geometry.Box; /** * This application demonstrates the use of 3D sound. It loads three sounds: * loop3.wav is an ambient background sound and loop1.wav and loop2.wav are * point sounds. The two point sounds can be switched on and off use AWT * buttons. The user can navigate around the scene using the keyboard. * * @author I.J.Palmer * @version 1.0 */ public class SimpleSounds extends Frame implements ActionListener { protected Canvas3D myCanvas3D = new Canvas3D(null); /** The exit button to quit the application */ protected Button exitButton = new Button("Exit"); /** The button to switch on and off the first sound */ protected Button sound1Button = new Button("Sound 1"); /** The button to switch on and off the second sound */ protected Button sound2Button = new Button("Sound 2"); protected BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 10000.0); //Create the two point sounds PointSound sound1 = new PointSound(); PointSound sound2 = new PointSound(); /** * Build the view branch of the scene graph. In this case a key navigation * utility object is created and associated with the view transform so that * the view can be changed via the keyboard. * * @return BranchGroup that is the root of the view branch */ protected BranchGroup buildViewBranch(Canvas3D c) { BranchGroup viewBranch = new BranchGroup(); Transform3D viewXfm = new Transform3D(); viewXfm.set(new Vector3f(0.0f, 0.0f, 30.0f)); TransformGroup viewXfmGroup = new TransformGroup(viewXfm); viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); viewXfmGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); ViewPlatform myViewPlatform = new ViewPlatform(); BoundingSphere movingBounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0); BoundingLeaf boundLeaf = new BoundingLeaf(movingBounds); PhysicalBody myBody = new PhysicalBody(); PhysicalEnvironment myEnvironment = new PhysicalEnvironment(); viewXfmGroup.addChild(myViewPlatform); viewBranch.addChild(viewXfmGroup); View myView = new View(); myView.addCanvas3D(c); myView.attachViewPlatform(myViewPlatform); myView.setPhysicalBody(myBody); myView.setPhysicalEnvironment(myEnvironment); KeyNavigatorBehavior keyNav = new KeyNavigatorBehavior(viewXfmGroup); keyNav.setSchedulingBounds(movingBounds); viewBranch.addChild(keyNav); //Create a sounds mixer to use our sounds with //and initialise it JavaSoundMixer myMixer = new JavaSoundMixer(myEnvironment); myMixer.initialize(); return viewBranch; } /** * Add some lights to the scene graph * * @param b * BranchGroup that the lights are added to */ protected void addLights(BranchGroup b) { Color3f ambLightColour = new Color3f(0.5f, 0.5f, 0.5f); AmbientLight ambLight = new AmbientLight(ambLightColour); ambLight.setInfluencingBounds(bounds); Color3f dirLightColour = new Color3f(1.0f, 1.0f, 1.0f); Vector3f dirLightDir = new Vector3f(-1.0f, -1.0f, -1.0f); DirectionalLight dirLight = new DirectionalLight(dirLightColour, dirLightDir); dirLight.setInfluencingBounds(bounds); b.addChild(ambLight); b.addChild(dirLight); } /** * This adds a continuous background sound to the branch group. * * @param b * BranchGroup to add the sound to. * @param soundFile * String that is the name of the sound file. */ protected void addBackgroundSound(BranchGroup b, String soundFile) { //Create a media container to load the file MediaContainer droneContainer = new MediaContainer(soundFile); //Create the background sound from the media container BackgroundSound drone = new BackgroundSound(droneContainer, 1.0f); //Activate the sound drone.setSchedulingBounds(bounds); drone.setEnable(true); //Set the sound to loop forever drone.setLoop(BackgroundSound.INFINITE_LOOPS); //Add it to the group b.addChild(drone); } /** * Add a sound to the transform group. This takes a point sound object and * loads into it a sounds from a given file. The edge of the sound's extent * is also defined in a parameter. * * @param tg * TransformGroup that the sound is to be added to * @param sound * PointSound to be used * @param soundFile * String that is the name of the sound file to be loaded * @param edge * float that represents the sound's maximum extent */ protected void addObjectSound(TransformGroup tg, PointSound sound, String soundFile, float edge) { //First we get the current transform so that we can //position the sound in the same place Transform3D objXfm = new Transform3D(); Vector3f objPosition = new Vector3f(); tg.getTransform(objXfm); objXfm.get(objPosition); //Create the media container to load the sound MediaContainer soundContainer = new MediaContainer(soundFile); //Use the loaded data in the sound sound.setSoundData(soundContainer); sound.setInitialGain(1.0f); //Set the position to that of the given transform sound.setPosition(new Point3f(objPosition)); //Allow use to switch the sound on and off sound.setCapability(PointSound.ALLOW_ENABLE_READ); sound.setCapability(PointSound.ALLOW_ENABLE_WRITE); sound.setSchedulingBounds(bounds); //Set it off to start with sound.setEnable(false); //Set it to loop forever sound.setLoop(BackgroundSound.INFINITE_LOOPS); //Use the edge value to set to extent of the sound Point2f[] attenuation = { new Point2f(0.0f, 1.0f), new Point2f(edge, 0.1f) }; sound.setDistanceGain(attenuation); //Add the sound to the transform group tg.addChild(sound); } protected BranchGroup buildContentBranch() { //Create the appearance Appearance app = new Appearance(); Color3f ambientColour = new Color3f(1.0f, 0.0f, 0.0f); Color3f emissiveColour = new Color3f(0.0f, 0.0f, 0.0f); Color3f specularColour = new Color3f(1.0f, 1.0f, 1.0f); Color3f diffuseColour = new Color3f(1.0f, 0.0f, 0.0f); float shininess = 20.0f; app.setMaterial(new Material(ambientColour, emissiveColour, diffuseColour, specularColour, shininess)); //Make the cube Box myCube = new Box(1.0f, 1.0f, 1.0f, app); TransformGroup cubeGroup = new TransformGroup(); BranchGroup contentBranch = new BranchGroup(); addLights(contentBranch); addObjectSound(cubeGroup, sound1, new String("file:./loop1.wav"), 10.0f); addObjectSound(cubeGroup, sound2, new String("file:./loop2.wav"), 20.0f); addBackgroundSound(contentBranch, new String("file:./loop3.wav")); cubeGroup.addChild(myCube); contentBranch.addChild(cubeGroup); return contentBranch; } public void actionPerformed(ActionEvent e) { if (e.getSource() == exitButton) { dispose(); System.exit(0); } else if (e.getSource() == sound1Button) { if (sound1.getEnable()) sound1.setEnable(false); else sound1.setEnable(true); } else if (e.getSource() == sound2Button) { sound2.setEnable(!sound2.getEnable()); } } public SimpleSounds() { VirtualUniverse myUniverse = new VirtualUniverse(); Locale myLocale = new Locale(myUniverse); // buildUniverse(myCanvas3D); myLocale.addBranchGraph(buildContentBranch()); myLocale.addBranchGraph(buildViewBranch(myCanvas3D)); setTitle("SimpleSounds"); setSize(400, 400); setLayout(new BorderLayout()); Panel bottom = new Panel(); bottom.add(sound1Button); bottom.add(sound2Button); bottom.add(exitButton); add(BorderLayout.CENTER, myCanvas3D); add(BorderLayout.SOUTH, bottom); exitButton.addActionListener(this); sound1Button.addActionListener(this); sound2Button.addActionListener(this); setVisible(true); } public static void main(String[] args) { SimpleSounds sw = new SimpleSounds(); } }