private static Quaternion negated(Quaternion quat) { return new Quaternion(-quat.x, -quat.y, -quat.z, -quat.w); }
/** * When translating, the up direction of the node must match the up direction of the plane from * the hit result. However, we also need to make sure that the original forward direction of the * node is respected. */ private Quaternion calculateFinalDesiredLocalRotation(Quaternion desiredLocalRotation) { // Get a rotation just to the up direction. // Otherwise, the node will spin around as you rotate. Vector3 rotatedUp = Quaternion.rotateVector(desiredLocalRotation, Vector3.up()); desiredLocalRotation = Quaternion.rotationBetweenVectors(Vector3.up(), rotatedUp); // Adjust the rotation to make sure the node maintains the same forward direction. Quaternion forwardInLocal = Quaternion.rotationBetweenVectors(Vector3.forward(), initialForwardInLocal); desiredLocalRotation = Quaternion.multiply(desiredLocalRotation, forwardInLocal); return desiredLocalRotation.normalized(); }
if (plane.isPoseInPolygon(pose) && allowedPlaneTypes.contains(plane.getType())) { desiredLocalPosition = new Vector3(pose.tx(), pose.ty(), pose.tz()); desiredLocalRotation = new Quaternion(pose.qx(), pose.qy(), pose.qz(), pose.qw()); Node parent = getTransformableNode().getParent(); if (parent != null && desiredLocalPosition != null && desiredLocalRotation != null) { desiredLocalPosition = parent.worldToLocalPoint(desiredLocalPosition); desiredLocalRotation = Quaternion.multiply( parent.getWorldRotation().inverted(), Preconditions.checkNotNull(desiredLocalRotation));
@Override public void onContinueTransformation(TwistGesture gesture) { float rotationAmount = -gesture.getDeltaRotationDegrees() * rotationRateDegrees; Quaternion rotationDelta = new Quaternion(Vector3.up(), rotationAmount); Quaternion localrotation = getTransformableNode().getLocalRotation(); localrotation = Quaternion.multiply(localrotation, rotationDelta); getTransformableNode().setLocalRotation(localrotation); }
Quaternion rotationFromAToB = Quaternion.lookRotation(directionFromTopToBottom, desiredUp); Quaternion.rotateVector(rotationFromAToB, Vector3.forward()).normalized(); Vector3 rightDirection = Quaternion.rotateVector(rotationFromAToB, Vector3.right()).normalized(); Vector3 upDirection = Quaternion.rotateVector(rotationFromAToB, Vector3.up()).normalized(); desiredUp.set(upDirection);
/** Returns an ObjectAnimator that makes this node rotate. */ private static ObjectAnimator createAnimator() { // Node's setLocalRotation method accepts Quaternions as parameters. // First, set up orientations that will animate a circle. Quaternion orientation1 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 0); Quaternion orientation2 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 120); Quaternion orientation3 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 240); Quaternion orientation4 = Quaternion.axisAngle(new Vector3(0.0f, 1.0f, 0.0f), 360); ObjectAnimator orbitAnimation = new ObjectAnimator(); orbitAnimation.setObjectValues(orientation1, orientation2, orientation3, orientation4); // Next, give it the localRotation property. orbitAnimation.setPropertyName("localRotation"); // Use Sceneform's QuaternionEvaluator. orbitAnimation.setEvaluator(new QuaternionEvaluator()); // Allow orbitAnimation to repeat forever orbitAnimation.setRepeatCount(ObjectAnimator.INFINITE); orbitAnimation.setRepeatMode(ObjectAnimator.RESTART); orbitAnimation.setInterpolator(new LinearInterpolator()); orbitAnimation.setAutoCancel(true); return orbitAnimation; } }
lerp(rotations.get(segmentIndex), rotations.get(segmentIndex + 1), .5f); Vector3 rightDirection = Quaternion.rotateVector(averagedRotation, Vector3.right()).normalized(); Vector3 upDirection = Quaternion.rotateVector(averagedRotation, Vector3.up()).normalized();
@Override public void onUpdate(FrameTime frameTime) { if (infoCard == null) { return; } // Typically, getScene() will never return null because onUpdate() is only called when the node // is in the scene. // However, if onUpdate is called explicitly or if the node is removed from the scene on a // different thread during onUpdate, then getScene may be null. if (getScene() == null) { return; } Vector3 cameraPosition = getScene().getCamera().getWorldPosition(); Vector3 cardPosition = infoCard.getWorldPosition(); Vector3 direction = Vector3.subtract(cameraPosition, cardPosition); Quaternion lookRotation = Quaternion.lookRotation(direction, Vector3.up()); infoCard.setWorldRotation(lookRotation); } }
private void updateRotation(FrameTime frameTime) { // Store in local variable for nullness static analysis. Quaternion desiredLocalRotation = this.desiredLocalRotation; if (desiredLocalRotation == null) { return; } Quaternion localRotation = getTransformableNode().getLocalRotation(); float lerpFactor = MathHelper.clamp(frameTime.getDeltaSeconds() * LERP_SPEED, 0, 1); localRotation = Quaternion.slerp(localRotation, desiredLocalRotation, lerpFactor); float dot = Math.abs(dotQuaternion(localRotation, desiredLocalRotation)); if (dot >= ROTATION_DOT_THRESHOLD) { localRotation = desiredLocalRotation; this.desiredLocalRotation = null; } getTransformableNode().setLocalRotation(localRotation); }
desiredLocalRotation = calculateFinalDesiredLocalRotation(Quaternion.identity());
private static Quaternion lerp(Quaternion a, Quaternion b, float ratio) { return new Quaternion( MathHelper.lerp(a.x, b.x, ratio), MathHelper.lerp(a.y, b.y, ratio), MathHelper.lerp(a.z, b.z, ratio), MathHelper.lerp(a.w, b.w, ratio)); } }