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