Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ARCoreでsurfaceviewに配置した画像にタッチイベントを付加したい。何かいい方法はありませんか?

解決したいこと

surfaceviewに配置した画像にタッチイベントを付加したい。

発生している問題・エラー

サーフェースビューのタッチイベントで、オブジェクトへのタッチを検出したいのですが、
スクリーン座標を仮想オブジェクトのワールド座標へ変換をどうしたら良いか?
また、どうやって当たり判定すれば良いか?わかりません。SceanViewをで使用するのかもしれませんが、次のプログラムは、frameの設定がわかりません。
どなたかわかる方、お願いします。プログラムは、公式のCloud_anchorを使っています。

List<HitResult> hitResults = frame.hitTest(touchX, touchY);
                            for (HitResult hit : hitResults) {
                              Log.i("test",hit.createAnchor().toString());
                              // トラックポイントに対する処理を行う
                              // 例えば、トラックポイントに仮想オブジェクトがヒットした場合、そのオブジェクトに対する操作を行う
                            }

例)

NameError (uninitialized constant World)

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    surfaceView = findViewById(R.id.surfaceview);
    surfaceView.getHolder().addCallback(this);
    displayRotationHelper = new DisplayRotationHelper(this);



    // Set up renderer.
    surfaceView.setPreserveEGLContextOnPause(true);
    surfaceView.setEGLContextClientVersion(2);
    surfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); // Alpha used for plane blending.
    surfaceView.setRenderer(this);
    surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    surfaceView.setWillNotDraw(false);
    installRequested = false;

    // Initialize UI components.
    hostButton = findViewById(R.id.host_button);
    hostButton.setOnClickListener((view) -> onHostButtonPress());
    resolveButton = findViewById(R.id.resolve_button);
    resolveButton.setOnClickListener((view) -> onResolveButtonPress());
    roomCodeText = findViewById(R.id.room_code_text);

    // Initialize Cloud Anchor variables.
    firebaseManager = new FirebaseManager(this);
    currentMode = HostResolveMode.NONE;
    sharedPreferences = getSharedPreferences(PREFERENCE_FILE_KEY, Context.MODE_PRIVATE);





    // Set up touch listener.
    gestureDetector =
            new GestureDetector(
                    this,
                    new GestureDetector.SimpleOnGestureListener() {
                      @Override
                      public boolean onSingleTapUp(MotionEvent e) {
                        // タッチ位置を取得
                        float touchX = e.getX();
                        float touchY = e.getY();

                        Log.i("test",touchX+","+touchY);
                        // タッチアクションの種類を判定
                        int action = e.getAction();

                        switch (action) {
                          case MotionEvent.ACTION_DOWN:
                            // タッチ開始時の処理
                            // タッチイベントからトラックポイントを取得する
                            List<HitResult> hitResults = frame.hitTest(touchX, touchY);
                            for (HitResult hit : hitResults) {
                              Log.i("test",hit.createAnchor().toString());
                              // トラックポイントに対する処理を行う
                              // 例えば、トラックポイントに仮想オブジェクトがヒットした場合、そのオブジェクトに対する操作を行う
                            }

                            break;
                          case MotionEvent.ACTION_MOVE:
                            // タッチ中の処理
                            break;
                          case MotionEvent.ACTION_UP:
                            // タッチ終了時の処理
                            break;
                          default:
                            break;
                        }
                        synchronized (singleTapLock) {
                          if (currentMode == HostResolveMode.HOSTING) {
                            queuedSingleTap = e;
                          }
                        }
                        return true;
                      }

                      @Override
                      public boolean onDown(MotionEvent e) {
                        return true;
                      }
                    });
    surfaceView.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event));
   
  }

例)

def greet
  puts Hello World
end

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。

0

1Answer

まずframeですが、こちらはonDrawFrame()にてsession.update()から取得したものがhandleTapに渡ってきています。

次に、こちらはちょっと検証していないのでわからないですが、frame.hitTestは地面や壁との当たり判定を行うメソッドで、配置したオブジェクトとの当たり判定はしていないように見受けられます。

もしHitResultの中にオブジェクトとの当たり判定結果も含まれているのであれば、それをそのまま使えばいいと思います。

frame.hitTest()がオブジェクトの当たり判定を行っていない場合、自前で「タップ座標から3D空間座標に変換する当たり判定」を実装する必要があります。

ですが、これを自前でやろうとすると3Dプログラムの基礎から勉強する必要があります

とりあえず、こんな感じなります。

最近はどこのライブラリも至れり尽くせりでだいたいこのあたりの変換関数を提供しているんですが、ARCoreはそうではないようですね。
もしかしたらandroid.openglの方に転がっているかもしれません。
よかったらお探しください。

1Like

Comments

  1. @yoshikawa922

    Questioner

    ありがとうございます。いろいろ試してみます。

Your answer might help someone💌