001: /**********************************************************
002: Copyright (C) 2001 Daniel Selman
003:
004: First distributed with the book "Java 3D Programming"
005: by Daniel Selman and published by Manning Publications.
006: http://manning.com/selman
007:
008: This program is free software; you can redistribute it and/or
009: modify it under the terms of the GNU General Public License
010: as published by the Free Software Foundation, version 2.
011:
012: This program is distributed in the hope that it will be useful,
013: but WITHOUT ANY WARRANTY; without even the implied warranty of
014: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: GNU General Public License for more details.
016:
017: The license can be found on the WWW at:
018: http://www.fsf.org/copyleft/gpl.html
019:
020: Or by writing to:
021: Free Software Foundation, Inc.,
022: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023:
024: Authors can be contacted at:
025: Daniel Selman: daniel@selman.org
026:
027: If you make changes you think others would like, please
028: contact one of the authors or someone at the
029: www.j3d.org web site.
030: **************************************************************/package com.db.utils.euler;
031:
032: import java.applet.Applet;
033: import java.awt.*;
034: import java.net.*;
035: import java.io.*;
036: import java.util.*;
037:
038: import javax.media.j3d.*;
039: import javax.vecmath.*;
040:
041: import com.sun.j3d.utils.behaviors.interpolators.*;
042:
043: //*****************************************************************************
044: /**
045: * Utils
046: *
047: * @author Daniel Selman
048: * @version 1.0
049: */
050: //*****************************************************************************
051: public class Utils {
052: // convert an angular rotation about an axis to a Quaternion
053: static Quat4f createQuaternionFromAxisAndAngle(Vector3d axis,
054: double angle) {
055: double sin_a = Math.sin(angle / 2);
056: double cos_a = Math.cos(angle / 2);
057:
058: // use a vector so we can call normalize
059: Vector4f q = new Vector4f();
060:
061: q.x = (float) (axis.x * sin_a);
062: q.y = (float) (axis.y * sin_a);
063: q.z = (float) (axis.z * sin_a);
064: q.w = (float) cos_a;
065:
066: // It is necessary to normalise the quaternion
067: // in case any values are very close to zero.
068: q.normalize();
069:
070: // convert to a Quat4f and return
071: return new Quat4f(q);
072: }
073:
074: // convert three rotations about the Euler axes to a Quaternion
075: static Quat4f createQuaternionFromEuler(double angleX,
076: double angleY, double angleZ) {
077: // simply call createQuaternionFromAxisAndAngle
078: // for each axis and multiply the results
079: Quat4f qx = createQuaternionFromAxisAndAngle(new Vector3d(1, 0,
080: 0), angleX);
081: Quat4f qy = createQuaternionFromAxisAndAngle(new Vector3d(0, 1,
082: 0), angleY);
083: Quat4f qz = createQuaternionFromAxisAndAngle(new Vector3d(0, 0,
084: 1), angleZ);
085:
086: // qx = qx * qy
087: qx.mul(qy);
088:
089: // qx = qx * qz
090: qx.mul(qz);
091:
092: return qx;
093: }
094:
095: static public double getRandomNumber(double basis, double random) {
096: return basis + ((float) Math.random() * random * 2f) - (random);
097: }
098:
099: static public double getRandomNumber(double basis, double random,
100: double scale) {
101: double value = basis + ((float) Math.random() * random * 2f)
102: - (random);
103: return value * scale;
104: }
105:
106: static public StringBuffer readFile(URL urlFile) {
107: // allocate a temporary buffer to store the input file
108: StringBuffer szBufferData = new StringBuffer();
109: Vector keyFramesVector = new Vector();
110:
111: try {
112: InputStream inputStream = urlFile.openStream();
113:
114: int nChar = 0;
115:
116: // read the entire file into the StringBuffer
117: while (true) {
118: nChar = inputStream.read();
119:
120: // if we have not hit the end of file
121: // add the character to the StringBuffer
122: if (nChar != -1)
123: szBufferData.append((char) nChar);
124: else
125: // EOF
126: break;
127: }
128:
129: inputStream.close();
130: } catch (Exception e) {
131: System.err.println(e.toString());
132: return null;
133: }
134:
135: return szBufferData;
136: }
137:
138: static public RotPosScaleTCBSplinePathInterpolator createSplinePathInterpolator(
139: Alpha alpha, TransformGroup tg, Transform3D axis,
140: URL urlKeyframes) {
141: TCBKeyFrame[] keyFrames = readKeyFrames(urlKeyframes);
142:
143: if (keyFrames != null)
144: return new RotPosScaleTCBSplinePathInterpolator(alpha, tg,
145: axis, keyFrames);
146:
147: return null;
148: }
149:
150: static public TCBKeyFrame[] readKeyFrames(URL urlKeyframes) {
151: StringBuffer szBufferData = readFile(urlKeyframes);
152:
153: if (szBufferData == null)
154: return null;
155:
156: Vector keyFramesVector = new Vector();
157:
158: // create a tokenizer to tokenize the input file at whitespace
159: java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
160: szBufferData.toString());
161:
162: // each keyframe is defined as follows
163: // - knot (0 >= k <= 1)
164: // - position (x,y,z)
165: // - rotation (rx,ry,rz)
166: // - scale (x,y,z)
167:
168: // - tension (-1 >= t <= 1)
169: // - continuity (-1 >= c <= 1)
170: // - bias (-1 >= b <= 1)
171: // - linear (int - 0 or 1)
172:
173: while (true) {
174: try {
175: float knot = Float.parseFloat(tokenizer.nextToken());
176:
177: float posX = Float.parseFloat(tokenizer.nextToken());
178: float posY = Float.parseFloat(tokenizer.nextToken());
179: float posZ = Float.parseFloat(tokenizer.nextToken());
180:
181: float rotX = Float.parseFloat(tokenizer.nextToken());
182: float rotY = Float.parseFloat(tokenizer.nextToken());
183: float rotZ = Float.parseFloat(tokenizer.nextToken());
184:
185: float scaleX = Float.parseFloat(tokenizer.nextToken());
186: float scaleY = Float.parseFloat(tokenizer.nextToken());
187: float scaleZ = Float.parseFloat(tokenizer.nextToken());
188:
189: float tension = Float.parseFloat(tokenizer.nextToken());
190: float continuity = Float.parseFloat(tokenizer
191: .nextToken());
192: float bias = Float.parseFloat(tokenizer.nextToken());
193:
194: int linear = Integer.parseInt(tokenizer.nextToken());
195:
196: TCBKeyFrame keyframe = new TCBKeyFrame(knot, linear,
197: new Point3f(posX, posY, posZ),
198: createQuaternionFromEuler(rotX, rotY, rotZ),
199: new Point3f(scaleX, scaleY, scaleZ), tension,
200: continuity, bias);
201:
202: keyFramesVector.add(keyframe);
203: } catch (Exception e) {
204: break;
205: }
206: }
207:
208: // create the return structure and populate
209: TCBKeyFrame[] keysReturn = new TCBKeyFrame[keyFramesVector
210: .size()];
211:
212: for (int n = 0; n < keysReturn.length; n++)
213: keysReturn[n] = (TCBKeyFrame) keyFramesVector.get(n);
214:
215: // return the array
216: return keysReturn;
217: }
218: }
|