简体   繁体   English

如何在 Android SceneForm 中使用 DragGesture 旋转 3D model

[英]How to rotate an 3D model using DragGesture in Android SceneForm

I followed the solution here for rotating a TransformableNode on the X axis based on the user's DragGesture , using the Sceneform Android SDK .我按照此处的解决方案,使用Sceneform Android SDK根据用户的DragGesture在 X 轴上旋转TransformableNode However, I would also like to rotate on the Y and Z axis as well, similar to how ARCore SceneViewer does it.但是,我也想在 Y 轴和 Z 轴上旋转,类似于 ARCore SceneViewer 的操作方式。

How can I achieve that?我怎样才能做到这一点?

What I have currently is on the left (rotates only on X axis), and what is desired is on the right (rotates on all axes, as in ARCore Scene Viewer).我目前拥有的在左侧(仅在 X 轴上旋转),而所需的在右侧(在所有轴上旋转,如在 ARCore Scene Viewer 中)。

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)

        // *** this only rotates on X axis. How do I rotate on all axes? ***

        transformableNode.localRotation = localRotation
    }

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

I was able to find a working solution here: https://github.com/chnouman/SceneView我能够在这里找到一个可行的解决方案: https://github.com/chnouman/SceneView

Here are the relevant snippets of code, with some of my adaptations to make it work for .glb files.以下是相关的代码片段,以及我的一些改编以使其适用于.glb文件。

I have forked this repo and am working on keyboard input support if anyone's interested in that.如果有人对此感兴趣,我已经分叉了这个 repo 并正在研究键盘输入支持。

Rendering the object:渲染 object:

private fun renderLocalObject() {

        skuProgressBar.setVisibility(View.VISIBLE)
        ModelRenderable.builder()
            .setSource(this,
                RenderableSource.builder().setSource(
                    this,
                    Uri.parse(localModel),
                    RenderableSource.SourceType.GLB)/*RenderableSource.SourceType.GLTF2)*/
                    .setScale(0.25f)
                    .setRecenterMode(RenderableSource.RecenterMode.ROOT)
                    .build())
            .setRegistryId(localModel)
            .build()
            .thenAccept { modelRenderable: ModelRenderable ->
                skuProgressBar.setVisibility(View.GONE)
                addNodeToScene(modelRenderable)
            }

Adding the object to the SceneView :将 object 添加到SceneView

private fun addNodeToScene(model: ModelRenderable) {
        if (sceneView != null) {
            val transformationSystem = makeTransformationSystem()
            var dragTransformableNode = DragTransformableNode(1f, transformationSystem)
            dragTransformableNode?.renderable = model
            sceneView.getScene().addChild(dragTransformableNode)
            dragTransformableNode?.select()
            sceneView.getScene()
                .addOnPeekTouchListener { hitTestResult: HitTestResult?, motionEvent: MotionEvent? ->
                    transformationSystem.onTouch(
                        hitTestResult,
                        motionEvent
                    )
                }
        }
    }

Custom TransformableNode :自定义TransformableNode

class DragTransformableNode(val radius: Float, transformationSystem: TransformationSystem) :
    TransformableNode(transformationSystem) {
    val dragRotationController = DragRotationController(
        this,
        transformationSystem.dragRecognizer
    )
}

Custom TransformationController :自定义TransformationController

class DragRotationController(
        private val transformableNode: DragTransformableNode,
        gestureRecognizer: DragGestureRecognizer
) :
    BaseTransformationController<DragGesture>(transformableNode, gestureRecognizer) {

    companion object {

        private const val initialLat = 26.15444376319647
        private const val initialLong = 18.995950736105442

        var lat: Double = initialLat
        var long: Double = initialLong
    }

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

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

    private fun getX(lat: Double, long: Double): Float {
        return (transformableNode.radius * Math.cos(Math.toRadians(lat)) * Math.sin(Math.toRadians(long))).toFloat()
    }

    private fun getY(lat: Double, long: Double): Float {
        return transformableNode.radius * Math.sin(Math.toRadians(lat)).toFloat()
    }

    private fun getZ(lat: Double, long: Double): Float {
        return (transformableNode.radius * Math.cos(Math.toRadians(lat)) * Math.cos(Math.toRadians(long))).toFloat()
    }

    override fun onActivated(node: Node?) {
        super.onActivated(node)
        Handler().postDelayed({
            transformCamera(lat, long)
        }, 0)
    }

    public override fun onContinueTransformation(gesture: DragGesture) {

        val rotationAmountY = gesture.delta.y * rotationRateDegrees
        val rotationAmountX = gesture.delta.x * rotationRateDegrees
        val deltaAngleY = rotationAmountY.toDouble()
        val deltaAngleX = rotationAmountX.toDouble()

        long -= deltaAngleX
        lat += deltaAngleY

        //lat = Math.max(Math.min(lat, 90.0), 0.0)

        transformCamera(lat, long)
    }

    private fun transformCamera(lat: Double, long: Double) {
        val camera = transformableNode.scene?.camera

        var rot = Quaternion.eulerAngles(Vector3(0F, 0F, 0F))
        val pos = Vector3(getX(lat, long), getY(lat, long), getZ(lat, long))
        rot = Quaternion.multiply(rot, Quaternion(Vector3.up(), (long).toFloat()))
        rot = Quaternion.multiply(rot, Quaternion(Vector3.right(), (-lat).toFloat()))
        camera?.localRotation = rot
        camera?.localPosition = pos
    }

    fun resetInitialState() {
        transformCamera(initialLat, initialLong)
    }



    public override fun onEndTransformation(gesture: DragGesture) {}


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Sceneform生态系统有问题地旋转3D模型 - Problematically rotate 3D model using Sceneform ecosystem 使用sceneform arcore android将文本添加到3d模型 - Adding text to a 3d model using sceneform arcore android Android AR 场景。 随着相机移动 3D model 移动。 3D model 应与底部对齐 - Android AR Sceneform. Moving 3D model along with Camera moving. 3D model should be align to the bottom 使用Android SceneForm以编程方式将2D图像转换为可渲染的3D - Programmatically convert 2D image to 3D renderable using android sceneform 谷歌场景表格 3D 导入 - Google sceneform 3D import Libgdx如何通过电话方向在多个轴上旋转3D模型 - Libgdx How to rotate a 3D model on multiple axes with phone orientation 如何旋转使用ARCORE SceneView渲染的3D模型 - how to rotate a 3d model rendered with ARCORE SceneView 如何在Android中使用Gesture Listener旋转和拖动Kudan中的3D对象(ARNode) - How to rotate and drag 3D object(ARNode) in Kudan using Gesture Listener in Android 如何旋转标签以及使用openGl和android创建的3d立方体。 - How to rotate labels along with 3d cube created using openGl and android. 如何在Android中的ListView和ImageView之间创建旋转3D动画? - How to create a rotate 3D Animation between a ListView and an ImageView in Android?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM