001: /*
002: * $Header: /cvs/j3dfly/J3dFly/src/org/jdesktop/j3dfly/utils/behaviors/KBSplineFromFileBG.java,v 1.1 2005/04/20 21:04:50 paulby Exp $
003: *
004: * Sun Public License Notice
005: *
006: * The contents of this file are subject to the Sun Public License Version
007: * 1.0 (the "License"). You may not use this file except in compliance with
008: * the License. A copy of the License is available at http://www.sun.com/
009: *
010: * The Original Code is Java 3D(tm) Fly Through.
011: * The Initial Developer of the Original Code is Paul Byrne.
012: * Portions created by Paul Byrne are Copyright (C) 2002.
013: * All Rights Reserved.
014: *
015: * Contributor(s): Paul Byrne.
016: *
017: **/
018: package org.jdesktop.j3dfly.utils.behaviors;
019:
020: import java.io.StreamTokenizer;
021: import java.io.BufferedReader;
022: import java.io.FileReader;
023: import java.io.IOException;
024: import java.util.ArrayList;
025: import javax.swing.JFrame;
026: import javax.swing.JPanel;
027: import javax.swing.JToggleButton;
028: import javax.swing.JButton;
029: import javax.swing.JFileChooser;
030:
031: import javax.media.j3d.TransformGroup;
032: import javax.media.j3d.Transform3D;
033: import javax.media.j3d.BoundingSphere;
034: import javax.media.j3d.Alpha;
035: import javax.media.j3d.BranchGroup;
036: import javax.media.j3d.Interpolator;
037: import javax.vecmath.Point3d;
038: import javax.vecmath.Point3f;
039: import org.jdesktop.j3dfly.utils.developmenttools.DevelopmentLocale;
040: import org.jdesktop.j3dfly.utils.loadercontrol.ExampleFileFilter;
041: import com.sun.j3d.utils.behaviors.interpolators.KBRotPosScaleSplinePathInterpolator;
042: import com.sun.j3d.utils.behaviors.interpolators.KBKeyFrame;
043:
044: /**
045: * A SceneGraph node which applies a KBRotPosScaleSplinePathInterpolator
046: * to a transformGroup. The main feature is that the KeyFrames for the
047: * Spline are read from a file
048: *
049: * Each line in the file represents a component of the spline, End of
050: * lines are significant. Comments follow the Java // style (not /*)
051: *
052: * The first line in the file must a single number, which is the number of
053: * increasingAlphaDuration for the interpolator.
054: *
055: * All subsequent lines must contain 13 floating point values representing
056: * the KBKeyFrame values of
057: * knot pos.x pos.y pos.z heading pitch bank scale.x scale.y scale.z
058: * tension continuity bias
059: *
060: * @author paulby
061: * @version 1.8 01/18/02
062: */
063: public class KBSplineFromFileBG extends BranchGroup implements
064: java.awt.event.ActionListener {
065:
066: private JFileChooser fileChooser = null;
067: private JToggleButton enableB;
068: private JButton loadB;
069: private String filename;
070: protected Alpha alpha;
071:
072: public KBSplineFromFileBG() {
073: super ();
074: init();
075: }
076:
077: /** Creates new KBRotPosScaleSplinePathFromFileInterpolator */
078: public KBSplineFromFileBG(TransformGroup target, String filename) {
079: super ();
080: this .filename = filename;
081: TransformGroup tg = new TransformGroup();
082: tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
083: Interpolator interp = createInterpolator(filename, target);
084:
085: interp.setSchedulingBounds(new BoundingSphere(new Point3d(),
086: Double.POSITIVE_INFINITY));
087: interp.setEnable(false);
088: this .setCapability(ALLOW_CHILDREN_READ);
089: this .addChild(interp);
090:
091: init();
092: }
093:
094: public String getFilename() {
095: return filename;
096: }
097:
098: private void init() {
099: /*
100: JFrame frame = new JFrame();
101: JPanel panel = new JPanel();
102: enableB = new JToggleButton("Auto Fly");
103: enableB.addActionListener( this );
104: loadB = new JButton("Load...");
105: loadB.addActionListener( this );
106: panel.add( enableB );
107: panel.add( loadB );
108: frame.getContentPane().add( panel );
109: frame.pack();
110: frame.setVisible( true );
111: */
112: }
113:
114: private Interpolator createInterpolator(String filename,
115: TransformGroup target) {
116: Interpolator ret = null;
117: KBKeyFrame[] keyFrames = null;
118:
119: alpha = new Alpha();
120: try {
121: if (filename == null) {
122: keyFrames = new KBKeyFrame[] {
123: new KBKeyFrame(0.0f, 0, new Point3f(), 0f, 0f,
124: 0f, new Point3f(1f, 1f, 1f), 0f, 0f, 0f),
125: new KBKeyFrame(1.0f, 0, new Point3f(10f, 10f,
126: 10f), 0f, 0f, 0f, new Point3f(1f, 1f,
127: 1f), 0f, 0f, 0f) };
128:
129: } else
130: keyFrames = loadFile(filename, alpha);
131: } catch (IOException e) {
132: e.printStackTrace();
133: System.exit(1);
134: }
135:
136: Transform3D trans = new Transform3D();
137: trans.setIdentity();
138: ret = new KBRotPosScaleSplinePathInterpolator(alpha, target,
139: trans, keyFrames);
140:
141: return ret;
142: }
143:
144: public void loadFile(String filename) throws IOException {
145: KBKeyFrame[] keys = loadFile(filename, alpha);
146: ((KBRotPosScaleSplinePathInterpolator) this .getChild(0))
147: .setKeyFrames(keys);
148: }
149:
150: /**
151: * Load the file
152: *
153: * Alpha will be populated with the Alpha data in the file
154: * and the KeyFrames in the file will be returned
155: */
156: private KBKeyFrame[] loadFile(String filename, Alpha alpha)
157: throws IOException {
158: ArrayList frames = new ArrayList();
159: KBKeyFrame[] ret = null;
160: StreamTokenizer tok = null;
161:
162: try {
163: tok = new StreamTokenizer(new BufferedReader(
164: new FileReader(filename)));
165:
166: tok.eolIsSignificant(true);
167: tok.parseNumbers();
168: tok.slashSlashComments(true);
169:
170: readAlpha(alpha, tok);
171:
172: tok.nextToken();
173: while (tok.ttype != StreamTokenizer.TT_EOF) {
174: // Skip any blank lines
175: while (tok.ttype == StreamTokenizer.TT_EOL)
176: tok.nextToken();
177:
178: if (tok.ttype != StreamTokenizer.TT_EOF)
179: frames.add(readKeyFrame(tok));
180: }
181:
182: ret = new KBKeyFrame[frames.size()];
183: ret = (KBKeyFrame[]) frames.toArray(ret);
184:
185: } catch (IOException e) {
186: if (tok == null)
187: throw e;
188: else
189: throw new IOException("Error at line " + tok.lineno()
190: + " " + e.getMessage());
191: }
192:
193: return ret;
194: }
195:
196: private void readAlpha(Alpha alpha, StreamTokenizer tok)
197: throws IOException {
198: alpha.setLoopCount(-1);
199: tok.nextToken();
200: alpha.setIncreasingAlphaDuration((long) tok.nval);
201:
202: tok.nextToken();
203: if (tok.ttype != StreamTokenizer.TT_EOL)
204: throw new IOException(
205: "Invalid alpha format, alpha line should just contain the duration");
206: }
207:
208: private KBKeyFrame readKeyFrame(StreamTokenizer tok)
209: throws IOException {
210: float[] data = new float[13];
211:
212: //float knot; data[0]
213: //float posX; data[1]
214: //float posY; data[2]
215: //float posZ; data[3]
216: //float heading; data[4]
217: //float pitch; data[5]
218: //float bank; data[6]
219: //float scaleX; data[7]
220: //float scaleY; data[8]
221: //float scaleZ; data[9]
222: //float tension; data[10]
223: //float continuity; data[11]
224: //float bias; data[12]
225:
226: for (int i = 0; i < data.length; i++) {
227: if (tok.ttype != StreamTokenizer.TT_NUMBER)
228: throw new IOException(
229: "Invalid KeyFrame format, KeyFrame line should just contain 13 floats.");
230: data[i] = (float) tok.nval;
231: tok.nextToken();
232: }
233:
234: if (!(tok.ttype == StreamTokenizer.TT_EOF || tok.ttype == StreamTokenizer.TT_EOL))
235: throw new IOException(
236: "Invalid KeyFrame format, KeyFrame line should just contain 13 floats.");
237:
238: return new KBKeyFrame(data[0], // Knot
239: 0, // Spline
240: new Point3f(data[1], data[2], data[3]), // Position
241: (float) Math.toRadians(data[4]), // heading
242: (float) Math.toRadians(data[5]), // pitch
243: (float) Math.toRadians(data[6]), // bank
244: new Point3f(data[7], data[8], data[9]), // scale
245: data[10], // tension
246: data[11], // continuity
247: data[12]); // bias
248: }
249:
250: public void setEnabled(boolean enabled) {
251: ((Interpolator) this .getChild(0)).setEnable(enabled);
252: }
253:
254: public boolean isEnabled() {
255: return ((Interpolator) this .getChild(0)).getEnable();
256: }
257:
258: public void actionPerformed(java.awt.event.ActionEvent actionEvent) {
259: if (actionEvent.getSource() == enableB) {
260: setEnabled(enableB.isSelected());
261: } else if (actionEvent.getSource() == loadB) {
262: if (fileChooser == null) {
263: fileChooser = new JFileChooser();
264: ExampleFileFilter filter = new ExampleFileFilter();
265: filter.addExtension("kbsp");
266: fileChooser.setFileFilter(filter);
267: String currentDir = System.getProperty("user.dir");
268: fileChooser.setCurrentDirectory(new java.io.File(
269: currentDir));
270: }
271: int r = fileChooser.showOpenDialog(null);
272: if (r == JFileChooser.APPROVE_OPTION) {
273: try {
274: KBKeyFrame[] keys = loadFile(fileChooser
275: .getSelectedFile().getAbsolutePath(), alpha);
276: ((KBRotPosScaleSplinePathInterpolator) this
277: .getChild(0)).setKeyFrames(keys);
278: } catch (IOException e) {
279: e.printStackTrace();
280: return;
281: }
282: }
283: }
284: }
285:
286: }
|