2015-09-28 72 views

回答

3

我来说也是一样的工作,这是我用:

首先,来看看拉贾瓦利的ArcballCamera类。您可以在那里看到如何处理触摸事件以通过触摸事件旋转摄像头。

问题是我不喜欢用户在屏幕上移动时旋转的默认行为,所以我根据前一个做了另一个实现,并直接旋转了我想要的球体摄像头的,所以这里有云(所有这一切都是我的渲染器类中,顺便说一句):

首先,声明:

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? –

相关问题