001: package ch.aecii.j3d.utils;
002:
003: import java.awt.AWTEvent;
004: import java.awt.Component;
005: import java.awt.event.MouseEvent;
006: import java.util.Enumeration;
007:
008: import javax.media.j3d.Transform3D;
009: import javax.media.j3d.TransformGroup;
010: import javax.media.j3d.WakeupCriterion;
011: import javax.media.j3d.WakeupOnAWTEvent;
012: import javax.media.j3d.WakeupOnBehaviorPost;
013: import javax.vecmath.Matrix4d;
014: import javax.vecmath.Vector3d;
015:
016: import com.sun.j3d.utils.behaviors.mouse.MouseBehavior;
017: import com.sun.j3d.utils.behaviors.mouse.MouseBehaviorCallback;
018:
019: /**
020: * Extends the MouseRotate from Java3D so that one can specifiy around which axis the rotation should be done.
021: * (Most of the code is copied from MouseRotate)
022: *
023: * @author sg
024: * @version 1.0
025: */
026: public class ExtendedMouseRotate extends MouseBehavior {
027: private double x_angle;
028: private double y_angle;
029: private double x_factor = .03;
030: private double y_factor = .03;
031:
032: //Added for extended Beahviuor
033: public static final int MODE_ALL = 0;
034: //Added for extended Beahviuor
035: public static final int MODE_X = 1;
036: //Added for extended Beahviuor
037: public static final int MODE_Y = 2;
038: //Added for extended Beahviuor
039: public static final int MODE_Z = 3;
040:
041: private int mode = MODE_ALL;
042:
043: //Just create one instance (performance) changed for extended behaviout
044: private Matrix4d mat = new Matrix4d();
045: private Vector3d translation = new Vector3d();
046: private Transform3D transformZ = new Transform3D();
047:
048: private MouseBehaviorCallback callback = null;
049:
050: /**
051: * Creates a rotate behavior given the transform group.
052: *
053: * @param transformGroup
054: * The transformGroup to operate on.
055: */
056: public ExtendedMouseRotate(TransformGroup transformGroup) {
057: super (transformGroup);
058: }
059:
060: /**
061: * Creates a default mouse rotate behavior.
062: */
063: public ExtendedMouseRotate() {
064: super (0);
065: }
066:
067: /**
068: * Creates a rotate behavior. Note that this behavior still needs a
069: * transform group to work on (use setTransformGroup(tg)) and the transform
070: * group must add this behavior.
071: *
072: * @param flags
073: * interesting flags (wakeup conditions).
074: */
075: public ExtendedMouseRotate(int flags) {
076: super (flags);
077: }
078:
079: /**
080: * Creates a rotate behavior that uses AWT listeners and behavior posts
081: * rather than WakeupOnAWTEvent. The behavior is added to the specified
082: * Component. A null component can be passed to specify the behavior should
083: * use listeners. Components can then be added to the behavior with the
084: * addListener(Component c) method.
085: *
086: * @param c
087: * The Component to add the MouseListener and MouseMotionListener
088: * to.
089: * @since Java 3D 1.2.1
090: */
091: public ExtendedMouseRotate(Component c) {
092: super (c, 0);
093: }
094:
095: /**
096: * Creates a rotate behavior that uses AWT listeners and behavior posts
097: * rather than WakeupOnAWTEvent. The behaviors is added to the specified
098: * Component and works on the given TransformGroup. A null component can be
099: * passed to specify the behavior should use listeners. Components can then
100: * be added to the behavior with the addListener(Component c) method.
101: *
102: * @param c
103: * The Component to add the MouseListener and MouseMotionListener
104: * to.
105: * @param transformGroup
106: * The TransformGroup to operate on.
107: * @since Java 3D 1.2.1
108: */
109: public ExtendedMouseRotate(Component c,
110: TransformGroup transformGroup) {
111: super (c, transformGroup);
112: }
113:
114: /**
115: * Creates a rotate behavior that uses AWT listeners and behavior posts
116: * rather than WakeupOnAWTEvent. The behavior is added to the specified
117: * Component. A null component can be passed to specify the behavior should
118: * use listeners. Components can then be added to the behavior with the
119: * addListener(Component c) method. Note that this behavior still needs a
120: * transform group to work on (use setTransformGroup(tg)) and the transform
121: * group must add this behavior.
122: *
123: * @param flags
124: * interesting flags (wakeup conditions).
125: * @since Java 3D 1.2.1
126: */
127: public ExtendedMouseRotate(Component c, int flags) {
128: super (c, flags);
129: }
130:
131: public void initialize() {
132: super .initialize();
133: x_angle = 0;
134: y_angle = 0;
135: if ((flags & INVERT_INPUT) == INVERT_INPUT) {
136: invert = true;
137: x_factor *= -1;
138: y_factor *= -1;
139: }
140: }
141:
142: /**
143: * Return the x-axis movement multipler.
144: */
145: public double getXFactor() {
146: return x_factor;
147: }
148:
149: /**
150: * Return the y-axis movement multipler.
151: */
152: public double getYFactor() {
153: return y_factor;
154: }
155:
156: /**
157: * Set the x-axis amd y-axis movement multipler with factor.
158: */
159: public void setFactor(double factor) {
160: x_factor = y_factor = factor;
161: }
162:
163: /**
164: * Set the x-axis amd y-axis movement multipler with xFactor and yFactor
165: * respectively.
166: */
167: public void setFactor(double xFactor, double yFactor) {
168: x_factor = xFactor;
169: y_factor = yFactor;
170: }
171:
172: public void processStimulus(Enumeration criteria) {
173: WakeupCriterion wakeup;
174: AWTEvent[] events;
175: MouseEvent evt;
176: // int id;
177: // int dx, dy;
178:
179: while (criteria.hasMoreElements()) {
180: wakeup = (WakeupCriterion) criteria.nextElement();
181: if (wakeup instanceof WakeupOnAWTEvent) {
182: events = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
183: if (events.length > 0) {
184: evt = (MouseEvent) events[events.length - 1];
185: doProcess(evt);
186: }
187: }
188:
189: else if (wakeup instanceof WakeupOnBehaviorPost) {
190: while (true) {
191: // access to the queue must be synchronized
192: synchronized (mouseq) {
193: if (mouseq.isEmpty())
194: break;
195: evt = (MouseEvent) mouseq.remove(0);
196: // consolidate MOUSE_DRAG events
197: while ((evt.getID() == MouseEvent.MOUSE_DRAGGED)
198: && !mouseq.isEmpty()
199: && (((MouseEvent) mouseq.get(0))
200: .getID() == MouseEvent.MOUSE_DRAGGED)) {
201: evt = (MouseEvent) mouseq.remove(0);
202: }
203: }
204: doProcess(evt);
205: }
206: }
207:
208: }
209: wakeupOn(mouseCriterion);
210: }
211:
212: void doProcess(MouseEvent evt) {
213: int id;
214: int dx, dy;
215:
216: processMouseEvent(evt);
217: if (((buttonPress) && ((flags & MANUAL_WAKEUP) == 0))
218: || ((wakeUp) && ((flags & MANUAL_WAKEUP) != 0))) {
219: id = evt.getID();
220: if ((id == MouseEvent.MOUSE_DRAGGED) && !evt.isMetaDown()
221: && !evt.isAltDown()) {
222: x = evt.getX();
223: y = evt.getY();
224:
225: dx = x - x_last;
226: dy = y - y_last;
227:
228: if (!reset) {
229: x_angle = dy * y_factor;
230: y_angle = dx * x_factor;
231:
232: transformGroup.getTransform(currXform);
233:
234: // Remember old matrix
235: currXform.get(mat);
236:
237: // Translate to origin
238: currXform
239: .setTranslation(new Vector3d(0.0, 0.0, 0.0));
240:
241: //Added for extended behaviour
242: switch (mode) {
243: case MODE_ALL:
244: transformX.rotX(x_angle);
245: transformY.rotY(y_angle);
246: if (invert) {
247: currXform.mul(currXform, transformX);
248: currXform.mul(currXform, transformY);
249: } else {
250: currXform.mul(transformX, currXform);
251: currXform.mul(transformY, currXform);
252: }
253: break;
254: case MODE_X:
255: transformX.rotX(x_angle);
256: if (invert) {
257: currXform.mul(currXform, transformX);
258: } else {
259: currXform.mul(transformX, currXform);
260: }
261: break;
262: case MODE_Y:
263: transformY.rotY(x_angle);
264: if (invert) {
265: currXform.mul(currXform, transformY);
266: } else {
267: currXform.mul(transformY, currXform);
268: }
269: break;
270: case MODE_Z:
271: transformZ.rotZ(x_angle);
272: if (invert) {
273: currXform.mul(currXform, transformZ);
274: } else {
275: currXform.mul(transformZ, currXform);
276: }
277: break;
278: }
279:
280: // Set old translation back
281: translation.set(mat.m03, mat.m13, mat.m23);
282: currXform.setTranslation(translation);
283:
284: // Update xform
285: transformGroup.setTransform(currXform);
286:
287: transformChanged(currXform);
288:
289: if (callback != null)
290: callback
291: .transformChanged(
292: MouseBehaviorCallback.ROTATE,
293: currXform);
294: } else {
295: reset = false;
296: }
297:
298: x_last = x;
299: y_last = y;
300: } else if (id == MouseEvent.MOUSE_PRESSED) {
301: x_last = evt.getX();
302: y_last = evt.getY();
303: }
304: }
305: }
306:
307: /**
308: * Users can overload this method which is called every time
309: * the Behavior updates the transform
310: *
311: * Default implementation does nothing
312: */
313: public void transformChanged(Transform3D transform) {
314: }
315:
316: /**
317: * The transformChanged method in the callback class will
318: * be called every time the transform is updated
319: */
320: public void setupCallback(MouseBehaviorCallback callback) {
321: this .callback = callback;
322: }
323:
324: /**
325: * Gets the mode
326: * @return the mode the MouseRotate is in
327: */
328: public int getMode() {
329: return mode;
330: }
331:
332: /**
333: * Set the mode of this MoudeRotate.
334: * Must be one of MODE_ALL, MODE_X, MMODE_Y, ODE_Z else an IllegalArgumentException is thrown.
335: * @param mode
336: */
337: public void setMode(int mode) {
338: if (mode > 3 || mode < 0)
339: throw new IllegalArgumentException("Unknow mode: " + mode);
340: this.mode = mode;
341: }
342: }
|