@Override
  public void render(RenderManager rm) {
    if (!isEnabled() || listener == null) {
      return;
    }

    Vector3f lastLocation = listener.getLocation();
    Vector3f currentLocation = camera.getLocation();
    Vector3f velocity = listener.getVelocity();

    if (!lastLocation.equals(currentLocation)) {
      velocity.set(currentLocation).subtractLocal(lastLocation);
      velocity.multLocal(1f / lastTpf);
      listener.setLocation(currentLocation);
      listener.setVelocity(velocity);
    } else if (!velocity.equals(Vector3f.ZERO)) {
      listener.setVelocity(Vector3f.ZERO);
    }

    Quaternion lastRotation = listener.getRotation();
    Quaternion currentRotation = camera.getRotation();
    if (!lastRotation.equals(currentRotation)) {
      listener.setRotation(currentRotation);
    }
  }
 /** WARNING - CompoundCollisionShape scaling has no effect. */
 @Override
 public void setScale(Vector3f scale) {
   if (!scale.equals(Vector3f.UNIT_XYZ)) {
     Logger.getLogger(this.getClass().getName())
         .log(Level.WARNING, "SphereCollisionShape cannot be scaled");
   }
 }
 private boolean lastCameraLocationsTheSame(List<Vector3f> locations) {
   boolean theSame = true;
   for (Vector3f l : locations) {
     for (Vector3f v : lastCameraLocations) {
       if (!v.equals(l)) {
         theSame = false;
         return false;
       }
     }
   }
   return theSame;
 }
  public Vector3f onMove(Vector3f moveVec) {
    if (moveVec.equals(Vector3f.ZERO)) {
      return currentPos3d;
    }

    Vector3f newPos2d = new Vector3f(currentPos3d);
    newPos2d.addLocal(moveVec);
    newPos2d.setY(0);

    Vector3f currentPos2d = new Vector3f(currentPos3d);
    currentPos2d.setY(0);

    // Cell nextCell = navMesh.resolveMotionOnMesh(currentPos2d, currentCell, newPos2d, newPos2d);
    // currentCell = nextCell;
    newPos2d.setY(currentPos3d.getY());
    return newPos2d;
  }