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)); } }
/** * 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(); }
public Vector3 getPosition() { return new Vector3(position); }
@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); } }
/** 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; } }
@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); }
@Override public void onUpdated(Node node, FrameTime frameTime) { if (isTransforming()) { return; } float t = MathHelper.clamp(frameTime.getDeltaSeconds() * LERP_SPEED, 0, 1); currentScaleRatio = MathHelper.lerp(currentScaleRatio, getClampedScaleRatio(), t); float finalScaleValue = getFinalScale(); Vector3 finalScale = new Vector3(finalScaleValue, finalScaleValue, finalScaleValue); getTransformableNode().setLocalScale(finalScale); }
private void updatePosition(FrameTime frameTime) { // Store in local variable for nullness static analysis. Vector3 desiredLocalPosition = this.desiredLocalPosition; if (desiredLocalPosition == null) { return; } Vector3 localPosition = getTransformableNode().getLocalPosition(); float lerpFactor = MathHelper.clamp(frameTime.getDeltaSeconds() * LERP_SPEED, 0, 1); localPosition = Vector3.lerp(localPosition, desiredLocalPosition, lerpFactor); float lengthDiff = Math.abs(Vector3.subtract(desiredLocalPosition, localPosition).length()); if (lengthDiff <= POSITION_LENGTH_THRESHOLD) { localPosition = desiredLocalPosition; this.desiredLocalPosition = null; } getTransformableNode().setLocalPosition(localPosition); }
private static float calculateDeltaRotation( Vector3 currentPosition1, Vector3 currentPosition2, Vector3 previousPosition1, Vector3 previousPosition2) { Vector3 currentDirection = Vector3.subtract(currentPosition1, currentPosition2).normalized(); Vector3 previousDirection = Vector3.subtract(previousPosition1, previousPosition2).normalized(); float sign = Math.signum( previousDirection.x * currentDirection.y - previousDirection.y * currentDirection.x); return Vector3.angleBetweenVectors(currentDirection, previousDirection) * sign; } }
@Override protected void onStart(HitTestResult hitTestResult, MotionEvent motionEvent) { debugLog("Started: " + pointerId); position.set(GesturePointersUtility.motionEventToPosition(motionEvent, pointerId)); gesturePointersUtility.retainPointerId(pointerId); }
private static Quaternion negated(Quaternion quat) { return new Quaternion(-quat.x, -quat.y, -quat.z, -quat.w); }
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); }
public Vector3 getDelta() { return new Vector3(delta); }
public static Vector3 motionEventToPosition(MotionEvent me, int pointerId) { int index = me.findPointerIndex(pointerId); return new Vector3(me.getX(index), me.getY(index), 0.0f); } }
public TwistGesture( GesturePointersUtility gesturePointersUtility, MotionEvent motionEvent, int pointerId2) { super(gesturePointersUtility); pointerId1 = motionEvent.getPointerId(motionEvent.getActionIndex()); this.pointerId2 = pointerId2; startPosition1 = GesturePointersUtility.motionEventToPosition(motionEvent, pointerId1); startPosition2 = GesturePointersUtility.motionEventToPosition(motionEvent, pointerId2); previousPosition1 = new Vector3(startPosition1); previousPosition2 = new Vector3(startPosition2); debugLog("Created"); }
public PinchGesture( GesturePointersUtility gesturePointersUtility, MotionEvent motionEvent, int pointerId2) { super(gesturePointersUtility); pointerId1 = motionEvent.getPointerId(motionEvent.getActionIndex()); this.pointerId2 = pointerId2; startPosition1 = GesturePointersUtility.motionEventToPosition(motionEvent, pointerId1); startPosition2 = GesturePointersUtility.motionEventToPosition(motionEvent, pointerId2); previousPosition1 = new Vector3(startPosition1); previousPosition2 = new Vector3(startPosition2); debugLog("Created"); }
@Override public void onContinueTransformation(PinchGesture gesture) { currentScaleRatio += gesture.gapDeltaInches() * sensitivity; float finalScaleValue = getFinalScale(); Vector3 finalScale = new Vector3(finalScaleValue, finalScaleValue, finalScaleValue); getTransformableNode().setLocalScale(finalScale); if (currentScaleRatio < -ELASTIC_RATIO_LIMIT || currentScaleRatio > (1.0f + ELASTIC_RATIO_LIMIT)) { gesture.cancel(); } }
private Node createPlanet( String name, Node parent, float auFromParent, float orbitDegreesPerSecond, ModelRenderable renderable, float planetScale) { // Orbit is a rotating node with no renderable positioned at the sun. // The planet is positioned relative to the orbit so that it appears to rotate around the sun. // This is done instead of making the sun rotate so each planet can orbit at its own speed. RotatingNode orbit = new RotatingNode(solarSettings, true); orbit.setDegreesPerSecond(orbitDegreesPerSecond); orbit.setParent(parent); // Create the planet and position it relative to the sun. Planet planet = new Planet(this, name, planetScale, renderable, solarSettings); planet.setParent(orbit); planet.setLocalPosition(new Vector3(auFromParent * AU_TO_METERS, 0.0f, 0.0f)); return planet; }