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