2015-09-28 7 views
2

В настоящее время я работаю над приложением VR для Android, использующим Google CardBoard и Rajawali для воспроизведения видео 360. Датчик работает хорошо, но я не могу использовать прикосновение, чтобы правильно перетащить сцену или камеру. Есть ли способ включить сенсорный режим в этом приложении?Перемещение камеры вокруг с помощью события touch в CardBoard и Rajawali VR Android

Любая помощь очень ценится! Спасибо.

ответ

3

Я работал на одном и том же, и это то, что я использовал:

Во-первых, посмотрите на ArcballCamera класса Rajawali в. Вы можете видеть, как обрабатываются события касания, чтобы повернуть камеру с событиями касания.

Проблема: мне не нравилось поведение по умолчанию вращения, когда пользователь перемещался по экрану, поэтому я сделал другую реализацию самостоятельно, основываясь на предыдущем, и вращал непосредственно сферу, на которую я искал камеры, так что здесь идет (все это в моем классе Renderer, кстати):

Во-первых, заявления:

private GestureDetector detector;   //gesture detector 
private ScaleGestureDetector scaleDetector; //scale detector (for zooming) 
private GestureListener gListener;   //gesture listener 
private ScaleListener sListener;   //scale listener 
private View.OnTouchListener touchListener; //touch events listener 
private boolean isRotating;     //true if the sphere is rotating 
private boolean isScaling;     //true if the sphere is scaling 
private float xInicial,yInicial;   //inicial touch point 
//sphere's yaw and pitch, used for rotation 
private double yaw,pitch, yawAcumulado=0, pitchAcumulado=0, yawAcumuladoR=0, pitchAcumuladoR=0; 
//physical to logical (in 3D world) conversion: screen scroll to sphere rotation 
private final double gradosPorBarridoX=120, gradosPorBarridoY=90; 
private final double gradosPorPixelYaw, gradosPorPixelPitch; 

В конструкторе Отображатель, я начать inizalizations (таймер и контроль используется для просмотра видеоконтроля, поэтому не обращайте на них внимание):

DisplayMetrics outMetrics = new DisplayMetrics(); 
    ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(outMetrics); 
    gradosPorPixelPitch = gradosPorBarridoY/outMetrics.heightPixels; 
    gradosPorPixelYaw = gradosPorBarridoX/outMetrics.widthPixels; 
    addListeners(); 
    ... 
    //from Rajawali ArcballCamera class 
private void addListeners(){ 
    ((Activity)context).runOnUiThread(new Runnable() { 
     @Override 
     public void run() { 
      gListener = new GestureListener(); 
      sListener = new ScaleListener(); 
      detector = new GestureDetector(context, gListener); 
      scaleDetector = new ScaleGestureDetector(context, sListener); 
      touchListener = new View.OnTouchListener() { 
       @Override 
       public boolean onTouch(View v, MotionEvent event) { 
        scaleDetector.onTouchEvent(event); //see if it is a scale event 
        //if not, check whether it is a scroll 
        if (!isScaling) { 
         detector.onTouchEvent(event); 
         //or an up motion 
         if (event.getAction() == MotionEvent.ACTION_UP) { 
          if (!isRotating) { 
           //change video control view's visibility 
           TouchActivity.timer.cancel(); 
           if (TouchActivity.control.getVisibility() == View.INVISIBLE) { 
            TouchActivity.control.setVisibility(View.VISIBLE); 
            TouchActivity.timer.start(); //timer is restarted 
           } else { 
            TouchActivity.control.setVisibility(View.INVISIBLE); 
           } 
          } else { 
           isRotating = false; //cancel rotation 
          } 
         } 
        } 
        return true; 
       } 
      }; 
      TouchActivity.principal.setOnTouchListener(touchListener); 
     } 
    }); 
} 

И последнее, но не менее важное, событие прослушивания (как для масштабирования и вращения):

/** 
* called when the rotation starts 
* @param x 
* @param y 
*/ 
private void startRotation(float x, float y){ 
    xInicial = x; 
    yInicial = y; 
} 

/** 
* called during the consecutive events of a rotation movement 
* @param x 
* @param y 
*/ 
private void updateRotation(float x, float y){ 
    float difX = xInicial - x; 
    float difY = yInicial - y; 
    yaw= difX * gradosPorPixelYaw; 
    pitch = difY * gradosPorPixelPitch; 
    yawAcumulado+=yaw; 
    pitchAcumulado+=pitch; 
} 

/** 
* event listener. if the user scrolls his finger through the screen, it sends the 
* touch event to calculate the sphere's rotation 
*/ 
private class GestureListener extends GestureDetector.SimpleOnGestureListener{ 
    @Override 
    public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) { 
     //starts or updates the rotation with the upcoming event x and y screen values 
     if(!isRotating) { 
      startRotation(event2.getX(), event2.getY()); 
      isRotating=true; 
      return false; 
     }else{ 
      isRotating = true; 
      updateRotation(event2.getX(), event2.getY()); 
      return false; 
     } 
    } 
} 

/** 
* event listener. Zooms in or out depending on the user's action 
*/ 
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener{ 
    //zooms in or out according to the scale detector value 
    @Override 
    public boolean onScale(ScaleGestureDetector detector) { 
     if(detector.getScaleFactor()>1){ 
      if(earthSphere.getScaleX()*1.1<120){ 
       earthSphere.setScaleX(earthSphere.getScaleX()*1.1); 
       earthSphere.setScaleY(earthSphere.getScaleY() * 1.1); 
       earthSphere.setScaleZ(earthSphere.getScaleZ() * 1.1); 
      } 
     }else{ 
      if(earthSphere.getScaleX()*0.9>0.95) { 
       earthSphere.setScaleX(earthSphere.getScaleX() * 0.9); 
       earthSphere.setScaleY(earthSphere.getScaleY() * 0.9); 
       earthSphere.setScaleZ(earthSphere.getScaleZ() * 0.9); 
      } 
     } 
     return true; 
    } 

    //the zoom begins 
    @Override 
    public boolean onScaleBegin (ScaleGestureDetector detector) { 
     isScaling = true; 
     isRotating = false; 
     return super.onScaleBegin(detector); 
    } 

    //the zoom ends 
    @Override 
    public void onScaleEnd (ScaleGestureDetector detector) { 
     isRotating = false; 
     isScaling = false; 
    } 
} 

При всем этом решен, осталось только установить ориентацию на каждом рендер, как это:

yawAcumuladoR = (yawAcumulado) * 0.04; 
    pitchAcumuladoR = (pitchAcumulado) * 0.04; 
    Quaternion q = new Quaternion(); 
    q.fromEuler(yawAcumuladoR, pitchAcumuladoR, 0); 
    earthSphere.setOrientation(q); 

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

+0

Спасибо, позвольте мне попробовать это первым. :) –

+0

Np, надеюсь, что он работает =) – SMalpica

+0

Что такое TouchActivity? –