001: /*
002: * $RCSfile: LwsFrame.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.4 $
041: * $Date: 2007/02/09 17:20:08 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.loaders.lw3d;
046:
047: import java.io.*;
048: import javax.vecmath.Matrix4d;
049: import javax.vecmath.Vector3d;
050: import javax.vecmath.Point3f;
051:
052: /**
053: * This class is responsible for parsing the data in a Scene file
054: * associated with a single keyframe. This data includes the position,
055: * orientation, and scaling information, in addition to the frame number
056: * of that keyframe and some spline controls which are currently
057: * ignored.
058: */
059:
060: class LwsFrame extends TextfileParser {
061:
062: // data from the file
063: double x, y, z;
064: double heading, pitch, bank;
065: double xScale, yScale, zScale;
066: double frameNumber;
067: int linearValue;
068: double tension, continuity, bias;
069:
070: /**
071: * Constructor: parses and stores all data associated with a particular
072: * keyframe
073: */
074: LwsFrame(StreamTokenizer st) {
075: x = getNumber(st);
076: y = getNumber(st);
077: z = -getNumber(st);
078: debugOutputLn(VALUES, "x, y, z " + x + ", " + y + ", " + z);
079: heading = getNumber(st);
080: pitch = getNumber(st);
081: bank = getNumber(st);
082: debugOutputLn(VALUES, "(degrees) h, p, b = " + heading + ", "
083: + pitch + ", " + bank);
084: heading *= (Math.PI / 180.0); // Java3d works with radians
085: pitch *= (Math.PI / 180.0);
086: bank *= (Math.PI / 180.0);
087: debugOutputLn(VALUES, "(radians) h, p, b = " + heading + ", "
088: + pitch + ", " + bank);
089: debugOutputLn(LINE_TRACE, "got pos and ori");
090: xScale = getNumber(st);
091: yScale = getNumber(st);
092: zScale = getNumber(st);
093: debugOutputLn(VALUES, "xs, ys, zs " + xScale + ", " + yScale
094: + ", " + zScale);
095: frameNumber = (int) getNumber(st);
096: // Note: The following spline controls are ignored
097: linearValue = (int) getNumber(st);
098: debugOutputLn(VALUES, "framenum, linear " + frameNumber + " , "
099: + linearValue);
100: tension = getNumber(st);
101: continuity = getNumber(st);
102: bias = getNumber(st);
103: debugOutputLn(VALUES, "tension, cont, bias = " + tension + ", "
104: + continuity + ", " + bias);
105: }
106:
107: /**
108: * Construct new frame that's in-between two given frames
109: * Ratio gives the interpolation value for how far in-between
110: * the new frame should be (0.5 is half-way, etc)
111: */
112: LwsFrame(LwsFrame prevFrame, LwsFrame nextFrame, double ratio) {
113:
114: x = prevFrame.x + (nextFrame.x - prevFrame.x) * ratio;
115: y = prevFrame.y + (nextFrame.y - prevFrame.y) * ratio;
116: z = prevFrame.z + (nextFrame.z - prevFrame.z) * ratio;
117:
118: heading = prevFrame.heading
119: + (nextFrame.heading - prevFrame.heading) * ratio;
120: pitch = prevFrame.pitch + (nextFrame.pitch - prevFrame.pitch)
121: * ratio;
122: bank = prevFrame.bank + (nextFrame.bank - prevFrame.bank)
123: * ratio;
124: xScale = prevFrame.xScale
125: + (nextFrame.xScale - prevFrame.xScale) * ratio;
126: yScale = prevFrame.yScale
127: + (nextFrame.yScale - prevFrame.yScale) * ratio;
128: zScale = prevFrame.zScale
129: + (nextFrame.zScale - prevFrame.zScale) * ratio;
130: frameNumber = prevFrame.frameNumber
131: + (nextFrame.frameNumber - prevFrame.frameNumber)
132: * ratio;
133:
134: // The following are not interpolated
135: linearValue = prevFrame.linearValue;
136: tension = prevFrame.tension;
137: continuity = prevFrame.continuity;
138: bias = prevFrame.bias;
139: }
140:
141: /**
142: * Using hermite interpolation construct a new frame that's
143: * in-between two given frames. We also need to be given a
144: * frame before the first frame and a frame after the second
145: * frame. The calling function will make sure that we get the
146: * four appropriate frames.
147: *
148: * Ratio gives the interpolation value for how far in-between
149: * the new frame should be. (.5 is half-way, etc.)
150: */
151: LwsFrame(LwsFrame prevFrame, LwsFrame frame1, LwsFrame frame2,
152: LwsFrame nextFrame, double u, double adj0, double adj1) {
153:
154: double h1, h2, h3, h4;
155: double dd0a, dd0b, ds1a, ds1b;
156:
157: // pre-compute spline coefficients
158: double u2, u3, z1;
159: u2 = u * u;
160: u3 = u2 * u;
161: z1 = 3.0f * u2 - u3 - u3;
162: h1 = 1.0f - z1;
163: h2 = z1;
164: h3 = u3 - u2 - u2 + u;
165: h4 = u3 - u2;
166:
167: dd0a = (1.0f - frame1.tension) * (1.0f + frame1.continuity)
168: * (1.0f + frame1.bias);
169:
170: dd0b = (1.0f - frame1.tension) * (1.0f - frame1.continuity)
171: * (1.0f - frame1.bias);
172:
173: ds1a = (1.0f - frame2.tension) * (1.0f - frame2.continuity)
174: * (1.0f + frame2.bias);
175:
176: ds1b = (1.0f - frame2.tension) * (1.0f + frame2.continuity)
177: * (1.0f - frame2.bias);
178:
179: double[] v = new double[4];
180:
181: // interpolate x, y, z
182: v[0] = prevFrame.x;
183: v[1] = frame1.x;
184: v[2] = frame2.x;
185: v[3] = nextFrame.x;
186: x = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0, adj1,
187: h1, h2, h3, h4);
188: v[0] = prevFrame.y;
189: v[1] = frame1.y;
190: v[2] = frame2.y;
191: v[3] = nextFrame.y;
192: y = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0, adj1,
193: h1, h2, h3, h4);
194: v[0] = prevFrame.z;
195: v[1] = frame1.z;
196: v[2] = frame2.z;
197: v[3] = nextFrame.z;
198: z = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0, adj1,
199: h1, h2, h3, h4);
200:
201: // interpolate heading pitch and bank
202: v[0] = prevFrame.heading;
203: v[1] = frame1.heading;
204: v[2] = frame2.heading;
205: v[3] = nextFrame.heading;
206: heading = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0,
207: adj1, h1, h2, h3, h4);
208:
209: v[0] = prevFrame.pitch;
210: v[1] = frame1.pitch;
211: v[2] = frame2.pitch;
212: v[3] = nextFrame.pitch;
213: pitch = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0,
214: adj1, h1, h2, h3, h4);
215:
216: v[0] = prevFrame.bank;
217: v[1] = frame1.bank;
218: v[2] = frame2.bank;
219: v[3] = nextFrame.bank;
220: bank = computeInterpolation(v, dd0a, dd0b, ds1a, ds1b, adj0,
221: adj1, h1, h2, h3, h4);
222:
223: // interpolate scale - scale interpolation is assumed to be linear
224: xScale = frame1.xScale + (frame2.xScale - frame1.xScale) * u;
225: yScale = frame1.yScale + (frame2.yScale - frame1.yScale) * u;
226: zScale = frame1.zScale + (frame2.zScale - frame1.zScale) * u;
227:
228: // interpolate frame number
229: frameNumber = frame1.frameNumber
230: + (frame2.frameNumber - frame1.frameNumber) * u;
231:
232: // The following are not interpolated
233: linearValue = frame2.linearValue;
234:
235: // We need to keep the spline smooth between knot points
236: tension = 0.0;
237: continuity = 0.0;
238: bias = 0.0;
239: }
240:
241: double computeInterpolation(double[] value, double dd0a,
242: double dd0b, double ds1a, double ds1b, double adj0,
243: double adj1, double h1, double h2, double h3, double h4) {
244:
245: double dd0, ds1;
246: double delta = value[2] - value[1];
247: double result;
248:
249: // if adj != 0
250: if (adj0 < -0.0001 || adj0 > 0.0001)
251: dd0 = adj0 * (dd0a * (value[1] - value[0]) + dd0b * delta);
252: else
253: dd0 = 0.5f * (dd0a + dd0b) * delta;
254:
255: // if adj != 0
256: if (adj1 < -0.0001 || adj1 > 0.0001)
257: ds1 = adj1 * (ds1a * delta + ds1b * (value[3] - value[2]));
258: else
259: ds1 = 0.5f * (ds1a + ds1b) * delta;
260:
261: result = value[1] * h1 + value[2] * h2 + dd0 * h3 + ds1 * h4;
262:
263: return (result);
264: }
265:
266: double getHeading() {
267: return heading;
268: }
269:
270: double getPitch() {
271: return pitch;
272: }
273:
274: double getBank() {
275: return bank;
276: }
277:
278: /**
279: * Sets the given matrix to contain the position, orientation, and
280: * scale values for the keyframe
281: */
282: void setMatrix(Matrix4d mat) {
283: setRotationMatrix(mat);
284: mat.setTranslation(new Vector3d(x, y, z));
285: Matrix4d m = new Matrix4d();
286: m.setColumn(0, xScale, 0, 0, 0); // setScale not yet implemented
287: m.setColumn(1, 0, yScale, 0, 0);
288: m.setColumn(2, 0, 0, zScale, 0);
289: m.setColumn(3, 0, 0, 0, 1);
290: mat.mul(m);
291: }
292:
293: /**
294: * Sets the given matrix to contain the orientation for this keyframe
295: */
296: void setRotationMatrix(Matrix4d mat) {
297: debugOutputLn(TRACE, "setRotMat()");
298: debugOutputLn(VALUES, " p, h, b = " + pitch + ", " + heading
299: + ", " + bank);
300: Matrix4d pitchMat = new Matrix4d();
301: pitchMat.rotX(-pitch);
302: Matrix4d bankMat = new Matrix4d();
303: bankMat.rotZ(bank);
304: mat.rotY(-heading);
305: mat.mul(pitchMat);
306: mat.mul(bankMat);
307: debugOutputLn(VALUES, "setRotMat(), mat = " + mat);
308: }
309:
310: Point3f getPosition() {
311: return (new Point3f((float) x, (float) y, (float) z));
312: }
313:
314: Point3f getScale() {
315: // Make sure we don't have zero scale components
316: if ((xScale < -0.0001 || xScale > 0.0001)
317: && (yScale < -0.0001 || yScale > 0.0001)
318: && (zScale < -0.0001 || zScale > 0.0001)) {
319: return (new Point3f((float) xScale, (float) yScale,
320: (float) zScale));
321: } else {
322: return (new Point3f(1.0f, 1.0f, 1.0f));
323: }
324: }
325:
326: double getFrameNum() {
327: return frameNumber;
328: }
329:
330: void printVals() {
331: debugOutputLn(VALUES, " x = " + x);
332: debugOutputLn(VALUES, " y = " + y);
333: debugOutputLn(VALUES, " z = " + z);
334: debugOutputLn(VALUES, " xScale = " + xScale);
335: debugOutputLn(VALUES, " yScale = " + yScale);
336: debugOutputLn(VALUES, " zScale = " + zScale);
337: debugOutputLn(VALUES, " heading = " + heading);
338: debugOutputLn(VALUES, " pitch = " + pitch);
339: debugOutputLn(VALUES, " bank = " + bank);
340: debugOutputLn(VALUES, " frameNum = " + frameNumber);
341: debugOutputLn(VALUES, " lin = " + linearValue);
342: debugOutputLn(VALUES, " tension = " + tension);
343: debugOutputLn(VALUES, " continuity = " + continuity);
344: debugOutputLn(VALUES, " bias = " + bias);
345: }
346:
347: }
|