2

I am using AR Core as a 3D Viewer in my application. I am not using Sceneform for AR rendering but for rendering the model in 3D. The problem I am facing is how I can 360 rotate the model with swipe gestures or touch events. Is that possible with sceneform or I need to use the more difficult ways like open GL.

Here is my code.

public class FullDegreeActivity extends AppCompatActivity {

SceneView sceneView;
Scene scene;
Node node;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_full_degree);
    inIt();
    renderObject();
}

private void inIt() {
    sceneView = findViewById(R.id.scene_view);
    scene = sceneView.getScene();
}

private void renderObject() {
    ModelRenderable.builder().setSource(this, Uri.parse("edited.sfb"))
            .build().thenAccept(modelRenderable -> {
                addNodeToScene(modelRenderable);
            }
    ).exceptionally(throwable -> {

        return null;
    });
}

private void addNodeToScene(ModelRenderable renderable) {
    node = new Node();
    node.setParent(scene);
    node.setLocalPosition(new Vector3(0f, 0f, -1f));
    node.setLocalScale(new Vector3(1f, 1f, 1f));
    node.setName("Dog");
    node.setRenderable(renderable);
    TransformableNode transformableNode = new TransformableNode(sceneView.getTransformationSystem());
    transformableNode.setParent(node);
    transformableNode.setLocalRotation(Quaternion.axisAngle(new Vector3(1f, 0, 0), 0f));
    transformableNode.setRenderable(renderable);
    transformableNode.select();
    scene.addChild(transformableNode);
}

@Override
protected void onPause() {
    super.onPause();
    sceneView.pause();
}

@Override
protected void onResume() {
    super.onResume();
    try {
        sceneView.resume();
    } catch (CameraNotAvailableException e) {
        e.printStackTrace();
    }
}
}
Dheeraj Rijhwani
  • 351
  • 5
  • 18

3 Answers3

3

I share my fresh experience, maybe someone still need a solution.

You have two options to achieve that:

  1. As noticed above you can implement your own gestures, scales and rotations using androids standard gestures or addOnPeekTouchListener listener of scene.

  2. Use Transformable node for it's facilities, then you only have to remove the translation controller and implement a new rotation controller.

Lets consider option 2 in bit detail with Kotlin code

Crate new rotation controller for Drag gestures:

class DragRotationController(transformableNode: BaseTransformableNode, gestureRecognizer: DragGestureRecognizer) :
    BaseTransformationController<DragGesture>(transformableNode, gestureRecognizer) {

    // Rate that the node rotates in degrees per degree of twisting.
    var rotationRateDegrees = 0.5f

    public override fun canStartTransformation(gesture: DragGesture): Boolean {
        return transformableNode.isSelected
    }

    public override fun onContinueTransformation(gesture: DragGesture) {

        var localRotation = transformableNode.localRotation

        val rotationAmountX = gesture.delta.x * rotationRateDegrees
        val rotationDeltaX = Quaternion(Vector3.up(), rotationAmountX)
        localRotation = Quaternion.multiply(localRotation, rotationDeltaX)

        transformableNode.localRotation = localRotation
    }

    public override fun onEndTransformation(gesture: DragGesture) {}
}

To remove translation controller:

node.translationController.isEnabled = false
node.removeTransformationController(translationController)

Add our custom rotation controller to node

val dragRotationController = DragRotationController(node, transformationSystem.dragRecognizer)
node.addTransformationController(dragRotationController)

And this is the DragTransformableNode

import com.google.ar.sceneform.ux.TransformableNode
import com.google.ar.sceneform.ux.TransformationSystem

class DragTransformableNode(transformationSystem: TransformationSystem) :
    TransformableNode(transformationSystem) {

    private val dragRotationController = DragRotationController(
        this,
        transformationSystem.dragRecognizer
    )

    init {
        translationController.isEnabled = false
        removeTransformationController(translationController)
        removeTransformationController(rotationController)
        addTransformationController(dragRotationController)
    }
}
Tigran Babajanyan
  • 1,967
  • 1
  • 22
  • 41
-1

You can do it easily with Sceneform. In fact you don't any Sceneform code for it. You just use Android's standard gesture recognition to detect the gesture and use it to update the rotation of your node. https://developer.android.com/training/gestures/detector

Steven Mohr
  • 1,167
  • 6
  • 19
-2

I think that your implementation is pretty close to how it should work. Just take a look at the hellosceneform example from Google (https://github.com/google-ar/sceneform-android-sdk/blob/master/samples/hellosceneform/app/src/main/java/com/google/ar/sceneform/samples/hellosceneform/HelloSceneformActivity.java).