001: /*
002: * $RCSfile: RotPosScaleTCBSplinePathInterpolator.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:
051: /**
052: * RotPosScaleTCBSplinePathInterpolator behavior. This class defines a
053: * behavior that varies the rotational, translational, and scale components
054: * of its target TransformGroup by using the Kochanek-Bartels cubic spline
055: * interpolation to interpolate among a series of key frames
056: * (using the value generated by the specified Alpha object). The
057: * interpolated position, orientation, and scale are used to generate
058: * a transform in the local coordinate system of this interpolator.
059: *
060: * @since Java3D 1.1
061: */
062:
063: public class RotPosScaleTCBSplinePathInterpolator extends
064: TCBSplinePathInterpolator {
065:
066: private Transform3D rotation = new Transform3D();
067: private Matrix4d tMat = new Matrix4d();
068: private Matrix4d sMat = new Matrix4d();
069: private Quat4f iQuat = new Quat4f(); // interpolated quaternion
070: private Vector3f iPos = new Vector3f(); // interpolated position
071: private Point3f iScale = new Point3f(); // interpolated scale
072:
073: CubicSplineCurve cubicSplineCurve = new CubicSplineCurve();
074: CubicSplineSegment cubicSplineSegments[];
075: int numSegments;
076: int currentSegmentIndex;
077: CubicSplineSegment currentSegment;
078:
079: // non-public, default constructor used by cloneNode
080: RotPosScaleTCBSplinePathInterpolator() {
081: }
082:
083: /**
084: * Constructs a new RotPosScaleTCBSplinePathInterpolator object that
085: * varies the rotation, translation, and scale of the target
086: * TransformGroup's transform. At least 2 key frames are required for
087: * this interpolator. The first key
088: * frame's knot must have a value of 0.0 and the last knot must have a
089: * value of 1.0. An intermediate key frame with index k must have a
090: * knot value strictly greater than the knot value of a key frame with
091: * index less than k.
092: * @param alpha the alpha object for this interpolator
093: * @param target the TransformGroup node affected by this interpolator
094: * @param axisOfTransform the transform that specifies the local
095: * coordinate system in which this interpolator operates.
096: * @param keys an array of key frames that defien the motion path
097: */
098: public RotPosScaleTCBSplinePathInterpolator(Alpha alpha,
099: TransformGroup target, Transform3D axisOfTransform,
100: TCBKeyFrame keys[]) {
101: super (alpha, target, axisOfTransform, keys);
102: // Create a spline curve using the derived key frames
103: cubicSplineCurve = new CubicSplineCurve(this .keyFrames);
104: numSegments = cubicSplineCurve.numSegments;
105:
106: }
107:
108: /**
109: * @deprecated As of Java 3D version 1.3, replaced by
110: * <code>TransformInterpolator.setTransformAxis(Transform3D)</code>
111: */
112: public void setAxisOfRotPosScale(Transform3D axisOfRotPosScale) {
113: setTransformAxis(axisOfRotPosScale);
114: }
115:
116: /**
117: * @deprecated As of Java 3D version 1.3, replaced by
118: * <code>TransformInterpolator.getTransformAxis()</code>
119: */
120: public Transform3D getAxisOfRotPosScale() {
121: return getTransformAxis();
122: }
123:
124: /**
125: * Computes the new transform for this interpolator for a given
126: * alpha value.
127: *
128: * @param alphaValue alpha value between 0.0 and 1.0
129: * @param transform object that receives the computed transform for
130: * the specified alpha value
131: *
132: * @since Java 3D 1.3
133: */
134: public void computeTransform(float alphaValue, Transform3D transform) {
135:
136: // compute the current value of u from alpha and the
137: // determine lower and upper knot points
138: computePathInterpolation(alphaValue);
139:
140: // Determine the segment within which we will be interpolating
141: currentSegmentIndex = this .lowerKnot - 1;
142:
143: // if we are at the start of the curve
144: if (currentSegmentIndex == 0 && currentU == 0f) {
145:
146: iQuat.set(keyFrames[1].quat);
147: iPos.set(keyFrames[1].position);
148: iScale.set(keyFrames[1].scale);
149:
150: // if we are at the end of the curve
151: } else if (currentSegmentIndex == (numSegments - 1)
152: && currentU == 1.0) {
153:
154: iQuat.set(keyFrames[upperKnot].quat);
155: iPos.set(keyFrames[upperKnot].position);
156: iScale.set(keyFrames[upperKnot].scale);
157:
158: // if we are somewhere in between the curve
159: } else {
160:
161: // Get a reference to the current spline segment i.e. the
162: // one bounded by lowerKnot and upperKnot
163: currentSegment = cubicSplineCurve
164: .getSegment(currentSegmentIndex);
165:
166: // interpolate quaternions
167: currentSegment.getInterpolatedQuaternion(currentU, iQuat);
168:
169: // interpolate position
170: currentSegment
171: .getInterpolatedPositionVector(currentU, iPos);
172:
173: // interpolate position
174: currentSegment.getInterpolatedScale(currentU, iScale);
175:
176: }
177:
178: // Alway normalize the quaternion
179: iQuat.normalize();
180: tMat.set(iQuat);
181:
182: // Set the translation components.
183: tMat.m03 = iPos.x;
184: tMat.m13 = iPos.y;
185: tMat.m23 = iPos.z;
186: rotation.set(tMat);
187:
188: // construct a Transform3D from: axis * rotation * axisInverse
189: transform.mul(axis, rotation);
190: transform.setScale(new Vector3d(iScale));
191: transform.mul(transform, axisInverse);
192:
193: }
194:
195: /**
196: * Used to create a new instance of the node. This routine is called
197: * by <code>cloneTree</code> to duplicate the current node.
198: * @param forceDuplicate when set to <code>true</code>, causes the
199: * <code>duplicateOnCloneTree</code> flag to be ignored. When
200: * <code>false</code>, the value of each node's
201: * <code>duplicateOnCloneTree</code> variable determines whether
202: * NodeComponent data is duplicated or copied.
203: *
204: * @see Node#cloneTree
205: * @see Node#cloneNode
206: * @see Node#duplicateNode
207: * @see NodeComponent#setDuplicateOnCloneTree
208: */
209: public Node cloneNode(boolean forceDuplicate) {
210: RotPosScaleTCBSplinePathInterpolator spline = new RotPosScaleTCBSplinePathInterpolator();
211: spline.duplicateNode(this , forceDuplicate);
212: return spline;
213: }
214:
215: /**
216: * Copies RotPosScaleTCBSplinePathInterpolator information from
217: * <code>originalNode</code> into
218: * the current node. This method is called from the
219: * <code>cloneNode</code> method which is, in turn, called by the
220: * <code>cloneTree</code> method.<P>
221: *
222: * @param originalNode the original node to duplicate.
223: * @param forceDuplicate when set to <code>true</code>, causes the
224: * <code>duplicateOnCloneTree</code> flag to be ignored. When
225: * <code>false</code>, the value of each node's
226: * <code>duplicateOnCloneTree</code> variable determines whether
227: * NodeComponent data is duplicated or copied.
228: *
229: * @exception RestrictedAccessException if this object is part of a live
230: * or compiled scenegraph.
231: *
232: * @see Node#duplicateNode
233: * @see Node#cloneTree
234: * @see NodeComponent#setDuplicateOnCloneTree
235: */
236: public void duplicateNode(Node originalNode, boolean forceDuplicate) {
237: super .duplicateNode(originalNode, forceDuplicate);
238: RotPosScaleTCBSplinePathInterpolator interpolator = (RotPosScaleTCBSplinePathInterpolator) originalNode;
239:
240: cubicSplineCurve = new CubicSplineCurve(interpolator.keyFrames);
241: numSegments = cubicSplineCurve.numSegments;
242: }
243: }
|