OpenGL添加触控

来源:互联网 发布:网络作答系统网站 编辑:程序博客网 时间:2024/05/17 05:13

1.glSurfaceView添加监听触控事件

//4.glSurfaceView添加监听触控事件        glSurfaceView.setOnTouchListener(new OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                // TODO Auto-generated method stub                if(event!=null){                    //触屏坐标转化成归一化坐标,即[-1,1]                    final float normalizedX = (event.getX()/(float)v.getWidth())*2-1;                    final float normalizedY = -((event.getY()/(float)v.getHeight())*2-1);                    //转发触控事件给渲染器                    if(event.getAction() == MotionEvent.ACTION_DOWN){                        glSurfaceView.queueEvent(new Runnable() {                            @Override                            public void run() {                                //调用渲染器按压事件                                renderer.handleTouchPress(normalizedX,normalizedY);                            }                        });                    } else if(event.getAction() == MotionEvent.ACTION_MOVE){                        glSurfaceView.queueEvent(new Runnable() {                            @Override                            public void run() {                                //调用渲染器拖拽事件                                renderer.handleTouchDrag(normalizedX,normalizedY);                            }                        });                    }                    return true;                } else {                    return false;                }            }        });

2.屏幕坐标归一化坐标转化成三维射线
2.1采用反转视图投影矩阵
2.2定义归一化坐标为其次在投影近远平面上
2.3撤销透视除法
2.4得到射线在投影近远平面上的交点
2.5得到射线

private Ray convertNormalized2DPointToRay(float normalizedX, float normalizedY){        //定义归一化坐标为其次在投影近远平面上        final float[] nearPointNdc = {normalizedX, normalizedY, -1, 1};         final float[] farPointNdc = {normalizedX, normalizedY, 1, 1};         final float[] nearPointWorld = new float[4];        final float[] farPointWorld = new float[4];        //撤销透视除法        multiplyMV(nearPointWorld, 0, invertedViewProjectionMatrix, 0, nearPointNdc, 0);        multiplyMV(farPointWorld, 0, invertedViewProjectionMatrix, 0, farPointNdc, 0);        divideByW(nearPointWorld);        divideByW(farPointWorld);        //得到射线在投影近远平面上的交点        Point nearPointRay = new Point(nearPointWorld[0], nearPointWorld[1], nearPointWorld[2]);        Point farPointRay = new Point(farPointWorld[0], farPointWorld[1], farPointWorld[2]);        //得到射线        return new Ray(nearPointRay, Geometry.vectorBetween(nearPointRay, farPointRay));    }

3.射线与球距离计算
3.1射线起点和终点到球心的向量
3.2以上三点构成三角形,两向量的交叉乘积向量长度为三角形面积的两倍
3.3射线与球距离 = 两向量的交叉乘积向量长度/射线长度

    private static float distanceBetween(Point point, Ray ray) {        //射线起点和终点到球心的向量        Vector p1ToPoint = vectorBetween(ray.point, point);        Vector p2ToPoint = vectorBetween(ray.point.translate(ray.vector), point);        //以上三点构成三角形,两向量的交叉乘积向量长度为三角形面积的两倍        float areaOfTriangleTimesTwo = p1ToPoint.crossProduce(p2ToPoint).length();        float lengthOfBase = ray.vector.length();        //射线与球距离 = 两向量的交叉乘积向量长度/射线长度        return areaOfTriangleTimesTwo/lengthOfBase;    }

4.通过拖动移动物体
4.1实际是射线与一平面的相交点来替代物体坐标
4.2计算射线到平面的向量
4.3缩放因子 = 射线到平面的向量与平面法向量向量之间的点积 / 射线向量与平面法向量向量的点积
4.4使用缩放因子平移射线点找出相交点

public static Point intersectionPoint(Ray ray, Plane plane){        //计算射线到平面的向量        Vector rayToPlaneVector = vectorBetween(ray.point, plane.point);        //缩放因子 = 射线到平面的向量与平面法向量向量之间的点积 / 射线向量与平面法向量向量的点积        float scaleFactor = rayToPlaneVector.dotProduct(plane.normal)                / ray.vector.dotProduct(plane.normal);        //使用缩放因子平移射线点找出相交点        Point intersectionPoint = ray.point.translate(ray.vector.scale(scaleFactor));        return intersectionPoint;    }

5.碰撞后的速度与方向
5.1速度:向量长度大小(摩擦与加速度)
5.2方向:向量的方向(反弹)
5.3实现:当前点+向量
5.4向量由主动碰撞物上帧位置到当前位置向量决定
6.源码:https://github.com/HQlin/ShaderOpenGL/commits/master

0 0