Search code examples
androidarcoresceneform

Scaling height and width of transformable node in AR-Core (Ar Fragment)


I am currently using AR-Core (Ar fragment), I have placed a transformable node to the ar fragment, and I can scale its x, y, and z coordinate with the pinch gesture. But the problem here is on changing the zooming in the transformable node, it scales with equal proportion. I want to scale x, y, z of transformable node separately with the help of pinch gesture.

For Example, If I perform the gesture in the x direction, then only the x-axis alone should scale, on changing the y-direction y-axis should change.


Solution

  • I assume that you have a TransformableNode and by default a ScaleController scales your model. The ScaleController is listening on the PinchGesture. It's scaling the node in all direction because its logic is simplified and it computes only one scale variable which is applied for all directions:

    https://github.com/google-ar/sceneform-android-sdk/blob/master/sceneformux/ux/src/main/java/com/google/ar/sceneform/ux/ScaleController.java#L111

    @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();
        }
    }
    

    As you see the finalScale = new Vector3(finalScaleValue, finalScaleValue, finalScaleValue); line. I'd spin-off my own ScaleController (by inheriting from that built-in ScaleController) which manages x, y, z pinches in separate variables. You'd need to override that onContinueTransformation function and having a Vector3 currentScaleVector and Vector3 finalScaleVector instead of float ones. Then when you instantiate your TransformableNode you can specify a TransformationSystem, and the ScaleController is one part of that TransformationSystem, so you'd pass in your overridden ScaleController to the system.

    scaleController = new ScaleController(this, transformationSystem.getPinchRecognizer());
    addTransformationController(scaleController);
    

    What I don't see clearly right now on the PinchGesture interface how you'd obtain the Vector3 gap, and not just the float one. If push comes to shove private fields (startPosition1, previousPosition1) can be read but that would be a hack.