@Override
 public void compute(ProcessorArmingCollection collection) {
   degrees += increment;
   quaternion.fromAngles(0.0f, degrees, 0.0f);
   quaternion.mult(up, upOut);
   quaternion.mult(position, positionOut);
 }
 private void moveObject(Vector3f delta) {
   //            Vector3f delta = new Vector3f(0, 0, -0.2f);
   Quaternion rotation =
       ClientContextJME.getViewManager().getCameraTransform().getRotation(null);
   delta = rotation.mult(delta);
   applyDelta(delta, new Quaternion());
 }
  @Override
  public void apply(float dt, Particle particle, int index) {

    if (particle.getStatus() == Particle.Status.Alive
        && floor.pseudoDistance(particle.getPosition()) <= 0) {

      float t =
          (floor.getNormal().dot(particle.getPosition()) - floor.getConstant())
              / floor.getNormal().dot(particle.getVelocity());
      Vector3f s = particle.getPosition().subtract(particle.getVelocity().mult(t));

      this.normal.normalizeLocal();
      Vector3f v1 = this.normal.cross(s.subtract(pos));
      Vector3f v2 = this.normal.cross(v1);
      v1.normalizeLocal();
      v2.normalizeLocal();

      Vector3f newVel = new Vector3f(particle.getVelocity());
      newVel.y *= -bouncyness;
      Quaternion q = new Quaternion();
      q.fromAxes(v1, this.normal, v2);
      newVel = q.mult(newVel);

      particle.setVelocity(newVel);
    } // if
  }
  protected void applyDelta(Vector3f deltaTranslation, Quaternion deltaRotation) {
    LOGGER.warning("Applying delta: " + deltaTranslation + " " + deltaRotation);

    boolean startedDrag = false;
    if (!dragging) {
      // no drag in progress. Start one now and end it after the drag
      // operation
      startDrag();
      startedDrag = true;
    }

    for (Cell cell : selected.getSelectedCells()) {
      CellTransform transform = cell.getLocalTransform();
      Vector3f translate = transform.getTranslation(null);
      Quaternion rotation = transform.getRotation(null);

      // if the cell has a parent, make sure to take the parent's
      // rotation and scale into account when applying the delta
      Vector3f localDeltaTranslation = deltaTranslation.clone();
      Cell parent = cell.getParent();
      if (parent != null) {
        CellTransform parentWorld = parent.getWorldTransform();
        Quaternion parentRotation = parentWorld.getRotation(null);
        float parentScale = parentWorld.getScaling();

        LOGGER.warning("Parent transform: " + parentWorld);

        // invert the rotation to get the child rotation
        parentRotation.inverseLocal();
        localDeltaTranslation = parentRotation.mult(deltaTranslation);
        localDeltaTranslation.multLocal(parentScale);

        LOGGER.warning("Local delta translation: " + localDeltaTranslation);
      }

      translate.addLocal(localDeltaTranslation);
      rotation.multLocal(deltaRotation);
      transform.setTranslation(translate);
      transform.setRotation(rotation);

      MovableComponent mc = getMovable(cell);
      if (mc != null) {
        mc.localMoveRequest(transform);
      }
    }
    lastTranslation.addLocal(deltaTranslation);
    lastRotation.multLocal(deltaRotation);
    // if we started a drag, remember to end it
    if (startedDrag) {
      endDrag();
    }
  }
  protected void handleRotate(Vector3f start, Vector3f end, float direction) {
    LOGGER.warning(
        "Handling rotate, start: "
            + start
            + ""
            + "\nlast: "
            + lastTranslation
            + ""
            + "\nend: "
            + end);
    Vector3f increment = end.subtract(lastTranslation);
    increment.y = 0;
    float length = increment.length();
    float magic = 3f; // ~ 180 degrees
    float percent = length / magic;

    // if the difference is negative, we need to rotate in the opposite
    // direction. Caclulate the difference after taking into account
    // the direction of the camera
    //        CellTransform viewTransform = ViewManager.getViewManager().getCameraTransform();
    //        Quaternion viewRotation = viewTransform.getRotation(null);
    //        increment = viewRotation.mult(increment);
    //
    //        LOGGER.warning("viewTransform: " + viewTransform + ", increment: " +
    //                       increment);
    //
    //        if (increment.x < 0 || increment.z < 0) {
    //            percent = -percent;
    //        }

    // take direction into account
    percent *= direction;

    Quaternion rotation = new Quaternion();
    rotation.fromAngles(0f, percent * FastMath.PI, 0f);

    // rotation is the total rotation since we started moving the mouse,
    // so calculate just the delta to apply
    Quaternion deltaRotation = rotation.mult(lastRotation.inverse());

    LOGGER.warning(
        "Percent: "
            + percent
            + " = "
            + toAnglesString(rotation)
            + ". Last = "
            + toAnglesString(lastRotation)
            + ". Delta = "
            + toAnglesString(deltaRotation));

    applyDelta(Vector3f.ZERO, deltaRotation);
  }