• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2012 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package com.jme3.input;
33 
34 import com.jme3.export.InputCapsule;
35 import com.jme3.export.JmeExporter;
36 import com.jme3.export.JmeImporter;
37 import com.jme3.export.OutputCapsule;
38 import com.jme3.input.controls.*;
39 import com.jme3.math.FastMath;
40 import com.jme3.math.Vector3f;
41 import com.jme3.renderer.Camera;
42 import com.jme3.renderer.RenderManager;
43 import com.jme3.renderer.ViewPort;
44 import com.jme3.scene.Spatial;
45 import com.jme3.scene.control.Control;
46 import java.io.IOException;
47 
48 /**
49  * A camera that follows a spatial and can turn around it by dragging the mouse
50  * @author nehon
51  */
52 public class ChaseCamera implements ActionListener, AnalogListener, Control {
53 
54     protected Spatial target = null;
55     protected float minVerticalRotation = 0.00f;
56     protected float maxVerticalRotation = FastMath.PI / 2;
57     protected float minDistance = 1.0f;
58     protected float maxDistance = 40.0f;
59     protected float distance = 20;
60     protected float zoomSpeed = 2f;
61     protected float rotationSpeed = 1.0f;
62     protected float rotation = 0;
63     protected float trailingRotationInertia = 0.05f;
64     protected float zoomSensitivity = 5f;
65     protected float rotationSensitivity = 5f;
66     protected float chasingSensitivity = 5f;
67     protected float trailingSensitivity = 0.5f;
68     protected float vRotation = FastMath.PI / 6;
69     protected boolean smoothMotion = false;
70     protected boolean trailingEnabled = true;
71     protected float rotationLerpFactor = 0;
72     protected float trailingLerpFactor = 0;
73     protected boolean rotating = false;
74     protected boolean vRotating = false;
75     protected float targetRotation = rotation;
76     protected InputManager inputManager;
77     protected Vector3f initialUpVec;
78     protected float targetVRotation = vRotation;
79     protected float vRotationLerpFactor = 0;
80     protected float targetDistance = distance;
81     protected float distanceLerpFactor = 0;
82     protected boolean zooming = false;
83     protected boolean trailing = false;
84     protected boolean chasing = false;
85     protected boolean canRotate;
86     protected float offsetDistance = 0.002f;
87     protected Vector3f prevPos;
88     protected boolean targetMoves = false;
89     protected boolean enabled = true;
90     protected Camera cam = null;
91     protected final Vector3f targetDir = new Vector3f();
92     protected float previousTargetRotation;
93     protected final Vector3f pos = new Vector3f();
94     protected Vector3f targetLocation = new Vector3f(0, 0, 0);
95     protected boolean dragToRotate = true;
96     protected Vector3f lookAtOffset = new Vector3f(0, 0, 0);
97     protected boolean leftClickRotate = true;
98     protected boolean rightClickRotate = true;
99     protected Vector3f temp = new Vector3f(0, 0, 0);
100     protected boolean invertYaxis = false;
101     protected boolean invertXaxis = false;
102     protected final static String ChaseCamDown = "ChaseCamDown";
103     protected final static String ChaseCamUp = "ChaseCamUp";
104     protected final static String ChaseCamZoomIn = "ChaseCamZoomIn";
105     protected final static String ChaseCamZoomOut = "ChaseCamZoomOut";
106     protected final static String ChaseCamMoveLeft = "ChaseCamMoveLeft";
107     protected final static String ChaseCamMoveRight = "ChaseCamMoveRight";
108     protected final static String ChaseCamToggleRotate = "ChaseCamToggleRotate";
109 
110     /**
111      * Constructs the chase camera
112      * @param cam the application camera
113      * @param target the spatial to follow
114      */
ChaseCamera(Camera cam, final Spatial target)115     public ChaseCamera(Camera cam, final Spatial target) {
116         this(cam);
117         target.addControl(this);
118     }
119 
120     /**
121      * Constructs the chase camera
122      * if you use this constructor you have to attach the cam later to a spatial
123      * doing spatial.addControl(chaseCamera);
124      * @param cam the application camera
125      */
ChaseCamera(Camera cam)126     public ChaseCamera(Camera cam) {
127         this.cam = cam;
128         initialUpVec = cam.getUp().clone();
129     }
130 
131     /**
132      * Constructs the chase camera, and registers inputs
133      * if you use this constructor you have to attach the cam later to a spatial
134      * doing spatial.addControl(chaseCamera);
135      * @param cam the application camera
136      * @param inputManager the inputManager of the application to register inputs
137      */
ChaseCamera(Camera cam, InputManager inputManager)138     public ChaseCamera(Camera cam, InputManager inputManager) {
139         this(cam);
140         registerWithInput(inputManager);
141     }
142 
143     /**
144      * Constructs the chase camera, and registers inputs
145      * @param cam the application camera
146      * @param target the spatial to follow
147      * @param inputManager the inputManager of the application to register inputs
148      */
ChaseCamera(Camera cam, final Spatial target, InputManager inputManager)149     public ChaseCamera(Camera cam, final Spatial target, InputManager inputManager) {
150         this(cam, target);
151         registerWithInput(inputManager);
152     }
153 
onAction(String name, boolean keyPressed, float tpf)154     public void onAction(String name, boolean keyPressed, float tpf) {
155         if (dragToRotate) {
156             if (name.equals(ChaseCamToggleRotate) && enabled) {
157                 if (keyPressed) {
158                     canRotate = true;
159                     inputManager.setCursorVisible(false);
160                 } else {
161                     canRotate = false;
162                     inputManager.setCursorVisible(true);
163                 }
164             }
165         }
166 
167     }
168     private boolean zoomin;
169 
onAnalog(String name, float value, float tpf)170     public void onAnalog(String name, float value, float tpf) {
171         if (name.equals(ChaseCamMoveLeft)) {
172             rotateCamera(-value);
173         } else if (name.equals(ChaseCamMoveRight)) {
174             rotateCamera(value);
175         } else if (name.equals(ChaseCamUp)) {
176             vRotateCamera(value);
177         } else if (name.equals(ChaseCamDown)) {
178             vRotateCamera(-value);
179         } else if (name.equals(ChaseCamZoomIn)) {
180             zoomCamera(-value);
181             if (zoomin == false) {
182                 distanceLerpFactor = 0;
183             }
184             zoomin = true;
185         } else if (name.equals(ChaseCamZoomOut)) {
186             zoomCamera(+value);
187             if (zoomin == true) {
188                 distanceLerpFactor = 0;
189             }
190             zoomin = false;
191         }
192     }
193 
194     /**
195      * Registers inputs with the input manager
196      * @param inputManager
197      */
registerWithInput(InputManager inputManager)198     public final void registerWithInput(InputManager inputManager) {
199 
200         String[] inputs = {ChaseCamToggleRotate,
201             ChaseCamDown,
202             ChaseCamUp,
203             ChaseCamMoveLeft,
204             ChaseCamMoveRight,
205             ChaseCamZoomIn,
206             ChaseCamZoomOut};
207 
208         this.inputManager = inputManager;
209         if (!invertYaxis) {
210             inputManager.addMapping(ChaseCamDown, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
211             inputManager.addMapping(ChaseCamUp, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
212         } else {
213             inputManager.addMapping(ChaseCamDown, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
214             inputManager.addMapping(ChaseCamUp, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
215         }
216         inputManager.addMapping(ChaseCamZoomIn, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
217         inputManager.addMapping(ChaseCamZoomOut, new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
218         if(!invertXaxis){
219             inputManager.addMapping(ChaseCamMoveLeft, new MouseAxisTrigger(MouseInput.AXIS_X, true));
220             inputManager.addMapping(ChaseCamMoveRight, new MouseAxisTrigger(MouseInput.AXIS_X, false));
221         }else{
222             inputManager.addMapping(ChaseCamMoveLeft, new MouseAxisTrigger(MouseInput.AXIS_X, false));
223             inputManager.addMapping(ChaseCamMoveRight, new MouseAxisTrigger(MouseInput.AXIS_X, true));
224         }
225         inputManager.addMapping(ChaseCamToggleRotate, new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
226         inputManager.addMapping(ChaseCamToggleRotate, new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
227 
228         inputManager.addListener(this, inputs);
229     }
230 
231     /**
232      * Sets custom triggers for toggleing the rotation of the cam
233      * deafult are
234      * new MouseButtonTrigger(MouseInput.BUTTON_LEFT)  left mouse button
235      * new MouseButtonTrigger(MouseInput.BUTTON_RIGHT)  right mouse button
236      * @param triggers
237      */
setToggleRotationTrigger(Trigger... triggers)238     public void setToggleRotationTrigger(Trigger... triggers) {
239         inputManager.deleteMapping(ChaseCamToggleRotate);
240         inputManager.addMapping(ChaseCamToggleRotate, triggers);
241         inputManager.addListener(this, ChaseCamToggleRotate);
242     }
243 
244     /**
245      * Sets custom triggers for zomming in the cam
246      * default is
247      * new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true)  mouse wheel up
248      * @param triggers
249      */
setZoomInTrigger(Trigger... triggers)250     public void setZoomInTrigger(Trigger... triggers) {
251         inputManager.deleteMapping(ChaseCamZoomIn);
252         inputManager.addMapping(ChaseCamZoomIn, triggers);
253         inputManager.addListener(this, ChaseCamZoomIn);
254     }
255 
256     /**
257      * Sets custom triggers for zomming out the cam
258      * default is
259      * new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false)  mouse wheel down
260      * @param triggers
261      */
setZoomOutTrigger(Trigger... triggers)262     public void setZoomOutTrigger(Trigger... triggers) {
263         inputManager.deleteMapping(ChaseCamZoomOut);
264         inputManager.addMapping(ChaseCamZoomOut, triggers);
265         inputManager.addListener(this, ChaseCamZoomOut);
266     }
267 
computePosition()268     private void computePosition() {
269 
270         float hDistance = (distance) * FastMath.sin((FastMath.PI / 2) - vRotation);
271         pos.set(hDistance * FastMath.cos(rotation), (distance) * FastMath.sin(vRotation), hDistance * FastMath.sin(rotation));
272         pos.addLocal(target.getWorldTranslation());
273     }
274 
275     //rotate the camera around the target on the horizontal plane
rotateCamera(float value)276     private void rotateCamera(float value) {
277         if (!canRotate || !enabled) {
278             return;
279         }
280         rotating = true;
281         targetRotation += value * rotationSpeed;
282 
283 
284     }
285 
286     //move the camera toward or away the target
zoomCamera(float value)287     private void zoomCamera(float value) {
288         if (!enabled) {
289             return;
290         }
291 
292         zooming = true;
293         targetDistance += value * zoomSpeed;
294         if (targetDistance > maxDistance) {
295             targetDistance = maxDistance;
296         }
297         if (targetDistance < minDistance) {
298             targetDistance = minDistance;
299         }
300         if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {
301             targetVRotation = minVerticalRotation;
302         }
303     }
304 
305     //rotate the camera around the target on the vertical plane
vRotateCamera(float value)306     private void vRotateCamera(float value) {
307         if (!canRotate || !enabled) {
308             return;
309         }
310         vRotating = true;
311         targetVRotation += value * rotationSpeed;
312         if (targetVRotation > maxVerticalRotation) {
313             targetVRotation = maxVerticalRotation;
314         }
315         if ((targetVRotation < minVerticalRotation) && (targetDistance > (minDistance + 1.0f))) {
316             targetVRotation = minVerticalRotation;
317         }
318     }
319 
320     /**
321      * Updates the camera, should only be called internally
322      */
updateCamera(float tpf)323     protected void updateCamera(float tpf) {
324         if (enabled) {
325             targetLocation.set(target.getWorldTranslation()).addLocal(lookAtOffset);
326             if (smoothMotion) {
327 
328                 //computation of target direction
329                 targetDir.set(targetLocation).subtractLocal(prevPos);
330                 float dist = targetDir.length();
331 
332                 //Low pass filtering on the target postition to avoid shaking when physics are enabled.
333                 if (offsetDistance < dist) {
334                     //target moves, start chasing.
335                     chasing = true;
336                     //target moves, start trailing if it has to.
337                     if (trailingEnabled) {
338                         trailing = true;
339                     }
340                     //target moves...
341                     targetMoves = true;
342                 } else {
343                     //if target was moving, we compute a slight offset in rotation to avoid a rought stop of the cam
344                     //We do not if the player is rotationg the cam
345                     if (targetMoves && !canRotate) {
346                         if (targetRotation - rotation > trailingRotationInertia) {
347                             targetRotation = rotation + trailingRotationInertia;
348                         } else if (targetRotation - rotation < -trailingRotationInertia) {
349                             targetRotation = rotation - trailingRotationInertia;
350                         }
351                     }
352                     //Target stops
353                     targetMoves = false;
354                 }
355 
356                 //the user is rotating the cam by dragging the mouse
357                 if (canRotate) {
358                     //reseting the trailing lerp factor
359                     trailingLerpFactor = 0;
360                     //stop trailing user has the control
361                     trailing = false;
362                 }
363 
364 
365                 if (trailingEnabled && trailing) {
366                     if (targetMoves) {
367                         //computation if the inverted direction of the target
368                         Vector3f a = targetDir.negate().normalizeLocal();
369                         //the x unit vector
370                         Vector3f b = Vector3f.UNIT_X;
371                         //2d is good enough
372                         a.y = 0;
373                         //computation of the rotation angle between the x axis and the trail
374                         if (targetDir.z > 0) {
375                             targetRotation = FastMath.TWO_PI - FastMath.acos(a.dot(b));
376                         } else {
377                             targetRotation = FastMath.acos(a.dot(b));
378                         }
379                         if (targetRotation - rotation > FastMath.PI || targetRotation - rotation < -FastMath.PI) {
380                             targetRotation -= FastMath.TWO_PI;
381                         }
382 
383                         //if there is an important change in the direction while trailing reset of the lerp factor to avoid jumpy movements
384                         if (targetRotation != previousTargetRotation && FastMath.abs(targetRotation - previousTargetRotation) > FastMath.PI / 8) {
385                             trailingLerpFactor = 0;
386                         }
387                         previousTargetRotation = targetRotation;
388                     }
389                     //computing lerp factor
390                     trailingLerpFactor = Math.min(trailingLerpFactor + tpf * tpf * trailingSensitivity, 1);
391                     //computing rotation by linear interpolation
392                     rotation = FastMath.interpolateLinear(trailingLerpFactor, rotation, targetRotation);
393 
394                     //if the rotation is near the target rotation we're good, that's over
395                     if (targetRotation + 0.01f >= rotation && targetRotation - 0.01f <= rotation) {
396                         trailing = false;
397                         trailingLerpFactor = 0;
398                     }
399                 }
400 
401                 //linear interpolation of the distance while chasing
402                 if (chasing) {
403                     distance = temp.set(targetLocation).subtractLocal(cam.getLocation()).length();
404                     distanceLerpFactor = Math.min(distanceLerpFactor + (tpf * tpf * chasingSensitivity * 0.05f), 1);
405                     distance = FastMath.interpolateLinear(distanceLerpFactor, distance, targetDistance);
406                     if (targetDistance + 0.01f >= distance && targetDistance - 0.01f <= distance) {
407                         distanceLerpFactor = 0;
408                         chasing = false;
409                     }
410                 }
411 
412                 //linear interpolation of the distance while zooming
413                 if (zooming) {
414                     distanceLerpFactor = Math.min(distanceLerpFactor + (tpf * tpf * zoomSensitivity), 1);
415                     distance = FastMath.interpolateLinear(distanceLerpFactor, distance, targetDistance);
416                     if (targetDistance + 0.1f >= distance && targetDistance - 0.1f <= distance) {
417                         zooming = false;
418                         distanceLerpFactor = 0;
419                     }
420                 }
421 
422                 //linear interpolation of the rotation while rotating horizontally
423                 if (rotating) {
424                     rotationLerpFactor = Math.min(rotationLerpFactor + tpf * tpf * rotationSensitivity, 1);
425                     rotation = FastMath.interpolateLinear(rotationLerpFactor, rotation, targetRotation);
426                     if (targetRotation + 0.01f >= rotation && targetRotation - 0.01f <= rotation) {
427                         rotating = false;
428                         rotationLerpFactor = 0;
429                     }
430                 }
431 
432                 //linear interpolation of the rotation while rotating vertically
433                 if (vRotating) {
434                     vRotationLerpFactor = Math.min(vRotationLerpFactor + tpf * tpf * rotationSensitivity, 1);
435                     vRotation = FastMath.interpolateLinear(vRotationLerpFactor, vRotation, targetVRotation);
436                     if (targetVRotation + 0.01f >= vRotation && targetVRotation - 0.01f <= vRotation) {
437                         vRotating = false;
438                         vRotationLerpFactor = 0;
439                     }
440                 }
441                 //computing the position
442                 computePosition();
443                 //setting the position at last
444                 cam.setLocation(pos.addLocal(lookAtOffset));
445             } else {
446                 //easy no smooth motion
447                 vRotation = targetVRotation;
448                 rotation = targetRotation;
449                 distance = targetDistance;
450                 computePosition();
451                 cam.setLocation(pos.addLocal(lookAtOffset));
452             }
453             //keeping track on the previous position of the target
454             prevPos.set(targetLocation);
455 
456             //the cam looks at the target
457             cam.lookAt(targetLocation, initialUpVec);
458 
459         }
460     }
461 
462     /**
463      * Return the enabled/disabled state of the camera
464      * @return true if the camera is enabled
465      */
isEnabled()466     public boolean isEnabled() {
467         return enabled;
468     }
469 
470     /**
471      * Enable or disable the camera
472      * @param enabled true to enable
473      */
setEnabled(boolean enabled)474     public void setEnabled(boolean enabled) {
475         this.enabled = enabled;
476         if (!enabled) {
477             canRotate = false; // reset this flag in-case it was on before
478         }
479     }
480 
481     /**
482      * Returns the max zoom distance of the camera (default is 40)
483      * @return maxDistance
484      */
getMaxDistance()485     public float getMaxDistance() {
486         return maxDistance;
487     }
488 
489     /**
490      * Sets the max zoom distance of the camera (default is 40)
491      * @param maxDistance
492      */
setMaxDistance(float maxDistance)493     public void setMaxDistance(float maxDistance) {
494         this.maxDistance = maxDistance;
495     }
496 
497     /**
498      * Returns the min zoom distance of the camera (default is 1)
499      * @return minDistance
500      */
getMinDistance()501     public float getMinDistance() {
502         return minDistance;
503     }
504 
505     /**
506      * Sets the min zoom distance of the camera (default is 1)
507      * @return minDistance
508      */
setMinDistance(float minDistance)509     public void setMinDistance(float minDistance) {
510         this.minDistance = minDistance;
511     }
512 
513     /**
514      * clone this camera for a spatial
515      * @param spatial
516      * @return
517      */
cloneForSpatial(Spatial spatial)518     public Control cloneForSpatial(Spatial spatial) {
519         ChaseCamera cc = new ChaseCamera(cam, spatial, inputManager);
520         cc.setMaxDistance(getMaxDistance());
521         cc.setMinDistance(getMinDistance());
522         return cc;
523     }
524 
525     /**
526      * Sets the spacial for the camera control, should only be used internally
527      * @param spatial
528      */
setSpatial(Spatial spatial)529     public void setSpatial(Spatial spatial) {
530         target = spatial;
531         if (spatial == null) {
532             return;
533         }
534         computePosition();
535         prevPos = new Vector3f(target.getWorldTranslation());
536         cam.setLocation(pos);
537     }
538 
539     /**
540      * update the camera control, should only be used internally
541      * @param tpf
542      */
update(float tpf)543     public void update(float tpf) {
544         updateCamera(tpf);
545     }
546 
547     /**
548      * renders the camera control, should only be used internally
549      * @param rm
550      * @param vp
551      */
render(RenderManager rm, ViewPort vp)552     public void render(RenderManager rm, ViewPort vp) {
553         //nothing to render
554     }
555 
556     /**
557      * Write the camera
558      * @param ex the exporter
559      * @throws IOException
560      */
write(JmeExporter ex)561     public void write(JmeExporter ex) throws IOException {
562         OutputCapsule capsule = ex.getCapsule(this);
563         capsule.write(maxDistance, "maxDistance", 40);
564         capsule.write(minDistance, "minDistance", 1);
565     }
566 
567     /**
568      * Read the camera
569      * @param im
570      * @throws IOException
571      */
read(JmeImporter im)572     public void read(JmeImporter im) throws IOException {
573         InputCapsule ic = im.getCapsule(this);
574         maxDistance = ic.readFloat("maxDistance", 40);
575         minDistance = ic.readFloat("minDistance", 1);
576     }
577 
578     /**
579      * returns the maximal vertical rotation angle of the camera around the target
580      * @return
581      */
getMaxVerticalRotation()582     public float getMaxVerticalRotation() {
583         return maxVerticalRotation;
584     }
585 
586     /**
587      * sets the maximal vertical rotation angle of the camera around the target default is Pi/2;
588      * @param maxVerticalRotation
589      */
setMaxVerticalRotation(float maxVerticalRotation)590     public void setMaxVerticalRotation(float maxVerticalRotation) {
591         this.maxVerticalRotation = maxVerticalRotation;
592     }
593 
594     /**
595      * returns the minimal vertical rotation angle of the camera around the target
596      * @return
597      */
getMinVerticalRotation()598     public float getMinVerticalRotation() {
599         return minVerticalRotation;
600     }
601 
602     /**
603      * sets the minimal vertical rotation angle of the camera around the target default is 0;
604      * @param minHeight
605      */
setMinVerticalRotation(float minHeight)606     public void setMinVerticalRotation(float minHeight) {
607         this.minVerticalRotation = minHeight;
608     }
609 
610     /**
611      * returns true is smmoth motion is enabled for this chase camera
612      * @return
613      */
isSmoothMotion()614     public boolean isSmoothMotion() {
615         return smoothMotion;
616     }
617 
618     /**
619      * Enables smooth motion for this chase camera
620      * @param smoothMotion
621      */
setSmoothMotion(boolean smoothMotion)622     public void setSmoothMotion(boolean smoothMotion) {
623         this.smoothMotion = smoothMotion;
624     }
625 
626     /**
627      * returns the chasing sensitivity
628      * @return
629      */
getChasingSensitivity()630     public float getChasingSensitivity() {
631         return chasingSensitivity;
632     }
633 
634     /**
635      *
636      * Sets the chasing sensitivity, the lower the value the slower the camera will follow the target when it moves
637      * default is 5
638      * Only has an effect if smoothMotion is set to true and trailing is enabled
639      * @param chasingSensitivity
640      */
setChasingSensitivity(float chasingSensitivity)641     public void setChasingSensitivity(float chasingSensitivity) {
642         this.chasingSensitivity = chasingSensitivity;
643     }
644 
645     /**
646      * Returns the rotation sensitivity
647      * @return
648      */
getRotationSensitivity()649     public float getRotationSensitivity() {
650         return rotationSensitivity;
651     }
652 
653     /**
654      * Sets the rotation sensitivity, the lower the value the slower the camera will rotates around the target when draging with the mouse
655      * default is 5, values over 5 should have no effect.
656      * If you want a significant slow down try values below 1.
657      * Only has an effect if smoothMotion is set to true
658      * @param rotationSensitivity
659      */
setRotationSensitivity(float rotationSensitivity)660     public void setRotationSensitivity(float rotationSensitivity) {
661         this.rotationSensitivity = rotationSensitivity;
662     }
663 
664     /**
665      * returns true if the trailing is enabled
666      * @return
667      */
isTrailingEnabled()668     public boolean isTrailingEnabled() {
669         return trailingEnabled;
670     }
671 
672     /**
673      * Enable the camera trailing : The camera smoothly go in the targets trail when it moves.
674      * Only has an effect if smoothMotion is set to true
675      * @param trailingEnabled
676      */
setTrailingEnabled(boolean trailingEnabled)677     public void setTrailingEnabled(boolean trailingEnabled) {
678         this.trailingEnabled = trailingEnabled;
679     }
680 
681     /**
682      *
683      * returns the trailing rotation inertia
684      * @return
685      */
getTrailingRotationInertia()686     public float getTrailingRotationInertia() {
687         return trailingRotationInertia;
688     }
689 
690     /**
691      * Sets the trailing rotation inertia : default is 0.1. This prevent the camera to roughtly stop when the target stops moving
692      * before the camera reached the trail position.
693      * Only has an effect if smoothMotion is set to true and trailing is enabled
694      * @param trailingRotationInertia
695      */
setTrailingRotationInertia(float trailingRotationInertia)696     public void setTrailingRotationInertia(float trailingRotationInertia) {
697         this.trailingRotationInertia = trailingRotationInertia;
698     }
699 
700     /**
701      * returns the trailing sensitivity
702      * @return
703      */
getTrailingSensitivity()704     public float getTrailingSensitivity() {
705         return trailingSensitivity;
706     }
707 
708     /**
709      * Only has an effect if smoothMotion is set to true and trailing is enabled
710      * Sets the trailing sensitivity, the lower the value, the slower the camera will go in the target trail when it moves.
711      * default is 0.5;
712      * @param trailingSensitivity
713      */
setTrailingSensitivity(float trailingSensitivity)714     public void setTrailingSensitivity(float trailingSensitivity) {
715         this.trailingSensitivity = trailingSensitivity;
716     }
717 
718     /**
719      * returns the zoom sensitivity
720      * @return
721      */
getZoomSensitivity()722     public float getZoomSensitivity() {
723         return zoomSensitivity;
724     }
725 
726     /**
727      * Sets the zoom sensitivity, the lower the value, the slower the camera will zoom in and out.
728      * default is 5.
729      * @param zoomSensitivity
730      */
setZoomSensitivity(float zoomSensitivity)731     public void setZoomSensitivity(float zoomSensitivity) {
732         this.zoomSensitivity = zoomSensitivity;
733     }
734 
735     /**
736      * Sets the default distance at start of applicaiton
737      * @param defaultDistance
738      */
setDefaultDistance(float defaultDistance)739     public void setDefaultDistance(float defaultDistance) {
740         distance = defaultDistance;
741         targetDistance = distance;
742     }
743 
744     /**
745      * sets the default horizontal rotation of the camera at start of the application
746      * @param angle
747      */
setDefaultHorizontalRotation(float angle)748     public void setDefaultHorizontalRotation(float angle) {
749         rotation = angle;
750         targetRotation = angle;
751     }
752 
753     /**
754      * sets the default vertical rotation of the camera at start of the application
755      * @param angle
756      */
setDefaultVerticalRotation(float angle)757     public void setDefaultVerticalRotation(float angle) {
758         vRotation = angle;
759         targetVRotation = angle;
760     }
761 
762     /**
763      * @return If drag to rotate feature is enabled.
764      *
765      * @see FlyByCamera#setDragToRotate(boolean)
766      */
isDragToRotate()767     public boolean isDragToRotate() {
768         return dragToRotate;
769     }
770 
771     /**
772      * @param dragToRotate When true, the user must hold the mouse button
773      * and drag over the screen to rotate the camera, and the cursor is
774      * visible until dragged. Otherwise, the cursor is invisible at all times
775      * and holding the mouse button is not needed to rotate the camera.
776      * This feature is disabled by default.
777      */
setDragToRotate(boolean dragToRotate)778     public void setDragToRotate(boolean dragToRotate) {
779         this.dragToRotate = dragToRotate;
780         this.canRotate = !dragToRotate;
781         inputManager.setCursorVisible(dragToRotate);
782     }
783 
784     /**
785      * return the current distance from the camera to the target
786      * @return
787      */
getDistanceToTarget()788     public float getDistanceToTarget() {
789         return distance;
790     }
791 
792     /**
793      * returns the current horizontal rotation around the target in radians
794      * @return
795      */
getHorizontalRotation()796     public float getHorizontalRotation() {
797         return rotation;
798     }
799 
800     /**
801      * returns the current vertical rotation around the target in radians.
802      * @return
803      */
getVerticalRotation()804     public float getVerticalRotation() {
805         return vRotation;
806     }
807 
808     /**
809      * returns the offset from the target's position where the camera looks at
810      * @return
811      */
getLookAtOffset()812     public Vector3f getLookAtOffset() {
813         return lookAtOffset;
814     }
815 
816     /**
817      * Sets the offset from the target's position where the camera looks at
818      * @param lookAtOffset
819      */
setLookAtOffset(Vector3f lookAtOffset)820     public void setLookAtOffset(Vector3f lookAtOffset) {
821         this.lookAtOffset = lookAtOffset;
822     }
823 
824     /**
825      * Sets the up vector of the camera used for the lookAt on the target
826      * @param up
827      */
setUpVector(Vector3f up)828     public void setUpVector(Vector3f up){
829         initialUpVec=up;
830     }
831 
832     /**
833      * Returns the up vector of the camera used for the lookAt on the target
834      * @return
835      */
getUpVector()836     public Vector3f getUpVector(){
837         return initialUpVec;
838     }
839 
840     /**
841      * invert the vertical axis movement of the mouse
842      * @param invertYaxis
843      */
setInvertVerticalAxis(boolean invertYaxis)844     public void setInvertVerticalAxis(boolean invertYaxis) {
845         this.invertYaxis = invertYaxis;
846         inputManager.deleteMapping(ChaseCamDown);
847         inputManager.deleteMapping(ChaseCamUp);
848         if (!invertYaxis) {
849             inputManager.addMapping(ChaseCamDown, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
850             inputManager.addMapping(ChaseCamUp, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
851         } else {
852             inputManager.addMapping(ChaseCamDown, new MouseAxisTrigger(MouseInput.AXIS_Y, false));
853             inputManager.addMapping(ChaseCamUp, new MouseAxisTrigger(MouseInput.AXIS_Y, true));
854         }
855         inputManager.addListener(this, ChaseCamDown, ChaseCamUp);
856     }
857 
858     /**
859      * invert the Horizontal axis movement of the mouse
860      * @param invertXaxis
861      */
setInvertHorizontalAxis(boolean invertXaxis)862     public void setInvertHorizontalAxis(boolean invertXaxis) {
863         this.invertXaxis = invertXaxis;
864         inputManager.deleteMapping(ChaseCamMoveLeft);
865         inputManager.deleteMapping(ChaseCamMoveRight);
866         if(!invertXaxis){
867             inputManager.addMapping(ChaseCamMoveLeft, new MouseAxisTrigger(MouseInput.AXIS_X, true));
868             inputManager.addMapping(ChaseCamMoveRight, new MouseAxisTrigger(MouseInput.AXIS_X, false));
869         }else{
870             inputManager.addMapping(ChaseCamMoveLeft, new MouseAxisTrigger(MouseInput.AXIS_X, false));
871             inputManager.addMapping(ChaseCamMoveRight, new MouseAxisTrigger(MouseInput.AXIS_X, true));
872         }
873         inputManager.addListener(this, ChaseCamMoveLeft, ChaseCamMoveRight);
874     }
875 }
876