Обнаружение, если событие касания с ARCore попадает в уже добавленный 3D-объект

Я следую образцу ARCore (https://github.com/google-ar/arcore-android-sdk), и я пытаюсь удалить уже добавленный объект 3d (andy). Как я могу определить, попадает ли событие касания с ARCore в уже добавленный 3D-объект?


person Vinicius Sossella    schedule 13.10.2017    source источник


Ответы (4)


Использование listener является довольно распространенным подходом в такой ситуации:

private Node getModel() {
    Node node = new Node();
    node.setRenderable(modelRenderable);
    Context cont = this;
    node.setOnTapListener((v, event) -> {
        Toast.makeText(
            cont, "Model was touched", Toast.LENGTH_LONG)   // Toast Notification 
            .show();
    });
    return node;
}
person Andy Fedoroff    schedule 20.04.2019

У меня был тот же вопрос в эти дни, я пробовал 2 решения,

1. frame.hitTest(MotionEvent)

2. спроецировать вершину из мира arcore в двухмерную координату в поле зрения

Сначала я использую 1., чтобы получить позу удара на плоскости и сравнить с позой уже существующего 3D-объекта, но как только 3D-объект покинул плоскость, это не сработает.

В конце концов, я использую 2., чтобы получить вершину трехмерного объекта в поле зрения, а затем выполнить тест на попадание с позицией касания.

Если вы следуете образцу ARCore, вы можете увидеть эту строку в методе рисования ObjectRenderer.java.

Matrix.multiplyMM(mModelViewProjectionMatrix, 0, 
                  cameraPerspective, 0, mModelViewMatrix, 0);

«mModelViewProjectionMatrix» просто использует эту матрицу ModelViewProjection для сопоставления вершин вашего уже добавленного 3D-объекта из 3D-мира arcore в 2D-представление.

В моем случае я делаю что-то вроде этого,

pose.toMatrix(mAnchorMatrix, 0);
objectRenderer.updateModelMatrix(mAnchorMatrix, 1);
objectRenderer.draw(cameraView, cameraPerspective, lightIntensity);

float[] centerVertexOf3dObject = {0f, 0f, 0f, 1};
float[] vertexResult = new float[4];
Matrix.multiplyMV(vertexResult, 0, 
                  objectRenderer.getModelViewProjectionMatrix(), 0, 
                  centerVertexOf3dObject, 0);
// circle hit test
float radius = (viewWidth / 2) * (cubeHitAreaRadius/vertexResult[3]);
float dx = event.getX() - (viewWidth / 2) * (1 + vertexResult[0]/vertexResult[3]);
float dy = event.getY() - (viewHeight / 2) * (1 - vertexResult[1]/vertexResult[3]);
double distance = Math.sqrt(dx * dx + dy * dy);
boolean isHit = distance < radius;

Я использую это в приложении ARCore Measure,
https://play.google.com/store/apps/details?id=com.hl3hl3.arcoremeasure

и исходный код, https://github.com/hl3hl3/ARCoreMeasure/blob/master/app/src/main/java/com/hl3hl3/arcoremeasure/ArMeasureActivity.java

person Rebecca Hsieh    schedule 18.10.2017

Вы можете просто добавить слушателя к узлу, где был добавлен ваш объект.

    node.setOnTapListener((v, event) -> {
        showMessage("tap happened");
    });
person rafavila    schedule 03.04.2019

В дополнение к другим подходам, описанным в других ответах, вы также можете проверить hitTestResult, чтобы увидеть, включает ли он узел (это Kotlin, но те же подходы применимы и для Java):

 if (hitTestResult.getNode() != null) {
    //We have hit an AR node
    Log.d(TAG, "hitTestResult.getNode() != null: " + hitTestResult.getNode());
    var hitNode: Node? = hitTestResult.node

    //You can add additional checks to see if it is a particuar type if renderable for example
    if (hitNode?.renderable == yourRenderable1) {
    //Do whatever you want if this renderable type is hit

    }
 } else {
    //We have not hit an ARNode - add your 
    //code here for this case....

 }
person Mick    schedule 04.01.2021