/* * Java classes for doing simulations of physical processes * on the Java3D scene graph. * * (C) 2000, 2001 Fred Klingener * klingener@BrockEng.com * www.VMech.com * * 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, * or you may read or obtain a copy at http://www.gnu.org/copyleft/gpl.html */ /* PlanE_Dali.java 0.0 09/15/01 * This is a program that will be used to illustrate opportunities and * problems doing physics with the Java 3D API. * * It is built using Sun Microsystem's tutorial example * HelloJava3Dc.java, the Copyright notice of which is * reproduced below. * * */ /* * @(#)HelloJava3Dc.java 1.1 00/09/22 13:55 * * Copyright (c) 1996-2000 Sun Microsystems, Inc. All Rights Reserved. * * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use, * modify and redistribute this software in source and binary code form, * provided that i) this copyright notice and license appear on all copies of * the software; and ii) Licensee does not utilize the software in a manner * which is disparaging to Sun. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * * This software is not designed or intended for use in on-line control of * aircraft, air traffic, aircraft navigation or aircraft communications; or in * the design, construction, operation or maintenance of any nuclear * facility. Licensee represents and warrants that it will not use or * redistribute the Software for such purposes. */ import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.event.*; import java.awt.GraphicsConfiguration; import com.sun.j3d.utils.applet.MainFrame; import com.sun.j3d.utils.geometry.ColorCube; import com.sun.j3d.utils.universe.*; import java.text.*; // 09-24-01 for diagnostics import java.util.*; // 09-24-01 for Behavior, diagnostics import javax.media.j3d.*; import javax.vecmath.*; /* Basic approach: * O build a scene-graph-based simulation model for * run/render in retained or retained/compiled mode. * O model Behaviors are scheduled to wakeupOnElapsedFrame(0) * O run the simulation clock in immediate mode. This * means extending Canvas3D and putting the clock maintenance * methods in the preRender() method, say. * o clock members are clock time and time step size * o at each step, * - increment clock by time step size * - Thread.sleep(time step size) * o public sets and gets * O build Interpolators that read the simulation clock time, get output from an Alpha * * * */ public class PlanE_Dali extends Applet { String ProgramName = "PlanE_Dali.java 09-28-2001"; /* * simpleU (Simple Universe) * | * objRoot (BG) * | * objSpin (TG) * rotator (RotationInterpolator) * | * ColorCube */ Dali3D canvas3D; public BranchGroup createScene() // same as HelloJava3D except for Interpolator {// Create the root of the branch graph BranchGroup objRoot = new BranchGroup(); // Create the transform group node and initialize it to the // identity. Add it to the root of the subgraph. TransformGroup objSpin = new TransformGroup(); objSpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); objRoot.addChild(objSpin); DaliInterpolator rotator = new DaliRotationInterpolator(canvas3D, new Alpha(-1, 4003), objSpin); BoundingSphere RotBounds = new BoundingSphere(); rotator.setSchedulingBounds(RotBounds); objRoot.addChild(rotator); // Create a simple shape leaf node, add it to the scene graph. // ColorCube is a Convenience Utility class objSpin.addChild(new ColorCube(0.4)); return objRoot; } // Constructor public PlanE_Dali() // same as HelloJava3D except for extended Canvas { setLayout(new BorderLayout()); GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration(); canvas3D = new Dali3D(config); canvas3D.setSize(256, 256); add("Center", canvas3D); // SimpleUniverse is a Convenience Utility class SimpleUniverse simpleU = new SimpleUniverse(canvas3D); // This will move the ViewPlatform back a bit so the // objects in the scene can be viewed. simpleU.getViewingPlatform().setNominalViewingTransform(); BranchGroup scene = createScene(); simpleU.addBranchGraph(scene); } // The following allows this to be run as an application // as well as an applet public static void main(String[] args) { Frame frame = new MainFrame(new PlanE_Dali(), 256, 256); } // end of main /**<PRE> * Dali3D. Getit? Clock on a Canvas3D. * Purpose is to offer a more controllable * time base for doing simulations. * * Overrides preRender()withSimClock+=DeltaT * and sleep(DeltaT) * * * * </PRE> * * @author klingener@BrockEng.com */ public class Dali3D extends Canvas3D {// Clock long SimClock; int DeltaT; boolean isRunning; // Frame counter private static final boolean debug = true; private static final boolean html = false; long FrameCount; int FrameBlock; long Then; private NumberFormat Double1; // Constructor public Dali3D(GraphicsConfiguration gc) { super(gc); SimClock = 0; DeltaT = 10; isRunning = false; if (debug) { Double1 = NumberFormat.getInstance(); Double1.setMaximumFractionDigits(1); Double1.setMinimumFractionDigits(1); Then = System.currentTimeMillis(); FrameCount = 0; FrameBlock = 250; } } public void preRender() { if (isRunning) { SimClock += DeltaT; try { Thread.sleep(DeltaT); } catch(InterruptedException e) {} // diagnostics if (debug) { if (FrameCount++ >= FrameBlock) { long Now = System.currentTimeMillis(); double AvgDelay = (double)(Now - Then)/(double)FrameBlock; if (html) { System.out.print("<TR><TD><CODE>"+DeltaT+ "</CODE></TD>\n<TD><CODE>"+AvgDelay+"</CODE></TD>\n"); String s = ""; for (int i=0; i<(int)AvgDelay-DeltaT; i++) { s += "*"; } System.out.print("<TD><CODE>"+s+"</CODE></TD></TR>\n"); } else // (!html) { System.out.print(" "+DeltaT+" "+ Double1.format(AvgDelay)+" "); String s = ""; for (int i=0; i<(int)AvgDelay-DeltaT; i++) { s += "*"; } System.out.print(s+"\n"); } // reset counter Then = Now; FrameCount = 0; // increment DeltaT DeltaT++; } } } } public long getSimClock() { return SimClock; } public void setDeltaT(int dt) { DeltaT = dt; } public void setSimClock(long p) { SimClock = p; if (debug) { Then = System.currentTimeMillis(); FrameCount = 0; } } public void setSimClock(long p, int dt) { setDeltaT(dt); setSimClock(p); } /** * - starts simulation clock * - resets diagnostics * - prints diagnostic header on console */ public void startSimClock() { isRunning = true; if (debug) { Then = System.currentTimeMillis(); FrameCount = 0; DateFormat DayTime; DayTime = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); if (html) { System.out.println("<P><CODE>Program: "+ProgramName+"<BR>"); System.out.println("Run "+DayTime.format(new Date())+"<BR>"); System.out.println("OS Arch.: "+System.getProperty("os.arch")+"<BR>"); System.out.println("OS: "+System.getProperty("os.name")+ " Version: "+System.getProperty("os.version")+"<BR></CODE><HR>"); System.out.println("<TR><TH><CODE>DeltaT</CODE></TH>\n"+ "<TH><CODE>Frame<BR>Delay</CODE></TH>"+ "<TH><CODE>Lag</CODE></TH></TR>"); System.out.println("<TR><TH><CODE>(ms)</CODE></TH>\n"+ "<TH><CODE>(ms)</CODE></TH>"+ "<TH><CODE>(ms)</CODE></TH><TR>"); } else // (!html) { System.out.println(""); System.out.println("Program: "+ProgramName); System.out.println("Run "+DayTime.format(new Date())); System.out.println("OS Arch.: "+System.getProperty("os.arch")); System.out.println("OS: "+System.getProperty("os.name")+ " Version: "+System.getProperty("os.version")); System.out.println("Averaging block = "+FrameBlock+" Frames"); System.out.println("---------------------------------"); System.out.print(" Frame\n"); System.out.print("DeltaT Delay Lag\n"); System.out.print("(ms) (ms) (ms)\n"); System.out.print("------ --------- -----------\n"); } } } public void stopSimClock() { isRunning = false; } } /** * * */ public class DaliInterpolator extends Behavior {// 1. alarm WakeupCriterion yawn; // 2. communicate with simulation clock in extended Canvas3D Dali3D c3d; // 3. set model Alpha SimAlpha; public DaliInterpolator(Dali3D dp, Alpha ap) { c3d = dp; SimAlpha = ap; yawn = new WakeupOnElapsedFrames(0); } public void initialize() {// 1. alarm wakeupOn(yawn); // 2. set sim clock c3d.setSimClock(0); c3d.startSimClock(); // 3. set model SimAlpha.setStartTime(0); } public void processStimulus(Enumeration e) {// 1. alarm wakeupOn(yawn); // 2. clock // nothing here. It's all done in the Canvas3D // 3. set model // do everything in the extensions } } public class DaliRotationInterpolator extends DaliInterpolator { TransformGroup targetTG; private Transform3D t3d; public DaliRotationInterpolator(Dali3D dp, Alpha ap, TransformGroup tg ) { super(dp, ap); targetTG = tg; t3d = new Transform3D(); } public void initialize() { super.initialize(); targetTG.setTransform(t3d); } public void processStimulus(Enumeration e) { super.processStimulus(e); t3d.rotY(Math.PI*2.0*SimAlpha.value(c3d.getSimClock())); targetTG.setTransform(t3d); } // end method } }