Одним из подходов является получение координат OpenGL из координат пикселей пальцев. В классе SurfaceView определяются методы обработки событий:
public class SurfaceView extends GLSurfaceView implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {
private GestureDetectorCompat detector;
private CoordinatesOpenGL coordinatesOpenGL;
private volatile float xPress;
private volatile float yPress;
public SurfaceView() {
...
detector = new GestureDetectorCompat(context, this);
detector.setOnDoubleTapListener(this);
coordinatesOpenGL = new CoordinatesOpenGL();
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent e) {
return mDetector.onTouchEvent(e) || super.onTouchEvent(e);
}
// event handling methods
@Override public boolean onDown(MotionEvent event) { ... return true; }
@Override public boolean onSingleTapConfirmed(MotionEvent event) { return true; }
@Override public boolean onDoubleTap(MotionEvent event) { ... return true; }
@Override public boolean onDoubleTapEvent(MotionEvent event) { ... return true; }
@Override public void onShowPress(MotionEvent event) { ... return true; }
@Override public boolean onSingleTapUp(MotionEvent event) { ... return true; }
@Override public boolean onScroll(MotionEvent event1, MotionEvent event2,
float distanceX, float distanceY) { ... return true; }
@Override public void onLongPress(MotionEvent event) {}
@Override public boolean onFling(MotionEvent event1, MotionEvent event2,
float v1, float v2) { ... return true; }
Затем в одном из этих методов вычисляются координаты OpenGL:
@Override
public boolean onDown(MotionEvent event) {
coordinatesOpenGL.fromDisplay(renderer.getWidthDisplay(),
renderer.getHeightDisplay(),
event.getX(), event.getY());
xPress = coordinatesOpenGL.getXGL(); // get OpenGL coordinates x[-1; 1], y[-1; 1]
yPress = coordinatesOpenGL.getYGL();
renderer.setPassXY(xPress, yPress); // pass x, y to render
return true;
}
Чтобы вычислить координаты OpenGL, я написал метод (на Kotlin), но, возможно, есть и другие стандартные функции:
fun fromDisplay(displayWidth: Int, displayHeight: Int,
displayX: Float, displayY: Float) {
val offsetX: Float // offset X-axis (pixels)
val offsetY: Float // offset Y-axis (pixels)
val centerX = displayWidth / 2 // x of screen center (pixels)
val centerY = displayHeight / 2 // y of screen center (pixels)
if (displayX <= centerX && displayY >= centerY) { // left-down quarter
offsetX = (centerX - displayX)
offsetY = (displayY - centerY)
xGL = -(offsetX / centerX)
yGL = -(offsetY / centerY)
} else if (displayX <= centerX && displayY <= centerY) { // left-up quarter
offsetX = (centerX - displayX)
offsetY = (centerY - displayY)
xGL = -(offsetX / centerX)
yGL = offsetY / centerY
} else if (displayX >= centerX && displayY <= centerY) { // rigth-up quarter
offsetX = (displayX - centerX)
offsetY = (centerY - displayY)
xGL = offsetX / centerX
yGL = offsetY / centerY
} else if (displayX > centerX && displayY > centerY) { // rigth-down quarter
offsetX = (displayX - centerX)
offsetY = (displayY - centerY)
xGL = offsetX / centerX
yGL = -(offsetY / centerY)
}
}
В классе Render используйте координаты OpenGL для перемещения объектов:
...
Matrix.translateM(modelMatrix, 0, x, y, z)
...
public void setPassXY(Float passX, Float passY) {
...
x = xPass * aspect; // or yPass * aspect - depending on orientation
y = yPass;
...
}
С вращением и масштабированием по аналогии .