Обнаружение самолетов и событий касания с ARCore

Я пытаюсь понять Google ARCore API и подтолкнул их образец проекта (java_arcore_hello_ar) в GitHub.

В этом примере при развертывании приложения на Android обнаруживаются любые горизонтальные поверхности / плоскости. Если вы нажмете на обнаруженный самолет, «Энди» робот Андрид будет отображаться в том месте, которое вы коснетесь. Довольно круто.

Я пытаюсь найти где в коде:

  1. Обнаруживается горизонтальная поверхность / плоскость; а также
  2. Там, где живет логика, чтобы правильно изменить размер и переориентировать Энди (я предполагаю, что если точка, которую вы нажимаете, находится дальше от камеры, он будет отображаться маленьким и т. Д.)

Я верю, что при обнаружении самолетов платформа Android вызывает метод onSurfaceCreated:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1.0f);

    // Create the texture and pass it to ARCore session to be filled during update().
    mBackgroundRenderer.createOnGlThread(/*context=*/this);
    mSession.setCameraTextureName(mBackgroundRenderer.getTextureId());

    // Prepare the other rendering objects.
    try {
        mVirtualObject.createOnGlThread(/*context=*/this, "andy.obj", "andy.png");
        mVirtualObject.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);

        mVirtualObjectShadow.createOnGlThread(/*context=*/this,
            "andy_shadow.obj", "andy_shadow.png");
        mVirtualObjectShadow.setBlendMode(BlendMode.Shadow);
        mVirtualObjectShadow.setMaterialProperties(1.0f, 0.0f, 0.0f, 1.0f);
    } catch (IOException e) {
        Log.e(TAG, "Failed to read obj file");
    }
    try {
        mPlaneRenderer.createOnGlThread(/*context=*/this, "trigrid.png");
    } catch (IOException e) {
        Log.e(TAG, "Failed to read plane texture");
    }
    mPointCloud.createOnGlThread(/*context=*/this);
}

Однако этот код выглядит, предполагается, что пользователь уже коснулся поверхности. Я не вижу if-условия, которое в основном говорит: «Визуализировать Энди , если пользователь нажал на обнаруженную плоскость / поверхность.». Может ли кто-нибудь заметить, где это может происходить?


person smeeb    schedule 11.09.2017    source источник


Ответы (1)


Обнаружение касания осуществляется в mGestureDetector:

mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        onSingleTap(e);
        return true;
    }

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
});

Это связано с SurfaceView

mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
    }
});

И то, и другое происходит в onCreate(), поэтому теперь каждый раз, когда вы нажимаете на вид поверхности («основной» вид в действии),

private void onSingleTap(MotionEvent e) {
    // Queue tap if there is space. Tap is lost if queue is full.
    mQueuedSingleTaps.offer(e);
}

вызывается, и кран сохраняется. Затем эта очередь обрабатывается в каждом отрисовке кадра (который, в свою очередь, выдается циклом отрисовки пользовательского интерфейса системы) здесь

MotionEvent tap = mQueuedSingleTaps.poll();
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
    for (HitResult hit : frame.hitTest(tap)) {
       ...

Это добавляет новый якорь (то есть точку, "заблокированную" в физическом мире "), в которой отображается объект Android .

person PhilLab    schedule 11.09.2017
comment
Спасибо @PhilLab (+1) - значит, вы говорите, что прослушиватель касаний GLSurfaceView - это то место, где ARCore может обнаруживать события касания для данной поверхности / плоскости? Если да, то как этот код связан с методом onSurfaceCreated (который вызывается первым - ›прослушиватель касаний onTouch или onSurfaceCreated)? - person smeeb; 11.09.2017
comment
слушатель касания только добавляет касание в очередь обработки. Из которого он затем опрашивается в методе рисования - person PhilLab; 11.09.2017
comment
Спасибо @PhilLab (снова +1) Я следую большей части из того, что вы говорите, за исключением одного: где (конкретно) приложение / фреймворк обнаруживает, что пользователь коснулся определенной плоскости (в отличие от простого нажатия на что-то, что не является плоскостью и, следовательно, не может привести к рендерингу Энди на этом)? Спасибо еще раз! - person smeeb; 12.09.2017
comment
Да, сегодня утром я еще раз взглянул на ваш ответ и код, и я думаю, что мы определенно упускаем кое-что здесь. Во-первых, я думаю, нам нужно уточнить, что такое GLSurfaceView. Прочитав его Javadocs, я не понимаю, представляет ли он (обнаруженную) плоскую / горизонтальную плоскость или просто представляет внешнюю текстуру любого (плоского или другого) 3D-объекта. После того, как я это пойму, код станет для меня немного понятнее! - person smeeb; 12.09.2017
comment
Но даже в этом случае я все еще думаю, что должен быть код где-то, который смотрит на кран (который, как я предполагаю, является экземпляром MotionEvent) и подтверждает, что касание действительно произошло над / в месте, где плоская плоскость была обнаружена. Я ищу, где происходит эта проверка ... есть идеи? Еще раз большое спасибо! - person smeeb; 12.09.2017
comment
Это frame.hitTest(tap) - person PhilLab; 13.09.2017