001: /*
002: * $RCSfile: SphereSensor.java,v $
003: *
004: * @(#)SphereSensor.java 1.27 99/03/01 14:30:43
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:02 $
034: * $State: Exp $
035: */
036: /*
037: * @Author: Rick Goldberg
038: *
039: */
040: package org.jdesktop.j3d.loaders.vrml97.impl;
041:
042: import javax.media.j3d.BoundingSphere;
043: import javax.media.j3d.Bounds;
044:
045: import javax.media.j3d.Transform3D;
046: import javax.media.j3d.TransformGroup;
047: import javax.vecmath.*;
048:
049: /** Description of the Class */
050: public class SphereSensor extends DragSensor {
051:
052: // exposedField
053: SFRotation offset;
054: // experimental
055: SFBool autoSpin;
056: SFInt32 autoSpinFrameWait;
057: SFFloat spinKick;
058:
059: // eventOut
060: SFRotation rotation;
061:
062: // api math objs ( gets from j3d )
063: Transform3D l2vwTf = new Transform3D();// local to vworld
064: Transform3D im2vwTf = new Transform3D();// image plate to vworld
065: Transform3D TTf = new Transform3D();// the xform in question
066: // obtained orig
067: // from getLocalToVworld()
068: // called on the node
069:
070: // vworld math
071: Quat4d T = new Quat4d();
072: Quat4d T_;// don't set until first used, set
073: // null if ever unrouted.
074: Quat4d rot = new Quat4d();
075: Transform3D im2lTf = new Transform3D();
076: Transform3D l2imTf = new Transform3D();
077: Transform3D vw2lTf = new Transform3D();
078:
079: Point3d p1 = new Point3d();
080: Point3d p2 = new Point3d();
081:
082: // track ball math
083: Transform3D rotTf = new Transform3D();
084: AxisAngle4d sfrOffset = new AxisAngle4d();
085: AxisAngle4d sfrR = new AxisAngle4d();
086: AxisAngle4d rotAxAngle = new AxisAngle4d();
087: Vector3d trackpt = new Vector3d();
088: Vector3d v = new Vector3d();
089: Vector3d vlast = new Vector3d();
090: Vector3d t = new Vector3d();
091: Vector3d u = new Vector3d();
092: double a;
093: Bounds bounds;
094: int count = 0;
095: boolean autoSpinning = false;
096: static double EPSILON = .00000001;
097: static double DELTA = .00001;
098:
099: // node references
100: javax.media.j3d.Node node = null;
101: javax.media.j3d.SceneGraphPath path = null;// could be a shared node
102:
103: /**
104: *Constructor for the SphereSensor object
105: *
106: *@param loader Description of the Parameter
107: */
108: public SphereSensor(Loader loader) {
109: super (loader);
110: offset = new SFRotation(0.0f, 1.0f, 0.0f, 0.0f);
111: rotation = new SFRotation(0.0f, 1.0f, 0.0f, 0.0f);
112: sfrOffset.set(offset.rot[0], offset.rot[1], offset.rot[2],
113: offset.rot[3]);
114: sfrR.set(rotation.rot[0], rotation.rot[1], rotation.rot[2],
115: rotation.rot[3]);
116: autoSpin = new SFBool(false);
117: autoSpinFrameWait = new SFInt32(3);
118: spinKick = new SFFloat(10.0f);
119: vlast.x = 0.0;
120: vlast.y = 1.0;
121: vlast.z = 0.0;
122: initSphereSensorFields();
123: }
124:
125: // P1 and P2 are in image plate coordinates and represent the beginning
126: // of the first drag segment and end of the current drag segment, where
127: // a drag segment is defined to be the multiple connected line segments
128: // that make up a complete AWT (or whathaveu)
129: // mousePressed->mouseDragged->mouseReleased action.
130: // nodeIn is supposed to be a TransformGroup(), and it really might not
131: // make sense if the receiver of the route is not in the same space.
132: // However, there may be occaisions that the node is not the TrasformGroup,
133: // in which case it is safe to assume that the offset is I.
134:
135: /**
136: * Description of the Method
137: *
138: *@param p1 Description of the Parameter
139: *@param p2 Description of the Parameter
140: *@param nodeIn Description of the Parameter
141: *@param pathIn Description of the Parameter
142: */
143: void update(Point3d p1, Point3d p2, javax.media.j3d.Node nodeIn,
144: javax.media.j3d.SceneGraphPath pathIn) {
145:
146: double ang;
147:
148: double m;
149: this .p1 = p1;
150: this .p2 = p2;
151:
152: count = autoSpinFrameWait.value;// count default 3 frames before autoSpin
153:
154: // A null path and node means this was expected to have been already set.
155: // not null does not mean that this was the first time to use this sensor,
156: // but the first time during this continuous mouse drag
157:
158: if ((nodeIn != null) && (pathIn != null)) {
159: this .node = nodeIn;
160: this .path = pathIn;
161:
162: if (browser.debug) {
163: // send out the whole path, including the
164: // Locale and "Object"
165: System.out.println(pathIn);
166: int xx;
167: System.out.println(pathIn.getLocale());
168: for (xx = 0; xx < pathIn.nodeCount(); xx++) {
169: System.out.println(pathIn.getNode(xx));
170: }
171: System.out.println(pathIn.getObject());
172: System.out.println("picked node" + node);
173: }
174: aquireTransform(nodeIn);
175:
176: // send the vrml event that this sensor is active
177: isActive.setValue(true);
178:
179: bounds = node.getBounds();
180:
181: } else {
182:
183: // already in a drag, check if currently autoSpinning, if so
184: // set the offset as if a mouse up happend
185:
186: if (autoSpinning) {
187:
188: // unlock the sensor
189: browser.evagation.forceUpDown();
190: aquireTransform(this .node);
191: doUpdate();
192: offset();
193:
194: // place this back
195: browser.evagation.curDragSensor = this ;
196: autoSpinning = false;
197:
198: }
199: }
200: browser.canvas.getImagePlateToVworld(im2vwTf);
201:
202: try {
203: node.getLocalToVworld(l2vwTf);
204: } catch (javax.media.j3d.IllegalSharingException e) {
205: node.getLocalToVworld(path, l2vwTf);
206: } catch (java.lang.NullPointerException npe) {
207: npe.printStackTrace();
208: // todo:why did sphere generate this, but it still works?
209: } catch (javax.media.j3d.CapabilityNotSetException cnse) {
210: /*cnse.printStackTrace()*/
211: ;
212: }
213:
214: // this is the local to vworld of the group, need the children
215: //
216: vw2lTf.invert(l2vwTf);
217: im2lTf.mul(vw2lTf, im2vwTf);
218: im2lTf.transform(p1);
219: im2lTf.transform(p2);
220: t.set(p1);
221: u.set(p2);
222: try {
223: norm(t);
224: norm(u);
225: v.cross(t, u);
226: a = angle(t, u) * coorelate(im2lTf);
227: if (Math.abs(a) > EPSILON) {
228: norm(v);
229: vlast.set(v);
230: } else {
231: v.set(vlast);
232: }
233: } catch (ArithmeticException ae) {
234: System.out.println("dinky delta");
235: }
236:
237: rotAxAngle.set(v.x, v.y, v.z, a);
238: rot.set(rotAxAngle);
239: T_.mul(rot, T);
240: //it'd be nice to have javac or the makefile use cpp
241: //if (browser.debug) {
242: //System.out.println("------------");
243: //System.out.println("P1 "+t);
244: //System.out.println("P2 "+u);
245: //System.out.println("P1xP2 "+v);
246: //System.out.println("x "+v.x+" y "+v.y+" z "+v.z+" a "+a);
247: //System.out.println("rot "+rot);
248: //System.out.println("T "+T);
249: //System.out.println("rot mul T "+T_);
250: //System.out.println("------------");
251: //}
252: doUpdate();
253: }
254:
255: // this is an experimental feature, to enable, uncomment the
256: // simTick call to curDragSensors in Evagation.
257: // its relatively light weight since only once dragSensor can
258: // be active at anyone time
259: /**
260: * Description of the Method
261: *
262: *@param t Description of the Parameter
263: */
264: void simTick(double t) {
265: if (autoSpin.value && (count-- <= 0)) {
266: autoSpinning = true;
267: rotAxAngle.set(v.x, v.y, v.z, rotAxAngle.angle + a);
268: rot.set(rotAxAngle);
269: T_.mul(rot, T);
270: doUpdate();
271: } else {
272: autoSpinning = false;
273: }
274: }
275:
276: /**
277: * Description of the Method
278: *
279: *@param nodeIn Description of the Parameter
280: */
281: void aquireTransform(javax.media.j3d.Node nodeIn) {
282: if (T_ == null) {
283: if (nodeIn instanceof javax.media.j3d.TransformGroup) {
284: ((javax.media.j3d.TransformGroup) nodeIn)
285: .getTransform(TTf);
286: } else {
287: TTf.setIdentity();
288: }
289: T_ = new Quat4d();
290: TTf.get(T);
291: T_.set(T);
292: } else {
293: // update has been called once for this drag
294: T_.get(T);
295: }
296: }
297:
298: /** Description of the Method */
299: void doUpdate() {
300:
301: if (enabled.value) {
302: sfrR.set(T_);
303: rotation.setValue((float) sfrR.x, (float) sfrR.y,
304: (float) sfrR.z, (float) sfrR.angle);
305:
306: // trackPoint is the origninal P2 in local coordinates
307: // componentwise divided by the distance to the origin, multiplied by distance
308: // of initial intersection to the origin; this can be obtained by rigorous
309: // geometry intersection, or just take the boundingSphere radius );
310:
311: trackpt.set(p2);
312: try {
313: norm(trackpt);
314: } catch (ArithmeticException ae) {
315: ;
316: }
317: trackpt.scale(((BoundingSphere) bounds).getRadius());
318:
319: // inherited from DragSensor
320: trackPoint.setValue((float) trackpt.x, (float) trackpt.y,
321: (float) trackpt.z);
322: }
323: }
324:
325: // call this at the end of a mouse drag sequence (mouse up event)
326: // to save the current transformation.
327: /** Description of the Method */
328: public void offset() {
329: // complete the vrml events,
330: isActive.setValue(false);
331:
332: AxisAngle4d sfrO = new AxisAngle4d();
333: sfrO.set(T_);
334:
335: offset.setValue((float) sfrO.x, (float) sfrO.y, (float) sfrO.z,
336: (float) sfrO.angle);
337: count = 0;
338:
339: }
340:
341: /**
342: * Description of the Method
343: *
344: *@param eventInName Description of the Parameter
345: *@param time Description of the Parameter
346: */
347: public void notifyMethod(String eventInName, double time) {
348: if (eventInName.equals("autoSpin")) {
349: if (autoSpinning) {
350: autoSpinning = false;
351: }
352: }
353: }
354:
355: /**
356: * Gets the type attribute of the SphereSensor object
357: *
358: *@return The type value
359: */
360: public String getType() {
361: return "SphereSensor";
362: }
363:
364: /**
365: * Description of the Method
366: *
367: *@return Description of the Return Value
368: */
369: public Object clone() {
370: return new SphereSensor(loader);
371: }
372:
373: /** Description of the Method */
374: void initSphereSensorFields() {
375: offset.init(this , FieldSpec, Field.EXPOSED_FIELD, "offset");
376: rotation.init(this , FieldSpec, Field.EVENT_OUT, "rotation");
377: autoSpin.init(this , FieldSpec, Field.FIELD, "autoSpin");
378: autoSpinFrameWait.init(this , FieldSpec, Field.FIELD,
379: "autoSpinFrameWait");
380: spinKick.init(this , FieldSpec, Field.FIELD, "spinKick");
381:
382: }
383:
384: }
|