ARCore OpenGL ES Moving Object с использованием onScroll

Я пытаюсь добавить перемещение объектов с помощью прокрутки одним пальцем. (См., Например, стикеры Google AR). Я использую собственный ARCore / OpenGL, изначально основанный на примерах ARCore. Когда вы перемещаете 1 палец, я хочу переместить объект в трехмерном пространстве по осям X и Z.

Я могу легко создать движение с помощью Translation, однако он выполняет движение на основе исходной ориентации камеры. Если вы физически переместите телефон / камеру на несколько шагов в сторону, движения пальцев больше не будут соответствовать тому, что ожидал бы пользователь.

Поэтому я изменил свой код и сопоставил расстояния пальца X и DistanceY, которые перемещаются, чтобы повлиять на координаты X и Z в зависимости от угла изменения от исходной начальной точки камеры до текущей точки камеры.

Проблема, с которой я сталкиваюсь, - это определение угла, на который была перемещена камера. Я смотрел значение из матрицы обзора камеры:

camera.getViewMatrix(viewmtx, 0);

Но координаты X, Y и Z всегда равны нулю. Я предполагаю, что это потому, что камера всегда является исходной точкой? Кто-нибудь знает, как вычислить угол поворота камеры от 3D-объекта с помощью библиотек ARCore / OpenGL ES? Красный угол на иллюстрации ниже (с точки зрения сверху вниз) - это то, что я пытаюсь получить. Извините за грубый рисунок:

введите здесь описание изображения

Вот мой код для справки:

// Handle Gestures - Single touch for Translation and Placement
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener()
{
  @Override
  public boolean onSingleTapUp(MotionEvent e)
  {
    onSingleTap(e);
    return true;
  }

  @Override
  public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
  {
    if (e2.getPointerCount() == 1 && ...)
    {
      double angle = findCameraAngleFromOrigin();
      double speed = 0.005d;

      if (angle / 90d < 1) //Quadrant 1
      {
        double transX = -(distanceY * (angle / 90d)) + (distanceX * ((90d - angle) / 90d));
        double transY = (distanceY * ((90d - angle) / 90d)) + (distanceX * (angle / 90d));
        mTranslationX.set(mTranslationX.size() - 1, (float) (mTranslationX.get(mTranslationX.size() - 1) + (transX * -speed)));
        mTranslationZ.set(mTranslationZ.size() - 1, (float) (mTranslationZ.get(mTranslationZ.size() - 1) + (transY * -speed)));
      }
      else if (angle / 90d < 2) //Quadrant 2
      {
        angle -= 90d;
        double transX = (distanceX * (angle / 90d)) + (distanceY * ((90d - angle) / 90d));
        double transY = (-distanceX * ((90d - angle) / 90d)) + (distanceY * (angle / 90d));
        mTranslationX.set(mTranslationX.size() - 1, (float) (mTranslationX.get(mTranslationX.size() - 1) + (transX * speed)));
        mTranslationZ.set(mTranslationZ.size() - 1, (float) (mTranslationZ.get(mTranslationZ.size() - 1) + (transY * speed)));
      }
      else if (angle / 90d < 3) //Quadrant 3
      {
        angle -= 180d;
        double transX = (distanceY * (angle / 90d)) + (-distanceX * ((90d - angle) / 90d));
        double transY = (-distanceY * ((90d - angle) / 90d)) + (-distanceX * (angle / 90d));
        mTranslationX.set(mTranslationX.size() - 1, (float) (mTranslationX.get(mTranslationX.size() - 1) + (transX * -speed)));
        mTranslationZ.set(mTranslationZ.size() - 1, (float) (mTranslationZ.get(mTranslationZ.size() - 1) + (transY * -speed)));
      }
      else  //Quadrant 4
      {
        angle -= 270d;
        double transX = (-distanceX * (angle / 90d)) + (-distanceY * ((90d - angle) / 90d));
        double transY = (distanceX * ((90d - angle) / 90d)) + (-distanceY * (angle / 90d));
        mTranslationX.set(mTranslationX.size() - 1, (float) (mTranslationX.get(mTranslationX.size() - 1) + (transX * speed)));
        mTranslationZ.set(mTranslationZ.size() - 1, (float) (mTranslationZ.get(mTranslationZ.size() - 1) + (transY * speed)));
      }
      return true;
    }
    return false;
  }
}

РЕДАКТИРОВАТЬ: обновить код


person abeauchamp    schedule 06.03.2018    source источник


Ответы (2)


Мне не удалось выяснить, как определить расстояние от точек камеры, но я смог хотя бы найти разницу в повороте телефона, которая ближе. Я сделал это с помощью кода ниже. Я все еще недоволен результатами, поэтому я опубликую обновления позже, когда найду более эффективное решение.

private double getDegree(double value1, double value2)
{
    double firstAngle = value1 * 90;
    double secondAngle = value2 * 90;
    if (secondAngle >= 0 && firstAngle >= 0)
    {
        Log.d(TAG, "FIRST QUADRANT");
        return firstAngle; // first quadrant
    }
    else if (secondAngle < 0 && firstAngle >= 0)
    {
        Log.d(TAG, "SECOND QUADRANT");
        return 90 + (90 - firstAngle); //second quadrant
    }
    else if (secondAngle < 0 && firstAngle < 0)
    {
        Log.d(TAG, "THIRD QUADRANT");
        return 180 - firstAngle; //third quadrant
    }
    else
    {
        Log.d(TAG, "FOURTH QUADRANT");
        return 270 + (90 + firstAngle); //fourth quadrant
    }
}

private double findCameraAngleFromOrigin()
{
    double angle = getDegree(mCurrentCameraMatrix[2], mCurrentCameraMatrix[0]) - getDegree(mOriginCameraMatrix[2], mOriginCameraMatrix[0]);
    if (angle < 0)
        return angle + 360;
    return angle;
}

@Override
public void onDrawFrame(GL10 gl)
{
    ...
    //When creating a new object
    Anchor anchor = hit.createAnchor();
    mAnchors.add(anchor);
    camera.getDisplayOrientedPose().toMatrix( mOriginCameraMatrix, 0);

    //During each draw frame
    camera.getDisplayOrientedPose().toMatrix( mCurrentCameraMatrix, 0);

    int ac = 0;
    for (Anchor anchor : mAnchors)
    {
      if (anchor.getTrackingState() != TrackingState.TRACKING)
      {
        continue;
      }
      // Get the current pose of an Anchor in world space. The Anchor pose is updated
      // during calls to session.update() as ARCore refines its estimate of the world.
      anchor.getPose().toMatrix(mAnchorMatrix, 0);

      // Update and draw the model
      if (mModelSet)
      {
        if (mScaleFactors.size() <= ac)
        {
          mScaleFactors.add(1.0f);
        }
        if (mRotationThetas.size() <= ac)
        {
          mRotationThetas.add(0.0f);
        }
        if (mTranslationX.size() <= ac)
        {
          mTranslationX.add(viewmtx[3]);
        }
        if (mTranslationZ.size() <= ac)
        {
          mTranslationZ.add(viewmtx[11]);
        }

        translateMatrix(mTranslationX.get(ac), 0, mTranslationZ.get(ac));
        rotateYAxisMatrix(mRotationThetas.get(ac));

        ObjectRenderer virtualObject = mVirtualObjects.get(mAnchorReferences.get(ac));
        virtualObject.updateModelMatrix(mAnchorMatrix, mScaleFactors.get(ac));
        virtualObject.draw(viewmtx, projmtx, lightIntensity);
      }
      ac++;
    }
}

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

person abeauchamp    schedule 13.03.2018

person    schedule
comment
Это просто код, который я ввел, так что это не совсем ответ. Я понимаю, что вам, вероятно, не хватает этого класса, кстати: github.com/nominedisorder / arcore-example / blob / master /. - person abeauchamp; 28.03.2018
comment
на самом деле у меня уже есть класс RotationGestureDetector.java. это не pblm .// ObjectRenderer vitualObject = mVirtualObjects.get (mAnchorReferences.get (ac)); как добавить file.obj в mVirtualObjects (список массивов) .. я добавляю file.obj вот так .// virtualObject.createOnGlThread (/ * context = * / this, andy.obj, andy.png); virtualObject.setMaterialProperties (0.0f, 3.5f, 1.0f, 6.0f); // @Override public void onSurfaceChanged (GL10 gl, int width, int height) {mVirtualObjects.add (virtualObject); } - person Mani Kandan; 28.03.2018
comment
Моя проблема заключалась в том, что файл file.obj не добавлен в список массивов mVirtualObjects. можете ли вы предоставить этот код .. как добавить mVirtualObjects.add (виртуальный объект); - person Mani Kandan; 28.03.2018
comment
Это очень просто: ObjectRenderer virtualObject = new ObjectRenderer (); virtualObject.createOnGlThread (/ * context = * / this, path, model); virtualObject.setMaterialProperties (0.0f, 3.5f, 1.0f, 6.0f); mVirtualObjects.add (виртуальный объект); Но я изменил свой ObjectRenderer, чтобы разрешить правильные файлы .OBJ с изображениями .TGA на основе этого примера: github.com/JohnLXiang/arcore-sandbox/blob/master/app/src/main/ < / а> - person abeauchamp; 29.03.2018
comment
спасибо приведенному выше коду, он работает .. несколько объектов добавляются по нажатой позиции, но мне нужно знать, как загружать разные объекты при щелчке по конкретному элементу из списка. - person Mani Kandan; 29.03.2018