移动摄像头周围采用纸板触摸事件和VR拉贾瓦利Android版纸板、摄像头、事件、Android

2023-09-07 09:41:04 作者:我只是有点倔强而已。

目前,我正在应用虚拟现实为使用谷歌纸板和拉贾瓦利播放360视频机器人。该传感器的工作很好,但我不能用触摸周围拖动正确的场景或相机。有没有什么办法,使触控模式,在此应用程序?

Currently, I am working on VR application for android that using google CardBoard and Rajawali to play the 360 video. The sensor is working well, but I cannot use touch to drag the scene or camera around correctly. Is there any way to enable touch mode in this app?

任何帮助是极大AP preciated!谢谢你。

Any help is greatly appreciated! Thank you.

推荐答案

我同样的事情的工作,这是我用什么:

I've worked on the same thing, and this is what I used:

首先,来看看拉贾瓦利的 ArcballCamera 类。你可以看到有事件如何处理的触摸与触摸事件旋转相机。

First, take a look at Rajawali's ArcballCamera class. You can see there how touch events are handled to rotate the camera with touch events.

问题是我不喜欢轮换的默认行为,当用户在屏幕上移动,所以我做了另一个实现我自己的基础上,previous之一,直接旋转我一直在寻找球以代替摄像机,所以这里有云(所有这一切都是我的渲染器类中,顺便说一句):

The problem is I didn't liked the default behaviour of the rotation when the user moved across the screen, so I did another implementation on my own, based on the previous one and rotating directly the sphere I was looking to instead of the camera, so here it goes (all of this is inside my Renderer class, btw):

一,声明:

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(定时器及控制被用于视频控制视图,因此不支付atention这些):

In the renderer's constructor I start the inizalizations (timer and control are used for the video control view, so don't pay atention to these):

    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);
        }
    });
}

和最后但并非最不重要的,该事件侦听(无论是缩放和旋转):

And last but not least, the event listening (both for scaling and rotating):

/**
 * 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;
    }
}

有了这一切尘埃落定,你只需要设置方向上的每个渲染,就像这样:

With all of this settled, you only have to set the orientation on each render, like this:

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

我已经说过了,这对我的作品,但我只转动球体。它不应该是很难将它addapt您的需要,除了你有弧形球类是一个摄像头,并可能是你想要的东西更好。无论如何,我希望这是对您有用。

As I've said, this works for me, but I'm only rotating the sphere. It shouldn't be difficult to addapt it to your needs, besides you have the Arcball class that is a camera and might be better for what you want. Anyway, I hope this is useful for you.