google-ar / arcore-android-sdk

ARCore SDK for Android Studio
https://developers.google.com/ar
Other
4.91k stars 1.2k forks source link

ARCore Android Studio- How to place 2d textiew on back of the 3d Model android and rotate? #1598

Open gptshubham595 opened 11 months ago

gptshubham595 commented 11 months ago

I have a 3d model and a viewRenderable layout

This is how i loaded the model

model = ModelRenderable.builder()
            .setSource(
                requireContext(),
                RenderableSource.builder()
                    .setSource(
                        requireContext(),
                        Uri.parse(path),
                        RenderableSource.SourceType.GLB
                    )
                    .setScale(scale)
                    .setRecenterMode(RenderableSource.RecenterMode.ROOT)
                    .build()
            )
            .build()

After loading the model I am trying to add it in the sceneview

   model?.thenAccept { modelRenderable ->
        addModelToScene(arFragment, anchor, modelRenderable)
    }

Here I have two nodes transformableNode(3dBadge) and textWrittenOverBadgeNode I have added setParent for textWrittenOverBadgeNode as transformableNode

 private fun addModelToScene(
        arFragment: CustomARCameraFragment,
        anchor: Anchor?,
        modelRenderable: ModelRenderable?,
    ) {
        val anchorNode = anchor?.let { AnchorNode(it) }

    val transformableNode =
        TransformableNode(arFragment.transformationSystem)
    transformableNode.localPosition = Vector3(0f, 0.2f, -0.2f)
    transformableNode.renderable = modelRenderable
    transformableNode.setParent(anchorNode)

 val textWrittenOverBadgeNode = Node()

        ViewRenderable.builder().setView(requireContext(), R.layout.layout_ar_write_over_model)
            .build()
            .thenAccept {
                textWrittenOverBadgeNode.renderable = it
                it.renderPriority = 0
                textWrittenOverBadgeNode.worldRotation = transformableNode.worldRotation

                textWrittenOverBadgeNode.setParent(transformableNode)
            }

This is how my layout looks like

<LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical">

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/tv_bullet_text"
            style="@style/text_24_gentona_bold_black_86"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#fff"
            android:elevation="12dp"
            android:paddingStart="2dp"
            android:paddingEnd="2dp"
            android:shadowColor="#402702"
            android:shadowDx="2"
            android:shadowDy="2"
            android:shadowRadius="5"
            android:text="HELLO" />
    </LinearLayout>

Now I'm rotating the text and object

val animator = createAnimator()
        animator?.target = transformableNode
        animator?.start()

But both text and badge is not aligned properly

private fun createAnimator(): ObjectAnimator? {
        // Node's setLocalRotation method accepts Quaternions as parameters.
        // First, set up orientations that will animate a circle.
        val orientation1 = Quaternion.axisAngle(Vector3(0.0f, 1.0f, 0.0f), 0f)
        val orientation2 = Quaternion.axisAngle(Vector3(0.0f, 1.0f, 0.0f), 120f)
        val orientation3 = Quaternion.axisAngle(Vector3(0.0f, 1.0f, 0.0f), 240f)
        val orientation4 = Quaternion.axisAngle(Vector3(0.0f, 1.0f, 0.0f), 360f)
        val orbitAnimation = ObjectAnimator()
        orbitAnimation.setObjectValues(orientation1, orientation2, orientation3, orientation4)

        // Next, give it the localRotation property.
        orbitAnimation.setPropertyName("localRotation")

        // Use Sceneform's QuaternionEvaluator.
        orbitAnimation.setEvaluator(QuaternionEvaluator())

        //  Allow orbitAnimation to repeat forever
        orbitAnimation.repeatCount = ObjectAnimator.INFINITE
        orbitAnimation.repeatMode = ObjectAnimator.RESTART
        orbitAnimation.duration = 4500
        orbitAnimation.interpolator = LinearInterpolator()

        orbitAnimation.setAutoCancel(true)
        return orbitAnimation
    }

enter image description here