我正在遵循谷歌的地理空间示例,并成功地在给定坐标下创建了3D模型网格. 现在我已经实现了命中测试并获得了结果,但我不知道如何检测它是否命中网格

我try 过这样的代码,但没有成功

    if (motionEvent != null) {
        //val hitResultList = frame.hitTestInstantPlacement(motionEvent!!.x, motionEvent!!.y, 2.0f)
        val hitResultList = frame.hitTest(motionEvent)
        val debug = hitResultList.toString()
        if (hitResultList.size > 0) {
            Log.d(TAG, debug)

            for (hit in hitResultList){

                val trackable = hit.trackable
                Log.d(TAG, trackable.toString())


                if (hit.equals(virtualObjectMesh)){
                    Log.d(TAG, "tapped!")
                }
                if (hit.equals(earthAnchor)){
                    Log.d(TAG, "tapped!")
                }
            }
        }
        motionEvent = null
    }

推荐答案

根据我在文档中看到的("ARCore / Perform hit-tests in your Android app"),要在Arcore或类似的AR平台中检测HitTest结果是否命中给定的Mesh object,您需要将从命中结果获得的TrackableMesh的实例或您感兴趣的对象进行比较.

However, directly comparing HitResult objects with your Mesh using equals is not the correct approach, as HitResult and your Mesh object are different types of objects.
See "Comparing Objects in Java" from François Dupire and reviewed by Greg Martin

相反,您应该判断与每个HitResult关联的Trackable中的type,以确定它是否属于您预期的类型(例如,PlanePoint),然后,如果您的Mesh对象连接到Anchor或具有某些可识别的特征,您应该使用这些特征来确定命中测试是否与您的Mesh相交.

if (motionEvent != null) {
    val hitResultList = frame.hitTest(motionEvent)
    if (!hitResultList.isEmpty()) {
        for (hit in hitResultList) {
            val trackable = hit.trackable

            // Assuming your mesh is associated with an Anchor
            if (trackable is Anchor && trackable == yourMeshAnchor) {
                Log.d(TAG, "Mesh tapped!")
            }

            // If you are looking for hits on specific types of trackables, like Planes
            if (trackable is Plane) {
                Log.d(TAG, "Plane tapped!")
                // Further checks can be done here to see if this Plane is related to your mesh
            }

            // If you have other conditions or objects to check, do so here
        }
    }
    motionEvent = null
}

在这里,yourMeshAnchor应该是您将Mesh放置在AR场景中时使用的Anchor.

在这里,yourMeshAnchor应该是您将Mesh放置在AR场景中时使用的Anchor.

因此,识别命中测试是否与特定的Mesh相交的确切方法取决于您的Mesh如何集成到AR场景中,以及您正在使用的AR平台的功能.如果你的Mesh是一个自定义对象,在ARCore中不直接支持Trackable类型,你可能需要实现额外的逻辑来映射Trackable对象和你的自定义对象.


I have changed my code according to your suggestion, I get only Plane and Point trackable types, but I never get an Anchor type...
Btw, I have a terrain anchor with a custom obj model attached ... I'm using ARCore Geospatial.

In ARCore, when you perform a hit test, the API returns HitResult objects that reference Trackable types like Plane and Point. These represent real-world surfaces and points that ARCore has detected.
Anchors, however, are not directly returned as part of hit test results; instead, they are used to create stable positions in the world for placing objects.

当您将自定义OBJ模型附加到地形锚点时,命中测试不会直接指示对"锚点"本身的命中,而是指示对锚点和模型所在的可跟踪表面(如平面)的命中.

考虑到您的Arcore地理空间方案,了解地理空间锚点用于在真实世界坐标中定位内容非常重要,但检测与附加到这些锚点的内容(如自定义模型)的交互需要将命中测试结果映射到定位的内容.

换句话说:挑战是确定由用户的touch 输入发起的命中测试是否与定制对象(例如,3D模型)相交,该定制对象并不直接对应于Arcore的命中测试通常检测到的Trackable个对象(PlanePoint)的类型.

完整的逻辑包括两个主要步骤:

  1. Performing the Hit Test:捕获用户的touch 输入并使用它执行命中测试,该测试返回HitResult个对象的列表.
  2. Mapping Hit Test Results to Anchored Content:确定这些命中测试结果中是否有任何与锚定的3D模型的位置和边界相交.

这将涉及:

  • 检测用户何时touch 屏幕并获得MotionEvent.
  • 使用此MotionEvent可以对AR场景执行命中测试,该测试将返回HitResult个对象的列表.这些对象表示AR世界中Trackable个曲面的交点.
  • 对于每个点击结果,提取点击的pose(空间中的位置和方向).
  • 对于每个点击姿势,判断它是否落在锚定模型的空间范围内.这涉及到将命中姿势与模型的锚定姿势和模型的预定义边界进行比较.
    • 了解模型相对于其锚点的空间维度和边界.它可以是一个简单的边框,也可以是一个更复杂的形状,准确地包围您的模型.
    • 计算命中姿势是否在这些范围内,并将锚的姿势作为模型在AR世界中位置的参考点.
  • 如果确定命中测试结果在模型的范围内,则执行所需的交互逻辑(例如,突出显示模型、显示信息等).
// Assuming you have access to `frame` from ARCore and a `motionEvent` from user input

// A function to check if a hit test point is within your model's bounds
fun isHitWithinModelBounds(hitPose: Pose, modelAnchorPose: Pose, modelBounds: ModelBounds): Boolean {
    // Implement logic here to determine if the hitPose falls within the modelBounds
    // relative to the modelAnchorPose
    return false // Example implementation; replace with actual logic
}

// Define the model's bounds relative to its anchor
val modelBounds = getModelBounds() // Assume this function defines the 3D model's bounds
val yourTerrainAnchorPose = yourTerrainAnchor.pose // Pose of your terrain anchor

if (motionEvent != null) {
    val hitResultList = frame.hitTest(motionEvent)
    for (hit in hitResultList) {
        val hitPose = hit.hitPose
        // Check if the hit is within the bounds of your model
        if (isHitWithinModelBounds(hitPose, yourTerrainAnchorPose, modelBounds)) {
            Log.d(TAG, "Custom model tapped!")
            // Perform your interaction logic here (e.g., highlight the model, show details, etc.)
        }
    }
    motionEvent = null // Reset the motion event to avoid processing it multiple times
}

getModelBounds()是一个假设函数,您可以根据3D模型的特定尺寸和形状来实现.

isHitWithinModelBounds(hitPose, modelAnchorPose, modelBounds)判断给定的命中测试结果是否在模型的定义边界内,并将模型的锚定姿势视为参考点.通过hitResultList的循环计算每个命中测试结果以确定它是否与模型交互.

Android相关问答推荐

当我的Log.i()不在主线程中时,如何在我的logcat中显示它?

将Android Studio插件复制到离线网络

Jetpack Compose-如何使用值动画直接控制其他动画

穿戴与iPhone连接的安卓操作系统

无法加载类';com.android.build.api.extension.AndroidComponentsExtension';

OutlinedTextField仅显示一次

是否可以附加事件处理程序,如onClick,拖动到Canvas Composable中绘制的内容,或使用drawBehind修饰符?

学习Kotlin问题.无法理解Modifier参数

Android 12+BLE字节不同

如何使用 Wea​​r OS 上的运行状况服务模拟位置?

如何删除 Jetpack Compose 中按钮的左边框?

为卡片的上半部分添加一个边框,用圆角半径组合

在 theme.xml 中使用 android:autoCompleteTextViewStyle

处理程序 postDelayed 方法不起作用,kotlin 应用程序卡在启动画面上

Kotlin 调用带参数的函数 Any is xxx ||任何 yyy 都不起作用

协程是否在 if 条件下保持秩序?

如何在包含 Jetpack Compose 内容的布局中使用权重

在 Android Studio 中替换字符串中的 "

如何满足设备内框架的无效 Wear OS 屏幕截图Wear OS 表盘策略违规?

无法再查看 Jetpack Compose 预览.无法实例化一个或多个类 (ComposeViewAdapter)