001: /*
002: * $RCSfile: TCBSplinePathInterpolator.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:12 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.behaviors.interpolators;
046:
047: import javax.media.j3d.*;
048: import java.util.*;
049: import javax.vecmath.*;
050: import com.sun.j3d.internal.J3dUtilsI18N;
051:
052: /**
053: * TCBSplinePathInterpolator behavior. This class defines the base class for
054: * all TCB (Kochanek-Bartels) Spline Path Interpolators.
055: *
056: * @since Java3D 1.1
057: */
058:
059: public abstract class TCBSplinePathInterpolator extends
060: TransformInterpolator {
061:
062: private int keysLength;
063:
064: /**
065: * An array of KBKeyFrame for interpolator
066: */
067: protected TCBKeyFrame[] keyFrames;
068:
069: /**
070: * This value is the distance between knots
071: * value which can be used in further calculations by the subclass.
072: */
073: protected float currentU;
074:
075: /**
076: * The lower knot
077: */
078: protected int lowerKnot;
079:
080: /**
081: * The upper knot
082: */
083: protected int upperKnot;
084:
085: /**
086: * Constructs a TCBSplinePathInterpolator node with a null alpha value and
087: * a null target of TransformGroup
088: *
089: * @since Java 3D 1.3
090: */
091:
092: TCBSplinePathInterpolator() {
093: }
094:
095: /**
096: * @deprecated As of Java 3D version 1.3, replaced by
097: * <code>TCBSplinePathInterpolator(Alpha, TransformGroup, TCBKeyFrame[]) </code>
098: */
099: public TCBSplinePathInterpolator(Alpha alpha, TCBKeyFrame keys[]) {
100: this (alpha, null, keys);
101: }
102:
103: /**
104: * Constructs a new TCBSplinePathInterpolator object that interpolates
105: * between keyframes with specified alpha, target and default axisOfTransform
106: * set to identity. It takes at least two key frames. The first key
107: * frame's knot must have a value of 0.0 and the last knot must have a
108: * value of 1.0. An intermediate key frame with index k must have a
109: * knot value strictly greater than the knot value of a key frame with
110: * index less than k. Once this constructor has all the valid key frames
111: * it creates its own list of key fames that duplicates the first key frame
112: * at the beginning of the list and the last key frame at the end of the
113: * list.
114: * @param alpha the alpha object for this interpolator
115: * @param target the TransformGroup node effected by this TCBSplinePathInterpolator
116: * @param keys an array of TCBKeyFrame. Requires at least two key frames.
117: *
118: * @since Java 3D 1.3
119: */
120: public TCBSplinePathInterpolator(Alpha alpha,
121: TransformGroup target, TCBKeyFrame keys[]) {
122: super (alpha, target);
123: processKeyFrames(keys);
124: }
125:
126: /**
127: * Constructs a new TCBSplinePathInterpolator object that interpolates
128: * between keyframes with specified alpha, target and axisOfTransform.
129: * It takes at least two key frames. The first key
130: * frame's knot must have a value of 0.0 and the last knot must have a
131: * value of 1.0. An intermediate key frame with index k must have a
132: * knot value strictly greater than the knot value of a key frame with
133: * index less than k. Once this constructor has all the valid key frames
134: * it creates its own list of key fames that duplicates the first key frame
135: * at the beginning of the list and the last key frame at the end of the
136: * list.
137: * @param alpha the alpha object for this interpolator
138: * @param target the TransformGroup node effected by this TCBSplinePathInterpolator
139: * @param axisOfTransform the transform that defines the local coordinate
140: * @param keys an array of TCBKeyFrame. Requires at least two key frames.
141: *
142: * @since Java 3D 1.3
143: */
144: public TCBSplinePathInterpolator(Alpha alpha,
145: TransformGroup target, Transform3D axisOfTransform,
146: TCBKeyFrame keys[]) {
147: super (alpha, target, axisOfTransform);
148: processKeyFrames(keys);
149: }
150:
151: /**
152: * Process the new array of key frames
153: */
154: private void processKeyFrames(TCBKeyFrame keys[]) {
155:
156: // Make sure that we have at least two key frames
157: keysLength = keys.length;
158: if (keysLength < 2) {
159: throw new IllegalArgumentException(J3dUtilsI18N
160: .getString("TCBSplinePathInterpolator0"));
161:
162: }
163:
164: // Make sure that the first key frame's knot is equal to 0.0
165: if (keys[0].knot < -0.0001 || keys[0].knot > 0.0001) {
166: throw new IllegalArgumentException(J3dUtilsI18N
167: .getString("TCBSplinePathInterpolator1"));
168: }
169:
170: // Make sure that the last key frames knot is equal to 1.0
171: if (keys[keysLength - 1].knot - 1.0 < -0.0001
172: || keys[keysLength - 1].knot - 1.0 > 0.0001) {
173: throw new IllegalArgumentException(J3dUtilsI18N
174: .getString("TCBSplinePathInterpolator2"));
175: }
176:
177: // Make sure that all the knots are in sequence
178: for (int i = 0; i < keysLength; i++) {
179: if (i > 0 && keys[i].knot < keys[i - 1].knot) {
180: throw new IllegalArgumentException(J3dUtilsI18N
181: .getString("TCBSplinePathInterpolator3"));
182: }
183: }
184:
185: // Make space for a leading and trailing key frame in addition to
186: // the keys passed in
187: keyFrames = new TCBKeyFrame[keysLength + 2];
188: keyFrames[0] = new TCBKeyFrame();
189: keyFrames[0] = keys[0];
190: for (int i = 1; i < keysLength + 1; i++) {
191: keyFrames[i] = keys[i - 1];
192: }
193: keyFrames[keysLength + 1] = new TCBKeyFrame();
194: keyFrames[keysLength + 1] = keys[keysLength - 1];
195:
196: // Make key frame length reflect the 2 added key frames
197: keysLength += 2;
198: }
199:
200: /**
201: * This method retrieves the length of the key frame array.
202: * @return the number of key frames
203: */
204: public int getArrayLength() {
205: return keysLength - 2;
206: }
207:
208: /**
209: * This method retrieves the key frame at the specified index.
210: * @param index the index of the key frame requested
211: * @return the key frame at the associated index
212: */
213: public TCBKeyFrame getKeyFrame(int index) {
214:
215: // We add 1 to index because we have added a leading keyFrame
216: return this .keyFrames[index + 1];
217: }
218:
219: /**
220: * This method computes the bounding knot indices and interpolation value
221: * "CurrentU" given the specified value of alpha and the knots[] array.
222: * @param alphaValue alpha value between 0.0 and 1.0
223: *
224: * @since Java 3D 1.3
225: */
226: protected void computePathInterpolation(float alphaValue) {
227:
228: // skip knots till we find the two we fall between
229: int i = 1;
230: int len = keysLength - 2;
231: while ((alphaValue > keyFrames[i].knot) && (i < len)) {
232: i++;
233: }
234:
235: if (i == 1) {
236: currentU = 0f;
237: lowerKnot = 1;
238: upperKnot = 2;
239: } else {
240: currentU = (alphaValue - keyFrames[i - 1].knot)
241: / (keyFrames[i].knot - keyFrames[i - 1].knot);
242: lowerKnot = i - 1;
243: upperKnot = i;
244: }
245: }
246:
247: /**
248: * @deprecated As of Java 3D version 1.3, replaced by
249: * <code>computePathInterpolation(float)</code>
250: */
251: protected void computePathInterpolation() {
252: float value = (this .getAlpha()).value();
253: computePathInterpolation(value);
254: }
255:
256: /**
257: * Copies all TCBSplinePathInterpolator information from
258: * <code>originalNode</code> into
259: * the current node. This method is called from the
260: * <code>cloneNode</code> method which is, in turn, called by the
261: * <code>cloneTree</code> method.<P>
262: *
263: * @param originalNode the original node to duplicate.
264: * @param forceDuplicate when set to <code>true</code>, causes the
265: * <code>duplicateOnCloneTree</code> flag to be ignored. When
266: * <code>false</code>, the value of each node's
267: * <code>duplicateOnCloneTree</code> variable determines whether
268: * NodeComponent data is duplicated or copied.
269: *
270: * @exception RestrictedAccessException if this object is part of a live
271: * or compiled scenegraph.
272: *
273: * @see Node#duplicateNode
274: * @see Node#cloneTree
275: * @see NodeComponent#setDuplicateOnCloneTree
276: */
277: public void duplicateNode(Node originalNode, boolean forceDuplicate) {
278: super .duplicateNode(originalNode, forceDuplicate);
279: TCBSplinePathInterpolator originalSpline = (TCBSplinePathInterpolator) originalNode;
280: setAlpha(originalSpline.getAlpha());
281: keysLength = originalSpline.keysLength;
282: keyFrames = new TCBKeyFrame[keysLength];
283: System.arraycopy(originalSpline.keyFrames, 0, keyFrames, 0,
284: keysLength);
285: }
286: }
|