001 /* 002 * $RCSfile: MouseRotate.java,v $ 003 * 004 * Copyright (c) 2004 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.1 $ 041 * $Date: 2004/06/09 04:10:24 $ 042 * $State: Exp $ 043 */ 044 045 package com.appearance3Dchooser; 046 047 import java.awt.*; 048 import java.awt.event.*; 049 import java.util.*; 050 051 import com.sun.j3d.utils.behaviors.mouse.*; 052 import javax.media.j3d.*; 053 import javax.vecmath.*; 054 055 /** 056 * MouseRotate is a Java3D behavior object that lets users control the 057 * rotation of an object via a mouse. 058 * <p> 059 * To use this utility, first create a transform group that this 060 * rotate behavior will operate on. Then, 061 *<blockquote><pre> 062 * 063 * MouseRotate behavior = new MouseRotate(); 064 * behavior.setTransformGroup(objTrans); 065 * objTrans.addChild(behavior); 066 * behavior.setSchedulingBounds(bounds); 067 * 068 *</pre></blockquote> 069 * The above code will add the rotate behavior to the transform 070 * group. The user can rotate any object attached to the objTrans. 071 */ 072 073 public class CustomMouseRotate extends MouseRotate { 074 double x_angle, y_angle; 075 double x_factor = .03; 076 double y_factor = .03; 077 078 private MouseBehaviorCallback callback = null; 079 080 private Canvas3D haut, droite, gauche, face, big = null; 081 082 // Definit une rotation autour de l'axe Z (repere absolu) 083 private Transform3D transformZ = null; 084 085 /** 086 * Creates a rotate behavior given the transform group. 087 * @param transformGroup The transformGroup to operate on. 088 */ 089 public CustomMouseRotate(TransformGroup transformGroup, 090 Canvas3D haut, Canvas3D droite, 091 Canvas3D gauche, Canvas3D face, 092 Canvas3D big 093 ) { 094 super(transformGroup); 095 this.haut = haut; 096 this.droite = droite; 097 this.gauche = gauche; 098 this.face = face; 099 this.big = big; 100 101 transformZ = new Transform3D(); 102 } 103 104 /** 105 * Creates a default mouse rotate behavior. 106 **/ 107 public CustomMouseRotate() { 108 super(0); 109 } 110 111 /** 112 * Creates a rotate behavior. 113 * Note that this behavior still needs a transform 114 * group to work on (use setTransformGroup(tg)) and 115 * the transform group must add this behavior. 116 * @param flags interesting flags (wakeup conditions). 117 */ 118 public CustomMouseRotate(int flags) { 119 super(flags); 120 } 121 122 /** 123 * Creates a rotate behavior that uses AWT listeners and behavior 124 * posts rather than WakeupOnAWTEvent. The behavior is added to the 125 * specified Component. A null component can be passed to specify 126 * the behavior should use listeners. Components can then be added 127 * to the behavior with the addListener(Component c) method. 128 * @param c The Component to add the MouseListener 129 * and MouseMotionListener to. 130 * @since Java 3D 1.2.1 131 */ 132 public CustomMouseRotate(Component c) { 133 super(c, 0); 134 } 135 136 /** 137 * Creates a rotate behavior that uses AWT listeners and behavior 138 * posts rather than WakeupOnAWTEvent. The behaviors is added to 139 * the specified Component and works on the given TransformGroup. 140 * A null component can be passed to specify the behavior should use 141 * listeners. Components can then be added to the behavior with the 142 * addListener(Component c) method. 143 * @param c The Component to add the MouseListener and 144 * MouseMotionListener to. 145 * @param transformGroup The TransformGroup to operate on. 146 * @since Java 3D 1.2.1 147 */ 148 public CustomMouseRotate(Component c, TransformGroup transformGroup) { 149 super(c, transformGroup); 150 } 151 152 /** 153 * Creates a rotate behavior that uses AWT listeners and behavior 154 * posts rather than WakeupOnAWTEvent. The behavior is added to the 155 * specified Component. A null component can be passed to specify 156 * the behavior should use listeners. Components can then be added to 157 * the behavior with the addListener(Component c) method. 158 * Note that this behavior still needs a transform 159 * group to work on (use setTransformGroup(tg)) and the transform 160 * group must add this behavior. 161 * @param flags interesting flags (wakeup conditions). 162 * @since Java 3D 1.2.1 163 */ 164 public CustomMouseRotate(Component c, int flags) { 165 super(c, flags); 166 } 167 168 public void initialize() { 169 super.initialize(); 170 x_angle = 0; 171 y_angle = 0; 172 if ((flags & INVERT_INPUT) == INVERT_INPUT) { 173 invert = true; 174 x_factor *= -1; 175 y_factor *= -1; 176 } 177 } 178 179 /** 180 * Return the x-axis movement multipler. 181 **/ 182 public double getXFactor() { 183 return x_factor; 184 } 185 186 /** 187 * Return the y-axis movement multipler. 188 **/ 189 public double getYFactor() { 190 return y_factor; 191 } 192 193 194 /** 195 * Set the x-axis amd y-axis movement multipler with factor. 196 **/ 197 public void setFactor( double factor) { 198 x_factor = y_factor = factor; 199 } 200 201 /** 202 * Set the x-axis amd y-axis movement multipler with xFactor and yFactor 203 * respectively. 204 **/ 205 public void setFactor( double xFactor, double yFactor) { 206 x_factor = xFactor; 207 y_factor = yFactor; 208 } 209 210 public void processStimulus (Enumeration criteria) { 211 WakeupCriterion wakeup; 212 AWTEvent[] events; 213 MouseEvent evt; 214 // int id; 215 // int dx, dy; 216 217 while (criteria.hasMoreElements()) { 218 wakeup = (WakeupCriterion) criteria.nextElement(); 219 if (wakeup instanceof WakeupOnAWTEvent) { 220 events = ((WakeupOnAWTEvent)wakeup).getAWTEvent(); 221 if (events.length > 0) { 222 evt = (MouseEvent) events[events.length-1]; 223 doProcess(evt); 224 } 225 } 226 227 else if (wakeup instanceof WakeupOnBehaviorPost) { 228 while (true) { 229 // access to the queue must be synchronized 230 synchronized (mouseq) { 231 if (mouseq.isEmpty()) break; 232 evt = (MouseEvent)mouseq.remove(0); 233 // consolidate MOUSE_DRAG events 234 while ((evt.getID() == MouseEvent.MOUSE_DRAGGED) && 235 !mouseq.isEmpty() && 236 (((MouseEvent)mouseq.get(0)).getID() == 237 MouseEvent.MOUSE_DRAGGED)) { 238 evt = (MouseEvent)mouseq.remove(0); 239 } 240 } 241 doProcess(evt); 242 } 243 } 244 245 } 246 wakeupOn (mouseCriterion); 247 } 248 249 void doProcess(MouseEvent evt) { 250 int id; 251 int dx, dy; 252 253 processMouseEvent(evt); 254 if (((buttonPress)&&((flags & MANUAL_WAKEUP) == 0)) || 255 ((wakeUp)&&((flags & MANUAL_WAKEUP) != 0))) { 256 id = evt.getID(); 257 if ((id == MouseEvent.MOUSE_DRAGGED) && 258 !evt.isMetaDown() && ! evt.isAltDown()){ 259 x = evt.getX(); 260 y = evt.getY(); 261 262 dx = x - x_last; 263 dy = y - y_last; 264 265 if (!reset){ 266 x_angle = dy * y_factor; 267 y_angle = dx * x_factor; 268 269 // Transformations specifiques a chaque canvas 3D 270 if (evt.getSource().equals(haut)) { 271 transformX.rotX(x_angle); 272 transformY.setIdentity(); 273 transformZ.rotZ(-y_angle); 274 } 275 else if (evt.getSource().equals(droite)) { 276 transformX.setIdentity(); 277 transformY.rotY(y_angle); 278 transformZ.rotZ(-x_angle); 279 } 280 else if (evt.getSource().equals(gauche)) { 281 transformX.setIdentity(); 282 transformY.rotY(y_angle); 283 transformZ.rotZ(x_angle); 284 } 285 else if (evt.getSource().equals(face)) { 286 transformX.rotX(x_angle); 287 transformY.rotY(y_angle); 288 transformZ.setIdentity(); 289 } 290 else if (evt.getSource().equals(big)) { 291 transformX.rotX(x_angle); 292 transformY.rotY(y_angle); 293 transformZ.setIdentity(); 294 } 295 296 transformGroup.getTransform(currXform); 297 298 Matrix4d mat = new Matrix4d(); 299 // Remember old matrix 300 currXform.get(mat); 301 302 // Translate to origin 303 currXform.setTranslation(new Vector3d(0.0,0.0,0.0)); 304 if (invert) { 305 currXform.mul(currXform, transformX); 306 currXform.mul(currXform, transformY); 307 currXform.mul(currXform, transformZ); 308 } else { 309 currXform.mul(transformX, currXform); 310 currXform.mul(transformY, currXform); 311 currXform.mul(transformZ, currXform); 312 } 313 314 // Set old translation back 315 Vector3d translation = new 316 Vector3d(mat.m03, mat.m13, mat.m23); 317 currXform.setTranslation(translation); 318 319 // Update xform 320 transformGroup.setTransform(currXform); 321 322 transformChanged( currXform ); 323 324 if (callback!=null) 325 callback.transformChanged( MouseBehaviorCallback.ROTATE, 326 currXform ); 327 } 328 else { 329 reset = false; 330 } 331 332 x_last = x; 333 y_last = y; 334 } 335 else if (id == MouseEvent.MOUSE_PRESSED) { 336 x_last = evt.getX(); 337 y_last = evt.getY(); 338 } 339 } 340 } 341 342 /** 343 * Users can overload this method which is called every time 344 * the Behavior updates the transform 345 * 346 * Default implementation does nothing 347 */ 348 public void transformChanged( Transform3D transform ) { 349 } 350 351 352 /** 353 * The transformChanged method in the callback class will 354 * be called every time the transform is updated 355 */ 356 public void setupCallback( MouseBehaviorCallback callback ) { 357 this.callback = callback; 358 } 359 }