View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.ui.behaviors;
39  
40  import java.awt.AWTEvent;
41  import java.awt.event.MouseEvent;
42  import java.util.Iterator;
43  import org.jogamp.java3d.Transform3D;
44  import org.jogamp.java3d.TransformGroup;
45  import org.jogamp.java3d.WakeupCriterion;
46  import org.jogamp.java3d.WakeupOnAWTEvent;
47  import org.jogamp.vecmath.Matrix4d;
48  import org.jogamp.vecmath.Vector3d;
49  import org.jogamp.vecmath.Vector3f;
50  
51  /**
52   * The MouseOrbit class implements a mouse orbit behavior.
53   *
54   * @author Michael J. Schnieders
55   */
56  public class MouseOrbit extends MouseBehavior {
57  
58    double xAngle, yAngle;
59    double xFactor = 0.01; // .03;
60    double yFactor = 0.01; // .03;
61    private TransformGroup tg_ghost;
62    private MouseBehaviorCallback callback = null;
63  
64    /**
65     * Constructor for MouseOrbit.
66     *
67     * @param flags a int.
68     * @param VPTG a {@link org.jogamp.java3d.TransformGroup} object.
69     */
70    public MouseOrbit(int flags, TransformGroup VPTG) {
71      super(flags, VPTG);
72    }
73  
74    /**
75     * Return the x-axis movement multipler.
76     *
77     * @return a double.
78     */
79    public double getXFactor() {
80      return xFactor;
81    }
82  
83    /**
84     * Return the y-axis movement multipler.
85     *
86     * @return a double.
87     */
88    public double getYFactor() {
89      return yFactor;
90    }
91  
92    /** initialize */
93    public void initialize() {
94      super.initialize();
95      xAngle = 0;
96      yAngle = 0;
97      if ((flags & INVERT_INPUT) == INVERT_INPUT) {
98        invert = true;
99        xFactor *= -1;
100       yFactor *= -1;
101     }
102   }
103 
104   /** {@inheritDoc} */
105   public void processStimulus(Iterator<WakeupCriterion> criteria) {
106     while (criteria.hasNext()) {
107       WakeupCriterion wakeup = criteria.next();
108       if (wakeup instanceof WakeupOnAWTEvent) {
109         AWTEvent[] event = ((WakeupOnAWTEvent) wakeup).getAWTEvent();
110         for (AWTEvent awtEvent : event) {
111           processMouseEvent((MouseEvent) awtEvent);
112           if (((buttonPress) && ((flags & MANUAL_WAKEUP) == 0))
113               || ((wakeUp) && ((flags & MANUAL_WAKEUP) != 0))) {
114             int id = awtEvent.getID();
115             if ((id == MouseEvent.MOUSE_DRAGGED)) {
116               x = ((MouseEvent) awtEvent).getX();
117               y = ((MouseEvent) awtEvent).getY();
118               int dx = x - xLast;
119               int dy = y - yLast;
120               if (!reset) {
121                 Transform3D tempT3D = new Transform3D();
122                 Transform3D orbitT3D = new Transform3D();
123                 tempT3D.rotX(-dy * yFactor);
124                 orbitT3D.mul(tempT3D);
125                 tempT3D.rotY(-dx * xFactor);
126                 orbitT3D.mul(tempT3D);
127                 Transform3D tg_ghost_T3D = new Transform3D();
128                 tg_ghost.getTransform(tg_ghost_T3D);
129                 Vector3f tg_ghost_vec3f = new Vector3f();
130                 tg_ghost_T3D.get(tg_ghost_vec3f);
131                 Matrix4d tg_ghost_mat4d = new Matrix4d();
132                 tg_ghost_T3D.get(tg_ghost_mat4d);
133                 Transform3D VPTG_ghost_T3D_inverted = new Transform3D();
134                 Transform3D VPTG_ghost_T3D_noninverted = new Transform3D();
135                 // (super.ViewerTG).getTransform(VPTG_ghost_T3D_inverted);
136                 ViewerTG.getTransform(VPTG_ghost_T3D_inverted);
137                 // (super.ViewerTG).getTransform(VPTG_ghost_T3D_noninverted);
138                 ViewerTG.getTransform(VPTG_ghost_T3D_noninverted);
139                 VPTG_ghost_T3D_inverted.setTranslation(new Vector3d(0.0, 0.0, 0.0));
140                 VPTG_ghost_T3D_noninverted.setTranslation(new Vector3d(0.0, 0.0, 0.0));
141                 VPTG_ghost_T3D_inverted.invert();
142                 tg_ghost_T3D.mul(VPTG_ghost_T3D_inverted, tg_ghost_T3D);
143                 tg_ghost_T3D.setTranslation(new Vector3d(0.0, 0.0, 0.0));
144                 if (invert) {
145                   tg_ghost_T3D.mul(tg_ghost_T3D, orbitT3D);
146                 } else {
147                   tg_ghost_T3D.mul(orbitT3D, tg_ghost_T3D);
148                 }
149                 tg_ghost_T3D.mul(VPTG_ghost_T3D_noninverted, tg_ghost_T3D);
150                 tg_ghost_T3D.setTranslation(tg_ghost_vec3f);
151                 tg_ghost.setTransform(tg_ghost_T3D);
152                 Transform3D VPTG_ghost_T3D = new Transform3D();
153                 // (super.ViewerTG).getTransform(VPTG_ghost_T3D);
154                 ViewerTG.getTransform(VPTG_ghost_T3D);
155                 Vector3f VPTG_ghost_vec3f = new Vector3f();
156                 VPTG_ghost_T3D.get(VPTG_ghost_vec3f);
157                 Vector3f temp_vec3f = new Vector3f();
158                 temp_vec3f.x = VPTG_ghost_vec3f.x - tg_ghost_vec3f.x;
159                 temp_vec3f.y = VPTG_ghost_vec3f.y - tg_ghost_vec3f.y;
160                 temp_vec3f.z = VPTG_ghost_vec3f.z - tg_ghost_vec3f.z;
161                 VPTG_ghost_T3D.setTranslation(temp_vec3f);
162                 VPTG_ghost_T3D.mul(VPTG_ghost_T3D_inverted, VPTG_ghost_T3D);
163                 if (invert) {
164                   VPTG_ghost_T3D.mul(VPTG_ghost_T3D, orbitT3D);
165                 } else {
166                   VPTG_ghost_T3D.mul(orbitT3D, VPTG_ghost_T3D);
167                 }
168                 VPTG_ghost_T3D.mul(VPTG_ghost_T3D_noninverted, VPTG_ghost_T3D);
169                 VPTG_ghost_T3D.get(temp_vec3f);
170                 temp_vec3f.x = temp_vec3f.x + tg_ghost_vec3f.x;
171                 temp_vec3f.y = temp_vec3f.y + tg_ghost_vec3f.y;
172                 temp_vec3f.z = temp_vec3f.z + tg_ghost_vec3f.z;
173                 VPTG_ghost_T3D.setTranslation(temp_vec3f);
174                 // (super.ViewerTG).setTransform(VPTG_ghost_T3D);
175                 ViewerTG.setTransform(VPTG_ghost_T3D);
176                 transformChanged(currXform);
177                 if (callback != null) {
178                   callback.transformChanged(MouseBehaviorCallback.ORBIT, currXform);
179                 }
180               } else {
181                 reset = false;
182               }
183               xLast = x;
184               yLast = y;
185             } else if (id == MouseEvent.MOUSE_PRESSED) {
186               xLast = ((MouseEvent) awtEvent).getX();
187               yLast = ((MouseEvent) awtEvent).getY();
188             }
189           }
190         }
191       }
192     }
193     wakeupOn(mouseCriterion);
194   }
195 
196   /**
197    * Set the x-axis amd y-axis movement multipler with factor.
198    *
199    * @param factor a double.
200    */
201   public void setFactor(double factor) {
202     xFactor = yFactor = factor;
203   }
204 
205   /**
206    * Set the x-axis amd y-axis movement multipler with xFactor and yFactor respectively.
207    *
208    * @param xFactor a double.
209    * @param yFactor a double.
210    */
211   public void setFactor(double xFactor, double yFactor) {
212     this.xFactor = xFactor;
213     this.yFactor = yFactor;
214   }
215 
216   /**
217    * setTransformGroups
218    *
219    * @param tg a {@link org.jogamp.java3d.TransformGroup} object.
220    * @param VPTG a {@link org.jogamp.java3d.TransformGroup} object.
221    */
222   public void setTransformGroups(TransformGroup tg, TransformGroup VPTG) {
223     super.ViewerTG = VPTG;
224     tg_ghost = new TransformGroup();
225     Transform3D tgT3D = new Transform3D();
226     tg.getTransform(tgT3D);
227     // Make a ghost TG since no transform on object is to occur
228     tg_ghost.setTransform(tgT3D);
229   }
230 
231   /**
232    * The transformChanged method in the callback class will be called every time the transform is
233    * updated
234    *
235    * @param c a {@link ffx.ui.behaviors.MouseBehaviorCallback} object.
236    */
237   public void setupCallback(MouseBehaviorCallback c) {
238     callback = c;
239   }
240 
241   /**
242    * transformChanged
243    *
244    * @param transform a {@link org.jogamp.java3d.Transform3D} object.
245    */
246   public void transformChanged(Transform3D transform) {}
247 }