因此,我一直努力将垂直放置的3D模型GLB格式正确放置在垂直表面上。
请注意,我并不是指确定垂直表面的困难,这本身就是另外一个问题。
删除安装程序的通用样板以最小化此职位。
我正在使用扩展ARFragment的片段。
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
}
并且为了开始和停止我的AR体验,我在片段中编写了一些方法,如下所示。
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体验的原因是为了最大化在此重叠屏幕上很繁重的其他UX交互的GPU周期,那么我们将根据当前的实时数据状态等待启动或停止其他正在发生的事情。
继续前进。
让我们回顾一下HitResult处理:在这种方法中,我做了几件事:
就是这样。水平放置效果很好,但垂直放置始终是随机的。
下面的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调用,因为它可以正常工作,我对此进行了评论只是为了确保它不起作用。
我尝试过的事情。
所以我用尽了互联网。我剩下的就是问社区,当然也要向Android的SceneForm团队发送帮助。
任何帮助或建议将不胜感激。
我的最佳猜测是我需要执行Quaternion.axisRotation(Vector3,Float),但是我所猜测或尝试并出错的所有方法均无效。我想我需要使用手机的xyz的worldPostion值来设置localRotation,以帮助识别重力。我真的不知道了,哈哈。
非常感谢任何可以提供帮助的人。我知道Sceneform相当新,文档是HORRIBLE,并且由于缺少内容或文档标头而可能不存在。开发人员必须确实不希望人们使用它,但我正在猜测:(。
最后,我要说的是,除了旋转的垂直放置,其他所有东西在我当前的实现中都运行良好。只是为了避免在此讨论中遇到麻烦,我没有任何其他问题。
哦,我注意到的最后一条线索。根据我轻按的位置,电视似乎几乎围绕垂直平面的中心旋转,底部似乎几乎指向平面的任意中心,如果这样可以帮助任何人找出来。
哦,是的,我知道GLB中缺少我的纹理,我包装不正确,打算以后再修复。
当然,它在一定程度上取决于您如何握住手机以及对周围环境的了解,但是现在在接近水平的情况下总是相当不错,而我所做的横向和纵向测试都没有失败。
所以这就是我所学到的。
在anchorNode上设置worldRotation将有助于使3DModel稍加减法即可朝向cameraview。
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
但是,这不能解决垂直放置的方向问题。我发现,如果对外观旋转进行X旋转90度递减,则每次都能正常工作。根据您的3D模型,它可能会有所不同,但是我的锚点位于中后中间位置,因此我不确定它如何确定向上的方向。但是,我注意到每当在tvNode上设置worldRotation时,它将放置电视级别,但会向前倾斜90度。因此,在进行了各种旋转之后,我终于得到了答案。
val tvRotation = Quaternion.axisAngle(Vector3(1f, 0f, 0f), 90f)
tvNode.worldRotation = tvRotation
这解决了我的问题。因此,onSurfaceTap和放置的最终结果是:
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模型,因此所需的自定义Pixel Copy工作和我的屏幕截图有些慢,但是至少可以使用,不用了SDK。所以他们还有很长的路要走,令人沮丧的是他们的产品,缺乏文档,对客户服务以及GitHub记录的问题都缺乏响应能力,这令人沮丧,但是,至少我明白了,我希望这可以帮助其他人。
快乐编码!