当前位置: 首页 > 知识库问答 >
问题:

如何用重力定位Android Sceneform层中的GLTF

齐望
2023-03-14

我一直得到我的屁股踢尝试得到一个垂直放置的三维模型GLB格式正确放置在垂直表面。

为了澄清一点,我指的不是识别垂直表面的困难,这本身是一个完全不同的问题。

删除设置的常用样板以最小化此帖子。

class SceneFormARFragment: ArFragment() {
override fun getSessionConfiguration(session: Session?): Config {
    val config = super.getSessionConfiguration(session)
    // By default we are not tracking and tracking is driven by startTracking()
    config.planeFindingMode = Config.PlaneFindingMode.DISABLED
    config.focusMode = Config.FocusMode.AUTO
    return config
}
private fun startTracking() = viewScope.launchWhenResumed {
    try {
        arSceneView.session?.apply {
            val changedConfig = config
            changedConfig.planeFindingMode = Config.PlaneFindingMode.HORIZONTAL_AND_VERTICAL
            configure(changedConfig)
        }

        logv("startTracking")
        planeDiscoveryController.show()
        arSceneView.planeRenderer.isVisible = true
        arSceneView.cameraStreamRenderPriority = 7
    } catch (ex: Exception) {
        loge("error starting ar session: ${ex.message}")
    }
}
private fun stopTracking() = viewScope.launchWhenResumed {
    try {
        arSceneView.session?.apply {
            val changedConfig = config
            changedConfig.planeFindingMode = Config.PlaneFindingMode.DISABLED
            configure(changedConfig)
        }

        logv("stopTracking")
        planeDiscoveryController.hide()
        arSceneView.planeRenderer.isVisible = false
        arSceneView.cameraStreamRenderPriority = 0
    } catch (ex: Exception) {
        loge("error stopping ar session: ${ex.message}")
    }
}

如果你想知道“启动和停止”AR体验的原因,是为了最大限度地利用GPU周期进行其他UX交互,而这些交互在这个覆盖屏幕上很重,所以我们等待启动或停止的基础上,其他事情正在发生的当前实时数据状态。

好吧继续。

让我们回顾一下HitResult处理:在这个方法中,我做了几件事:

    null

差不多就是这样。水平放置效果很好,但垂直放置总是随机的。

下面的OnTapArPlane代码:

 private fun onARSurfaceTapped() {
    setOnTapArPlaneListener { hitResult, plane, _ ->
        var isHorizontal = false
        val renderable = when (plane.type) {
            Plane.Type.HORIZONTAL_UPWARD_FACING -> {
                isHorizontal = true
                standmountTVRenderable
            }
            Plane.Type.VERTICAL                 -> wallmountTVRenderable
            else                                -> {
                activity?.toast("Do you want it to fall on your head really?")
                return@setOnTapArPlaneListener
            }
        }

        lastSelectedPlaneOrientation = plane.type
        removeActive3DTVModel()

        val anchorNode = AnchorNode(hitResult.createAnchor())
        anchorNode.name = TV_ANCHOR_NAME
        anchorNode.setParent(arSceneView.scene)

        val tvNode = TransformableNode(this.transformationSystem)
        tvNode.scaleController.isEnabled = false
        tvNode.setParent(anchorNode)
        tvNode.name = TV_NODE_NAME
        tvNode.select()

        // Set orientation towards camera
        // Ref: https://github.com/google-ar/sceneform-android-sdk/issues/379
        val cameraPosition = arSceneView.scene.camera.worldPosition
        val tvPosition = anchorNode.worldPosition
        val direction = Vector3.subtract(cameraPosition, tvPosition)

        if(isHorizontal) {
            tvNode.translationController.allowedPlaneTypes.clear()
            tvNode.translationController.allowedPlaneTypes.add(Plane.Type.HORIZONTAL_UPWARD_FACING)
        } else {
            tvNode.translationController.allowedPlaneTypes.clear()
            tvNode.translationController.allowedPlaneTypes.add(Plane.Type.VERTICAL)
        }

        val lookRotation = Quaternion.lookRotation(direction, Vector3.up())
        anchorNode.worldRotation = lookRotation

        tvNode.renderable = renderable

        addVideoTo3DModel(renderable)
    }
}

忽略addvideoTo3dModel调用,因为它工作得很好,我把它注释掉只是为了确保它不起作用。

    null

我知道Sceneform很新,文档很糟糕,如果缺少内容或文档头,那就不存在了。开发人员一定不想让人们使用它,但我猜:(。

我要说的最后一件事是,在我当前的实现中,除了旋转的垂直放置之外,所有的工作都很完美。为了避免在这次讨论中出现兔子的痕迹,我没有任何其他问题。

哦,还有我注意到的最后一条线索。电视几乎是围绕垂直平面的中心旋转的,根据我点击的位置,底部几乎是指向平面的任意中心,如果这能帮助任何人弄清楚的话。

哦,是的,我知道我的纹理从GLB缺失了,我包装他们不正确,并打算修复它以后。

共有1个答案

梅修贤
2023-03-14

我终于明白了。花了一段时间和一些认真的试验和错误旋转每一个节点,轴,角度,和旋转之前,我终于得到它的位置很好。所以我将分享我的结果,以备其他人也需要。

当然,这是温和的主观的你如何握手机和它的理解周围的环境,但它总是相当该死的接近水平,现在在景观和肖像测试,没有失败,我做过。

这是我学到的。

val cameraPosition = arSceneView.scene.camera.worldPosition
val tvPosition = anchorNode.worldPosition
val direction = Vector3.subtract(cameraPosition, tvPosition)
val lookRotation = Quaternion.lookRotation(direction, Vector3.up())
anchorNode.worldRotation = lookRotation
val tvRotation = Quaternion.axisAngle(Vector3(1f, 0f, 0f), 90f)
tvNode.worldRotation = tvRotation
   setOnTapArPlaneListener { hitResult, plane, _ ->
                var isHorizontal = false
                val renderable = when (plane.type) {
                    Plane.Type.HORIZONTAL_UPWARD_FACING -> {
                        isHorizontal = true
                        standmountTVRenderable
                    }
                    Plane.Type.VERTICAL -> wallmountTVRenderable
                    else -> {
                        activity?.toast("Do you want it to fall on your head really?")
                        return@setOnTapArPlaneListener
                    }
                }

                lastSelectedPlaneOrientation = plane.type
                removeActive3DTVModel()

                val anchorNode = AnchorNode(hitResult.createAnchor())
                anchorNode.name = TV_ANCHOR_NAME
                anchorNode.setParent(arSceneView.scene)

                val tvNode = TransformableNode(this.transformationSystem)
                tvNode.scaleController.isEnabled = false //disable scaling
                tvNode.setParent(anchorNode)
                tvNode.name = TV_NODE_NAME
                tvNode.select()

                val cameraPosition = arSceneView.scene.camera.worldPosition
                val tvPosition = anchorNode.worldPosition
                val direction = Vector3.subtract(cameraPosition, tvPosition)

                //restrict moving node to active surface orientation
                if (isHorizontal) {
                    tvNode.translationController.allowedPlaneTypes.clear()
                    tvNode.translationController.allowedPlaneTypes.add(Plane.Type.HORIZONTAL_UPWARD_FACING)
                } else {
                    tvNode.translationController.allowedPlaneTypes.clear()
                    tvNode.translationController.allowedPlaneTypes.add(Plane.Type.VERTICAL)

                    //x 90 degree rotation to flat mount TV vertical with gravity
                    val tvRotation = Quaternion.axisAngle(Vector3(1f, 0f, 0f), 90f)
                    tvNode.worldRotation = tvRotation
                }

                //set anchor nodes world rotation to face the camera view and up
                val lookRotation = Quaternion.lookRotation(direction, Vector3.up())
                anchorNode.worldRotation = lookRotation

                tvNode.renderable = renderable
                viewModel.updateStateTo(AriaMainViewModel.ARFlowState.REPOSITIONING)
            }

这已经测试了相当彻底,没有任何问题,目前为止,肖像和景观。对于Sceneform,我还有其他一些问题,比如即使有一个有效的表面,点也只会出现大约一半的时间,当然,在一个单色墙壁上的垂直检测是不可能的,如果没有墙上的图片或者其他东西来区分墙壁的话,用当前的SDK是不可能的。

此外,执行截图是不好的,因为它不包括3D模型,所以需要的自定义像素复制工作和我的截图有点慢,但至少他们工作,不感谢SDK。

因此,他们还有很长的路要走,在产品上开拓道路是令人沮丧的,缺乏文档,对客户服务和GitHub日志问题的响应能力明显不足,但至少我得到了它,我希望这能帮助其他人。

编码快乐!

 类似资料:
  • 本文向大家介绍js中的如何定位固定层的位置,包括了js中的如何定位固定层的位置的使用技巧和注意事项,需要的朋友参考一下 需要获取一些HTML的对象的坐标来更灵活的设置目标层的坐标,这里可以通过用到document.body.scrollTop等属性,但是这些属性在xhtml的标准网页中或更简单的说就是带<!DOCTYPE...>的标签中得到的值是0;如果不要此标签则一切正常,那么在xhtml中如何

  • 问题内容: 假设您有以下HTML: 请注意,层次结构是平坦的。 现在尝试选择元素的“中间对” 。这可能吗?我真的不知道怎么做。 此选择器仅获取后面的第一个: 但是此选择器将获取正确的元素对 以及我们想要的对之后出现的所有以下元素: 可能吗? 没有JavaScript。 没有标记更改。通用解决方案。允许任意数量的s或s,在这种情况下,数量2是任意的。 我在想使用选择器使用某些方法是可能的,但我似乎无

  • 问题内容: 我正在尝试使curl遵循重定向,但无法完全正常工作。我有一个字符串,我想将它作为GET参数发送到服务器并获取结果URL。 例: 字符串= Kobold害虫 网址= _www.wowhead.com/search?q=Kobold+Worker_ 如果您转到该URL,它将把您重定向到“ www.wowhead.com/npc=257”。我希望curl将此URL返回到我的PHP代码,以便我

  •     如果说CALayer是UIView内部实现细节,那我们为什么要全面地了解它呢?苹果当然为我们提供了优美简洁的UIView接口,那么我们是否就没必要直接去处理Core Animation的细节了呢?     某种意义上说的确是这样,对一些简单的需求来说,我们确实没必要处理CALayer,因为苹果已经通过UIView的高级API间接地使得动画变得很简单。     但是这种简单会不可避免地带来一

  • 我正在为一个移动应用程序创建一个多页面表单,以帮助用户烹饪意大利面。我需要以用户选择的单选按钮值为目标,以便在计算所需水量和面食量的公式中使用该值。提交表单后将触发计算。“提交”按钮尚未编码。

  • 我使用JAX-RS和Spring Boot和springfox从注释生成swagger-ui。 目前这些文档位于http://localhost:8080/swagger-ui.html 但是,我现在需要将其移动到http://localhost:8080/api/index.html 如果我为找到/替换上面的代码,我就有另一个问题,因为我的servlet已经在/api中定义了。 我如何将swag