Android преобразования OpenGL ES жестами пальцев для 2D - PullRequest
1 голос
/ 02 мая 2020

Существует ли пример кода для применения 2D-преобразования: поверните, масштабируйте, переведите для 2D-сцены OpenGL ES, используя жесты пальцев. Что-то похожее на это , но для Android вместо iPhone? Я искал везде, но не смог найти ни одного полезного исходного кода.

1 Ответ

1 голос
/ 02 мая 2020

Одним из подходов является получение координат 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;
    ...
} 

С вращением и масштабированием по аналогии .

...