001: /*
002: * $RCSfile: PositionPathInterpolator.java,v $
003: *
004: * Copyright 1997-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:28 $
029: * $State: Exp $
030: */
031:
032: package javax.media.j3d;
033:
034: import javax.vecmath.Point3f;
035: import javax.vecmath.Vector3f;
036:
037: /**
038: * PositionPathInterpolator behavior. This class defines a behavior
039: * that modifies the translational component of its target TransformGroup
040: * by linearly interpolating among a series of predefined knot/position
041: * pairs (using the value generated by the specified Alpha object). The
042: * interpolated position is used to generate a translation transform
043: * in the local coordinate system of this interpolator. The first knot
044: * must have a value of 0.0. The last knot must have a value of 1.0. An
045: * intermediate knot with index k must have a value strictly greater
046: * than any knot with index less than k.
047: */
048:
049: public class PositionPathInterpolator extends PathInterpolator {
050: private Transform3D position = new Transform3D();
051: private Vector3f pos = new Vector3f();
052:
053: // Array of positions at each knot
054: private Point3f positions[];
055: private float prevInterpolationValue = Float.NaN;
056:
057: // We can't use a boolean flag since it is possible
058: // that after alpha change, this procedure only run
059: // once at alpha.finish(). So the best way is to
060: // detect alpha value change.
061: private float prevAlphaValue = Float.NaN;
062: private WakeupCriterion passiveWakeupCriterion = (WakeupCriterion) new WakeupOnElapsedFrames(
063: 0, true);
064:
065: // non-public, default constructor used by cloneNode
066: PositionPathInterpolator() {
067: }
068:
069: /**
070: * Constructs a new PositionPathInterpolator that varies the transform
071: * of the target TransformGroup.
072: * @param alpha the alpha object for this interpolator
073: * @param target the TransformGroup node affected by this translator
074: * @param axisOfTransform the transform that defines the local
075: * coordinate system in which this interpolator operates
076: * @param knots an array of knot values that specify interpolation points.
077: * @param positions an array of position values at the knots.
078: * @exception IllegalArgumentException if the lengths of the
079: * knots and positions arrays are not the same.
080: */
081: public PositionPathInterpolator(Alpha alpha, TransformGroup target,
082: Transform3D axisOfTransform, float[] knots,
083: Point3f[] positions) {
084:
085: super (alpha, target, axisOfTransform, knots);
086:
087: if (knots.length != positions.length)
088: throw new IllegalArgumentException(J3dI18N
089: .getString("PositionPathInterpolator0"));
090: setPathArrays(positions);
091: }
092:
093: /**
094: * Sets the position at the specified index for this
095: * interpolator.
096: * @param index the index of the position to be changed
097: * @param position the new position at the index
098: */
099: public void setPosition(int index, Point3f position) {
100: this .positions[index].set(position);
101: }
102:
103: /**
104: * Retrieves the position value at the specified index.
105: * @param index the index of the value requested
106: * @param position the variable to receive the position value at
107: * the specified index
108: */
109: public void getPosition(int index, Point3f position) {
110: position.set(this .positions[index]);
111: }
112:
113: /**
114: * Replaces the existing arrays of knot values
115: * and position values with the specified arrays.
116: * The arrays of knots and positions are copied
117: * into this interpolator object.
118: * @param knots a new array of knot values that specify
119: * interpolation points
120: * @param positions a new array of position values at the knots
121: * @exception IllegalArgumentException if the lengths of the
122: * knots and positions arrays are not the same.
123: *
124: * @since Java 3D 1.2
125: */
126: public void setPathArrays(float[] knots, Point3f[] positions) {
127:
128: if (knots.length != positions.length)
129: throw new IllegalArgumentException(J3dI18N
130: .getString("PositionPathInterpolator0"));
131:
132: setKnots(knots);
133: setPathArrays(positions);
134: }
135:
136: // Set the specific arrays for this path interpolator
137: private void setPathArrays(Point3f[] positions) {
138:
139: this .positions = new Point3f[positions.length];
140: for (int i = 0; i < positions.length; i++) {
141: this .positions[i] = new Point3f();
142: this .positions[i].set(positions[i]);
143: }
144: }
145:
146: /**
147: * Copies the array of position values from this interpolator
148: * into the specified array.
149: * The array must be large enough to hold all of the positions.
150: * The individual array elements must be allocated by the caller.
151: * @param positions array that will receive the positions
152: *
153: * @since Java 3D 1.2
154: */
155: public void getPositions(Point3f[] positions) {
156: for (int i = 0; i < this .positions.length; i++) {
157: positions[i].set(this .positions[i]);
158: }
159: }
160:
161: /**
162: * @deprecated As of Java 3D version 1.3, replaced by
163: * <code>TransformInterpolator.setTransformAxis(Transform3D)</code>
164: */
165: public void setAxisOfTranslation(Transform3D axisOfTranslation) {
166: setTransformAxis(axisOfTranslation);
167: }
168:
169: /**
170: * @deprecated As of Java 3D version 1.3, replaced by
171: * <code>TransformInterpolator.getTransformAxis()</code>
172: */
173: public Transform3D getAxisOfTranslation() {
174: return getTransformAxis();
175: }
176:
177: /**
178: * Computes the new transform for this interpolator for a given
179: * alpha value.
180: *
181: * @param alphaValue alpha value between 0.0 and 1.0
182: * @param transform object that receives the computed transform for
183: * the specified alpha value
184: *
185: * @since Java 3D 1.3
186: */
187: public void computeTransform(float alphaValue, Transform3D transform) {
188:
189: computePathInterpolation(alphaValue);
190:
191: if (currentKnotIndex == 0 && currentInterpolationValue == 0f) {
192: pos.x = positions[0].x;
193: pos.y = positions[0].y;
194: pos.z = positions[0].z;
195: } else {
196: pos.x = positions[currentKnotIndex].x
197: + (positions[currentKnotIndex + 1].x - positions[currentKnotIndex].x)
198: * currentInterpolationValue;
199: pos.y = positions[currentKnotIndex].y
200: + (positions[currentKnotIndex + 1].y - positions[currentKnotIndex].y)
201: * currentInterpolationValue;
202: pos.z = positions[currentKnotIndex].z
203: + (positions[currentKnotIndex + 1].z - positions[currentKnotIndex].z)
204: * currentInterpolationValue;
205: }
206: position.setIdentity();
207: position.setTranslation(pos);
208:
209: // construct a Transform3D from: axis * position * axisInverse
210: transform.mul(axis, position);
211: transform.mul(transform, axisInverse);
212: }
213:
214: /**
215: * Used to create a new instance of the node. This routine is called
216: * by <code>cloneTree</code> to duplicate the current node.
217: * @param forceDuplicate when set to <code>true</code>, causes the
218: * <code>duplicateOnCloneTree</code> flag to be ignored. When
219: * <code>false</code>, the value of each node's
220: * <code>duplicateOnCloneTree</code> variable determines whether
221: * NodeComponent data is duplicated or copied.
222: *
223: * @see Node#cloneTree
224: * @see Node#cloneNode
225: * @see Node#duplicateNode
226: * @see NodeComponent#setDuplicateOnCloneTree
227: */
228: public Node cloneNode(boolean forceDuplicate) {
229: PositionPathInterpolator ppi = new PositionPathInterpolator();
230: ppi.duplicateNode(this , forceDuplicate);
231: return ppi;
232: }
233:
234: /**
235: * Copies all PositionPathInterpolator information from
236: * <code>originalNode</code> into
237: * the current node. This method is called from the
238: * <code>cloneNode</code> method which is, in turn, called by the
239: * <code>cloneTree</code> method.<P>
240: *
241: * @param originalNode the original node to duplicate.
242: * @param forceDuplicate when set to <code>true</code>, causes the
243: * <code>duplicateOnCloneTree</code> flag to be ignored. When
244: * <code>false</code>, the value of each node's
245: * <code>duplicateOnCloneTree</code> variable determines whether
246: * NodeComponent data is duplicated or copied.
247: *
248: * @exception RestrictedAccessException if this object is part of a live
249: * or compiled scenegraph.
250: *
251: * @see Node#duplicateNode
252: * @see Node#cloneTree
253: * @see NodeComponent#setDuplicateOnCloneTree
254: */
255: void duplicateAttributes(Node originalNode, boolean forceDuplicate) {
256: super .duplicateAttributes(originalNode, forceDuplicate);
257:
258: PositionPathInterpolator pi = (PositionPathInterpolator) originalNode;
259:
260: int len = pi.getArrayLengths();
261:
262: // No API available to set the size of positions
263: positions = new Point3f[len];
264:
265: Point3f dupPoint = new Point3f();
266: for (int i = 0; i < len; i++) {
267: positions[i] = new Point3f();
268: pi.getPosition(i, dupPoint);
269: setPosition(i, dupPoint);
270: }
271: }
272: }
|