001: /*
002: * $RCSfile: PathInterpolator.java,v $
003: *
004: * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
006: *
007: * This code is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License version 2 only, as
009: * published by the Free Software Foundation. Sun designates this
010: * particular file as subject to the "Classpath" exception as provided
011: * by Sun in the LICENSE file that accompanied this code.
012: *
013: * This code is distributed in the hope that it will be useful, but WITHOUT
014: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: * version 2 for more details (a copy is included in the LICENSE file that
017: * accompanied this code).
018: *
019: * You should have received a copy of the GNU General Public License version
020: * 2 along with this work; if not, write to the Free Software Foundation,
021: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
022: *
023: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
024: * CA 95054 USA or visit www.sun.com if you need additional information or
025: * have any questions.
026: *
027: * $Revision: 1.5 $
028: * $Date: 2008/02/28 20:17:27 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import java.util.Enumeration;
035:
036: /**
037: * PathInterpolator behavior. This class defines the base class for
038: * all Path Interpolators. Subclasses have access to the
039: * computePathInterpolation() method, which computes the
040: * currentInterpolationValue given the current time and alpha.
041: * The method also computes the currentKnotIndex, which is based on
042: * the currentInterpolationValue.
043: * The currentInterpolationValue is calculated
044: * by linearly interpolating among a series of predefined knots
045: * (using the value generated by the specified Alpha object).
046: * The first knot must have a value of 0.0 and the last knot must have a
047: * value of 1.0. An intermediate knot with index k must have a value
048: * strictly greater than any knot with index less than k.
049: */
050:
051: public abstract class PathInterpolator extends TransformInterpolator {
052:
053: // Array of knots
054: private float knots[];
055:
056: /**
057: * This value is the ratio between knot values indicated by
058: * the currentKnotIndex variable. So if a subclass wanted to
059: * interpolate between knot values, it would use the currentKnotIndex
060: * to get the bounding knots for the "real" value, then use the
061: * currentInterpolationValue to interpolate between the knots.
062: * To calculate this variable, a subclass needs to call
063: * the <code>computePathInterpolation(alphaValue)</code> method from the subclass's
064: * computeTransform() method. Then this variable will hold a valid
065: * value which can be used in further calculations by the subclass.
066: */
067: protected float currentInterpolationValue;
068:
069: /**
070: * This value is the index of the current base knot value, as
071: * determined by the alpha function. A subclass wishing to
072: * interpolate between bounding knots would use this index and
073: * the one following it, and would use the currentInterpolationValue
074: * variable as the ratio between these indices.
075: * To calculate this variable, a subclass needs to call
076: * the <code>computePathInterpolation(alphaValue)</code> method from the subclass's
077: * computeTransform() method. Then this variable will hold a valid
078: * value which can be used in further calculations by the subclass.
079: */
080: protected int currentKnotIndex;
081:
082: /**
083: * Constructs a PathInterpolator node with a null alpha value and
084: * a null target of TransformGroup
085: *
086: * since Java 3D 1.3
087: */
088: PathInterpolator() {
089: }
090:
091: /**
092: * Constructs a new PathInterpolator object that interpolates
093: * between the knot values in the knots array. The array of knots
094: * is copied into this PathInterpolator object.
095: * @param alpha the alpha object for this interpolator.
096: * @param knots an array of knot values that specify interpolation
097: * points.
098: *
099: * @deprecated As of Java 3D version 1.3, replaced by
100: * <code>PathInterpolator(Alpha, TransformGroup, float[]) </code>
101: */
102: public PathInterpolator(Alpha alpha, float[] knots) {
103: this (alpha, null, knots);
104: }
105:
106: /**
107: * Constructs a new PathInterpolator object that interpolates
108: * between the knot values in the knots array. The array of knots
109: * is copied into this PathInterpolator object.
110: * @param alpha the alpha object for this interpolator.
111: * @param target the transformgroup node effected by this pathInterpolator
112: * @param knots an array of knot values that specify interpolation
113: * points.
114: *
115: * @since Java 3D 1.3
116: */
117:
118: public PathInterpolator(Alpha alpha, TransformGroup target,
119: float[] knots) {
120: super (alpha, target);
121: setKnots(knots);
122: }
123:
124: /**
125: * Constructs a new PathInterpolator object that interpolates
126: * between the knot values in the knots array. The array of knots
127: * is copied into this PathInterpolator object.
128: * @param alpha the alpha object for this interpolator.
129: * @param target the transform node effected by this positionInterpolator
130: * @param axisOfTransform the transform that defines the local coordinate
131: * @param knots an array of knot values that specify interpolation
132: * points.
133: *
134: * @since Java 3D 1.3
135: */
136: public PathInterpolator(Alpha alpha, TransformGroup target,
137: Transform3D axisOfTransform, float[] knots) {
138: super (alpha, target, axisOfTransform);
139: setKnots(knots);
140: }
141:
142: /**
143: * Retrieves the length of the knots array.
144: * @return the array length
145: */
146: public int getArrayLengths() {
147: return knots.length;
148: }
149:
150: /**
151: * Sets the knot at the specified index for this interpolator.
152: * @param index the index to be changed
153: * @param knot the new knot value
154: */
155: public void setKnot(int index, float knot) {
156: this .knots[index] = knot;
157: }
158:
159: /**
160: * Retrieves the knot at the specified index.
161: * @param index the index of the value requested
162: * @return the interpolator's knot value at the associated index
163: */
164: public float getKnot(int index) {
165: return this .knots[index];
166: }
167:
168: /**
169: * Replaces the existing array of knot values with
170: * the specified array. The array of knots is copied into this
171: * interpolator object. Prior to calling this method,
172: * subclasses should verify that the lengths of the new knots array
173: * and subclass-specific parameter arrays are the same.
174: * @param knots a new array of knot values that specify
175: * interpolation points.
176: *
177: * @since Java 3D 1.2
178: */
179: protected void setKnots(float[] knots) {
180: if (knots[0] < -0.0001 || knots[0] > 0.0001) {
181: throw new IllegalArgumentException(J3dI18N
182: .getString("PathInterpolator0"));
183: }
184:
185: if ((knots[knots.length - 1] - 1.0f) < -0.0001
186: || (knots[knots.length - 1] - 1.0f) > 0.0001) {
187: throw new IllegalArgumentException(J3dI18N
188: .getString("PathInterpolator1"));
189: }
190:
191: this .knots = new float[knots.length];
192: for (int i = 0; i < knots.length; i++) {
193: if (i > 0 && knots[i] < knots[i - 1]) {
194: throw new IllegalArgumentException(J3dI18N
195: .getString("PathInterpolator2"));
196: }
197: this .knots[i] = knots[i];
198: }
199: }
200:
201: /**
202: * Copies the array of knots from this interpolator
203: * into the specified array.
204: * The array must be large enough to hold all of the knots.
205: * @param knots array that will receive the knots.
206: *
207: * @since Java 3D 1.2
208: */
209: public void getKnots(float[] knots) {
210: for (int i = 0; i < this .knots.length; i++) {
211: knots[i] = this .knots[i];
212: }
213: }
214:
215: /**
216: * Computes the base knot index and interpolation value
217: * given the specified value of alpha and the knots[] array. If
218: * the index is 0 and there should be no interpolation, both the
219: * index variable and the interpolation variable are set to 0.
220: * Otherwise, currentKnotIndex is set to the lower index of the
221: * two bounding knot points and the currentInterpolationValue
222: * variable is set to the ratio of the alpha value between these
223: * two bounding knot points.
224: * @param alphaValue alpha value between 0.0 and 1.0
225: *
226: * @since Java 3D 1.3
227: */
228: protected void computePathInterpolation(float alphaValue) {
229:
230: int i;
231:
232: for (i = 0; i < knots.length; i++) {
233: if ((i == 0 && alphaValue <= knots[i])
234: || (i > 0 && alphaValue >= knots[i - 1] && alphaValue <= knots[i])) {
235:
236: if (i == 0) {
237: currentInterpolationValue = 0f;
238: currentKnotIndex = 0;
239: } else {
240: currentInterpolationValue = (alphaValue - knots[i - 1])
241: / (knots[i] - knots[i - 1]);
242: currentKnotIndex = i - 1;
243: }
244: break;
245: }
246: }
247: }
248:
249: /**
250: * @deprecated As of Java 3D version 1.3, replaced by
251: * <code>computePathInterpolation(float)</code>
252: */
253: protected void computePathInterpolation() {
254: float value = this .alpha.value();
255: computePathInterpolation(value);
256: }
257:
258: /**
259: * Copies all PathInterpolator information from
260: * <code>originalNode</code> into
261: * the current node. This method is called from the
262: * <code>cloneNode</code> method which is, in turn, called by the
263: * <code>cloneTree</code> method.<P>
264: *
265: * @param originalNode the original node to duplicate.
266: * @param forceDuplicate when set to <code>true</code>, causes the
267: * <code>duplicateOnCloneTree</code> flag to be ignored. When
268: * <code>false</code>, the value of each node's
269: * <code>duplicateOnCloneTree</code> variable determines whether
270: * NodeComponent data is duplicated or copied.
271: *
272: * @exception RestrictedAccessException if this object is part of a live
273: * or compiled scenegraph.
274: *
275: * @see Node#duplicateNode
276: * @see Node#cloneTree
277: * @see NodeComponent#setDuplicateOnCloneTree
278: */
279: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
280: super .duplicateAttributes(originalNode, forceDuplicate);
281:
282: PathInterpolator pi = (PathInterpolator) originalNode;
283:
284: int len = pi.getArrayLengths();
285:
286: // No API available to set knots size
287: knots = new float[len];
288:
289: for (int i = 0; i < len; i++)
290: setKnot(i, pi.getKnot(i));
291: }
292: }
|