001: /*
002: * $RCSfile: Transform.java,v $
003: *
004: * @(#)Transform.java 1.57 99/03/15 10:26:40
005: *
006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
007: *
008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
009: * modify and redistribute this software in source and binary code form,
010: * provided that i) this copyright notice and license appear on all copies of
011: * the software; and ii) Licensee does not utilize the software in a manner
012: * which is disparaging to Sun.
013: *
014: * This software is provided "AS IS," without a warranty of any kind. ALL
015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGES.
025: *
026: * This software is not designed or intended for use in on-line control of
027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
028: * the design, construction, operation or maintenance of any nuclear
029: * facility. Licensee represents and warrants that it will not use or
030: * redistribute the Software for such purposes.
031: *
032: * $Revision: 1.2 $
033: * $Date: 2005/02/03 23:07:03 $
034: * $State: Exp $
035: */
036: /*
037: * @Author: Rick Goldberg
038: * @Author: Doug Gehringer
039: *
040: */
041: package org.jdesktop.j3d.loaders.vrml97.impl;
042:
043: import java.util.Vector;
044: import javax.media.j3d.BoundingSphere;
045:
046: import javax.media.j3d.Transform3D;
047: import javax.media.j3d.TransformGroup;
048: import javax.vecmath.AxisAngle4d;
049: import javax.vecmath.Matrix4d;
050: import javax.vecmath.Point3d;
051: import javax.vecmath.Vector3d;
052:
053: /** Description of the Class */
054: public class Transform extends GroupBase {
055:
056: TransformGroup impl;
057:
058: SFVec3f center;
059: SFRotation rotation;
060: SFVec3f scale;
061: SFRotation scaleOrientation;
062: SFVec3f translation;
063:
064: private Transform3D trans1;
065: private Transform3D trans2;
066: private Transform3D trans3;
067: private Transform3D T;
068: private Transform3D C;
069: private Transform3D R;
070: private Transform3D SR;
071: private Transform3D S;
072: private Transform3D P;
073: private boolean pending = false;
074: private Vector3d tempVec;
075: private AxisAngle4d tempAxis;
076:
077: /**
078: *Constructor for the Transform object
079: *
080: *@param loader Description of the Parameter
081: */
082: public Transform(Loader loader) {
083: super (loader);
084: center = new SFVec3f(0.0f, 0.0f, 0.0f);
085: rotation = new SFRotation();
086: scale = new SFVec3f(1.0f, 1.0f, 1.0f);
087: scaleOrientation = new SFRotation();
088: translation = new SFVec3f(0.0f, 0.0f, 0.0f);
089:
090: initTransformFields();
091: }
092:
093: /**
094: *Constructor for the Transform object
095: *
096: *@param loader Description of the Parameter
097: *@param children Description of the Parameter
098: *@param bboxCenter Description of the Parameter
099: *@param bboxSize Description of the Parameter
100: *@param center Description of the Parameter
101: *@param rotation Description of the Parameter
102: *@param scale Description of the Parameter
103: *@param scaleOrientation Description of the Parameter
104: *@param translation Description of the Parameter
105: */
106: Transform(Loader loader, MFNode children, SFVec3f bboxCenter,
107: SFVec3f bboxSize, SFVec3f center, SFRotation rotation,
108: SFVec3f scale, SFRotation scaleOrientation,
109: SFVec3f translation) {
110:
111: super (loader, children, bboxCenter, bboxSize);
112:
113: this .center = center;
114: this .rotation = rotation;
115: this .scale = scale;
116: this .scaleOrientation = scaleOrientation;
117: this .translation = translation;
118:
119: initTransformFields();
120: }
121:
122: /**
123: * Description of the Method
124: *
125: *@param val1 Description of the Parameter
126: *@param val2 Description of the Parameter
127: *@return Description of the Return Value
128: */
129: private boolean floatEq(float val1, float val2) {
130: float diff = val1 - val2;
131: if (diff < 0) {
132: diff *= -1;
133: }
134: if (diff < 0.001) {
135: return true;
136: } else {
137: return false;
138: }
139: }
140:
141: /** Description of the Method */
142: void updateTransform() {
143: //System.out.println(this);
144: // T x C x R x SR x S x -SR x -C
145: if ((browser == null) || browser.pendingTransforms.batchReady) {
146: tempVec.x = -center.value[0];
147: tempVec.y = -center.value[1];
148: tempVec.z = -center.value[2];
149: trans2.setIdentity();
150: trans2.setTranslation(tempVec);
151: //System.out.println("-C "+trans2);
152: float scaleVal = 1.0f;
153: if (floatEq(scale.value[0], scale.value[1])
154: && floatEq(scale.value[0], scale.value[2])) {
155: scaleVal = scale.value[0];
156: trans1.set(scaleVal);
157: //System.out.println("S"+trans1);
158: } else {
159: // non-uniform scale
160: //System.out.println("Non Uniform Scale");
161: tempAxis.x = scaleOrientation.rot[0];
162: tempAxis.y = scaleOrientation.rot[1];
163: tempAxis.z = scaleOrientation.rot[2];
164: tempAxis.angle = -scaleOrientation.rot[3];
165: double tempAxisNormalizer = Math.sqrt(tempAxis.x
166: * tempAxis.x + tempAxis.y * tempAxis.y
167: + tempAxis.z * tempAxis.z);
168: tempAxis.x /= tempAxisNormalizer;
169: tempAxis.y /= tempAxisNormalizer;
170: tempAxis.z /= tempAxisNormalizer;
171:
172: trans1.set(tempAxis);
173: trans3.mul(trans1, trans2);
174: trans1.setNonUniformScale(scale.value[0],
175: scale.value[1], scale.value[2]);
176: trans2.mul(trans1, trans3);
177: tempAxis.x = scaleOrientation.rot[0];
178: tempAxis.y = scaleOrientation.rot[1];
179: tempAxis.z = scaleOrientation.rot[2];
180: tempAxis.angle = scaleOrientation.rot[3];
181: trans1.set(tempAxis);
182: }
183: trans3.mul(trans1, trans2);
184: //System.out.println("Sx-C"+trans3);
185: float magSq = (rotation.rot[0] * rotation.rot[0]
186: + rotation.rot[1] * rotation.rot[1] + rotation.rot[2]
187: * rotation.rot[2]);
188: if (magSq < 0.0001) {
189: // all zeros, use the default
190: // ?? does this still happen
191: tempAxis.x = 0.0;
192: tempAxis.y = 0.0;
193: //tempAxis.y = 1.0;
194: tempAxis.z = 0.0;
195: } else {
196: if ((magSq > 1.01) || (magSq < 0.99)) {
197: float mag = (float) Math.sqrt((double) magSq);
198: tempAxis.x = rotation.rot[0] / mag;
199: tempAxis.y = rotation.rot[1] / mag;
200: tempAxis.z = rotation.rot[2] / mag;
201: } else {
202: tempAxis.x = rotation.rot[0];
203: tempAxis.y = rotation.rot[1];
204: tempAxis.z = rotation.rot[2];
205: }
206: }
207: tempAxis.angle = rotation.rot[3];
208: trans1.set(tempAxis);
209: //System.out.println("R"+trans1);
210: trans2.mul(trans1, trans3);
211: //System.out.println("RxSx-C"+trans2);
212: tempVec.x = center.value[0];
213: tempVec.y = center.value[1];
214: tempVec.z = center.value[2];
215: trans1.setIdentity();
216: trans1.setTranslation(tempVec);
217: //System.out.println("C"+trans1);
218: //trans1.set(1.0, tempVec);
219: trans3.mul(trans1, trans2);
220: //System.out.println("CxRxSx-C"+trans3);
221: tempVec.x = translation.value[0];
222: tempVec.y = translation.value[1];
223: tempVec.z = translation.value[2];
224: trans1.setIdentity();
225: trans1.setTranslation(tempVec);
226: //trans1.set(1.0, tempVec);
227: trans2.mul(trans1, trans3);
228: //System.out.println("TxCxRxSx-C"+trans2);
229:
230: //trans2.normalize();
231:
232: //if(browser.debug)System.out.println(trans2+" "+trans2.getType());
233:
234: try {
235: impl.setTransform(trans2);
236: } catch (javax.media.j3d.BadTransformException bte) {
237: if (browser.debug) {
238: bte.printStackTrace();
239: }
240: } catch (Exception e) {
241: e.printStackTrace();
242: }
243: pending = false;
244: } else {
245: if (pending == false) {
246: pending = true;
247: browser.pendingTransforms.add(this );
248: }
249: }
250: }
251:
252: /** Description of the Method */
253: void initImpl() {
254: impl = new TransformGroup();
255: implGroup = (javax.media.j3d.Group) impl;
256: implNode = impl;
257: impl.setUserData(new Vector());
258: trans1 = new Transform3D();
259: trans2 = new Transform3D();
260: trans3 = new Transform3D();
261: T = new Transform3D();
262: C = new Transform3D();
263: R = new Transform3D();
264: SR = new Transform3D();
265: S = new Transform3D();
266: P = new Transform3D();
267: tempVec = new Vector3d();
268: tempAxis = new AxisAngle4d();
269:
270: // make sure the rotation axis magnitude is non zero
271: if ((rotation.rot[0] == rotation.rot[1])
272: && (rotation.rot[1] == rotation.rot[2])
273: && (rotation.rot[2] == 0.0f)) {
274: rotation.rot[1] = 1.0f;
275: }
276:
277: // and the scale?
278: if ((scale.value[0] == scale.value[1])
279: && (scale.value[0] == scale.value[2])
280: && (scale.value[0] == 0.0f)) {
281: scale.setValue(1.0f, 1.0f, 1.0f);
282: }
283:
284: updateTransform();
285: super .replaceChildren();// init the implGroup for clone()
286: implReady = true;
287: }
288:
289: /**
290: * Description of the Method
291: *
292: *@param eventInName Description of the Parameter
293: *@param time Description of the Parameter
294: */
295: public void notifyMethod(String eventInName, double time) {
296: if (eventInName.equals("rotation")) {
297: updateTransform();
298: } else if (eventInName.equals("scale")
299: || eventInName.equals("scaleOrientation")
300: || eventInName.equals("center")
301: || eventInName.equals("translation")) {
302: updateTransform();
303: } else if (eventInName.equals("route_rotation")
304: || eventInName.equals("route_translation")
305: || eventInName.equals("route_scale")
306: || eventInName.equals("route_center")
307: || eventInName.equals("route_scaleOrientation")) {
308: impl.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
309: impl.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
310: impl
311: .setCapability(javax.media.j3d.Group.ENABLE_PICK_REPORTING);
312: } else {
313: super .notifyMethod(eventInName, time);
314: }
315: }
316:
317: /**
318: * Description of the Method
319: *
320: *@return Description of the Return Value
321: */
322: public Object clone() {
323: if (loader.debug) {
324: System.out.println("Transform.clone() called");
325: }
326: return new Transform(loader, (MFNode) children.clone(),
327: (SFVec3f) bboxCenter.clone(), (SFVec3f) bboxSize
328: .clone(), (SFVec3f) center.clone(),
329: (SFRotation) rotation.clone(), (SFVec3f) scale.clone(),
330: (SFRotation) scaleOrientation.clone(),
331: (SFVec3f) translation.clone());
332: }
333:
334: /**
335: * Gets the type attribute of the Transform object
336: *
337: *@return The type value
338: */
339: public String getType() {
340: return "Transform";
341: }
342:
343: /** Description of the Method */
344: void initFields() {
345: super .initFields();
346: initTransformFields();
347: }
348:
349: /** Description of the Method */
350: void initTransformFields() {
351: center.init(this , FieldSpec, Field.EXPOSED_FIELD, "center");
352: rotation.init(this , FieldSpec, Field.EXPOSED_FIELD, "rotation");
353: scale.init(this , FieldSpec, Field.EXPOSED_FIELD, "scale");
354: scaleOrientation.init(this , FieldSpec, Field.EXPOSED_FIELD,
355: "scaleOrientation");
356: translation.init(this , FieldSpec, Field.EXPOSED_FIELD,
357: "translation");
358: }
359:
360: /**
361: * Description of the Method
362: *
363: *@return Description of the Return Value
364: */
365: public String toStringBodyS() {
366: String retval = "Transform {\n";
367: if ((center.value[0] != 0.0) || (center.value[1] != 0.0)
368: || (center.value[2] != 0.0)) {
369: retval += "center " + center;
370: }
371: if ((rotation.rot[0] != 0.0) || (rotation.rot[1] != 0.0)
372: || (rotation.rot[2] != 1.0) || (rotation.rot[3] != 0.0)) {
373: retval += "rotation " + rotation;
374: }
375: if ((scale.value[0] != 1.0) || (scale.value[1] != 1.0)
376: || (scale.value[2] != 1.0)) {
377: retval += "scale " + scale;
378: }
379: if ((scaleOrientation.rot[0] != 0.0)
380: || (scaleOrientation.rot[1] != 0.0)
381: || (scaleOrientation.rot[2] != 1.0)
382: || (scaleOrientation.rot[3] != 0.0)) {
383: retval += "scaleOrientation " + scaleOrientation;
384: }
385: if ((translation.value[0] != 0.0)
386: || (translation.value[1] != 0.0)
387: || (translation.value[2] != 0.0)) {
388: retval += "translation " + translation;
389: }
390: retval += super .toStringBody();
391: retval += "}";
392: return retval;
393: }
394:
395: }
|