如何申请拖放和规模在Android中的OpenGL ES [英] How to apply drag drop and scale in Android OpenGL ES

查看:224
本文介绍了如何申请拖放和规模在Android中的OpenGL ES的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有说不上来一个问题,如何添加触摸或长按操作OpenGL的转换和调整参数?

目前我的编码显示在手机屏幕的中间有质感,我想拖动和缩放用手指的质感,让我怎么操纵OpenGL的转换和调整参数?

这是我的主类:

 进口android.app.Activity;
进口android.os.Bundle;
进口android.view.WindowManager;

公共类MainActivity延伸活动{

私人阶段阶段;

@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);

    //屏幕设置
    。getWindow()addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    。getWindow()addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    。getWindow()clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

    的setContentView(R.layout.main_layout);
    舞台=(第一阶段)findViewById(R.id.my_stage);
}

@覆盖
保护无效的onPause(){
    super.onPause();
    stage.onPause();
}

@覆盖
保护无效onResume(){
    super.onResume();
    stage.onResume();
}
}
 

这是我第二次类:

 进口android.content.Context;
进口android.opengl.GLES10;
进口android.opengl.GLSurfaceView;
进口android.util.AttributeSet;

进口java.nio.ByteBuffer中;
进口java.nio.ByteOrder中;
进口java.nio.FloatBuffer中;

进口javax.microedition.khronos.egl.EGLConfig;
进口javax.microedition.khronos.opengles.GL10;

公共类舞台扩展GLSurfaceView {

/ *舞台宽度和高度* /
私人浮动W,H;

/ *屏幕宽度和高度* /
私人诠释屏幕宽度,screenHeight;

/ *我们的母语顶点缓冲区* /
私人FloatBuffer vertexBuffer;

私人纹理TEX;

公共舞台(上下文的背景下,ATTRS的AttributeSet){
    超(背景下,ATTRS);
    setEGLConfigChooser(8,​​8,8,8,0,0);
    setRenderer(新MyRenderer());
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    浮动顶点[] = {
            -0.5f,-0.5f,0.0,// 0左下方
            0.5F,-0.5f,0.0,// 1右下
            -0.5f,0.5F,0.0,// 2。左顶
            0.5F,0.5F,0.0 // 3。右顶
    };

    ByteBuffer的VBB = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(顶点);
    vertexBuffer.position(0);

    TEX =新的纹理(R.drawable.kdk);

}

私人final类MyRenderer实现GLSurfaceView.Renderer {

    公众最终无效onDrawFrame(GL10 GL){

        gl.glClear(GLES10.GL_COLOR_BUFFER_BIT);
        gl.glVertexPointer(3,GL10.GL_FLOAT,0,vertexBuffer);
        特prepare(GL,GL10.GL_CLAMP_TO_EDGE)。
        tex.draw(GL,(W / 2),(H / 2),tex.getWidth(),tex.getHeight(),0);

    }

    公众最终无效onSurfaceChanged(GL10 GL,诠释的宽度,高度INT){
        gl.glClearColor(0,0,0,1.0F);

        如果(宽>高度){
            H = 600;
            W =宽*高/高度;
        } 其他 {
            W = 600;
            H =高*宽/宽;
        }
        屏幕宽度=宽度;
        screenHeight =高度;

        gl.glViewport(0,0,屏幕宽度,screenHeight);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0,W,H,0,-1,1);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    公众最终无效onSurfaceCreated(GL10 GL,EGLConfig配置){
        //设置alpha混合
        gl.glEnable(GL10.GL_ALPHA_TEST);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE,GL10.GL_ONE_MINUS_SRC_ALPHA);

        //我们在2D。为什么需要深度?
        gl.glDisable(GL10.GL_DEPTH_TEST);

        //启用顶点数组(我们将用它来绘制原语)。
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        //启用纹理协调阵列。
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        tex.load(的getContext());
    }



}

}
 

这是我的第三子类:

 进口android.content.Context;
进口android.content.res.Resources;
进口android.graphics.Bitmap;
进口android.graphics.BitmapFactory;
进口android.opengl.GLES10;
进口android.opengl.GLES20;
进口android.opengl.GLUtils;
进口android.util.Log;
进口java.nio.ByteBuffer中;
进口java.nio.ByteOrder中;
进口java.nio.FloatBuffer中;
进口javax.microedition.khronos.opengles.GL10;

公共类纹理{

/ **
 *与此纹理关联的OpenGL ES的纹理名。
 * /
保护INT textureId;

/ **
 *图像的水平和垂直尺寸。
 * /
保护INT宽度,高度;

/ **
 *因为我们要加载的图像资源标识符。
 * /
INT RESOURCEID;

/ **
 *我们是否应该产生MIP映射。
 * /
布尔贴图;

/ **
 *含纹理映射的缓冲区。
 * /
私人FloatBuffer tempTextureBuffer = NULL;

纹理(INT RESOURCEID,布尔贴图){
    this.resourceId = RESOURCEID;
    this.textureId = -1;
    this.mipmaps =贴图;
}

纹理(INT RESOURCEID){
    这个(RESOURCEID,假);
}

/ **
 *生成一个新的OpenGL ES纹理名称(标识)。
 返回:新生成的纹理名称。
 * /
私有静态最终诠释newTextureID(){
    INT []临时=新的INT [1];
    GLES10.glGenTextures(1,温度,0);
    返回温度[0];
}

公众最终诠释的getWidth(){
    返回宽度;
}

公众最终诠释的getHeight(){
    返回高度;
}

公众最终无效负载(上下文的背景下){
    //将资源位图。
    BitmapFactory.Options选择采用=新BitmapFactory.Options();
    opts.inScaled = FALSE;
    BMP位= BitmapFactory.de codeResource(context.getResources(),RESOURCEID,选择采用);

    //更新这个纹理实例的宽度和高度。
    宽度= bmp.getWidth();
    身高= bmp.getHeight();

    //创建并绑定一个新的纹理名称。
    textureId = newTextureID();
    GLES10.glBindTexture(GL10.GL_TEXTURE_2D,textureId);

    //加载纹理到我们的纹理名。
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D,0,BMP,0);

    //设置放大过滤器,双线性插值。
    GLES10.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MAG_FILTER,GL10.GL_LINEAR);

    如果(贴图){
        //如果贴图请求,生成贴图​​并设置缩小过滤器,三线性过滤。
        GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
        GLES10.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR_MIPMAP_LINEAR);
    }
    其他GLES10.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);

    //回收该位图。
    bmp.recycle();

    //如果纹理映射的缓冲区还没有被初始化,现在就做。
    如果(tempTextureBuffer == NULL)
        buildTextureMapping();
}

/ **
 *构建纹理映射缓冲器。
 * /
私人无效buildTextureMapping(){
    //纹理贴图坐标的数组。
    最终浮动质地[] = {
            0,0,//第一个顶点
            1,0,//第二顶点
            0,1,//第三顶点
            1,1,//第四顶点
    };

    //创建一个本地缓存了上述阵。
    最后的ByteBuffer IBB = ByteBuffer.allocateDirect(texture.length * 4);
    ibb.order(ByteOrder.nativeOrder());
    tempTextureBuffer = ibb.asFloatBuffer();
    tempTextureBuffer.put(纹理);
    tempTextureBuffer.position(0);
}

/ **
 *删除纹理名称和标记这个实例作为卸载。
 * /
公众最终无效的destroy(){
    GLES10.glDeleteTextures(1,新INT [] {textureId},0);

    //将此值设置为-1表示它被卸载。
    textureId = -1;
}

isLoaded公众最终布尔(){
    返回textureId> = 0;
}

公众最终无效prepare(GL10 GL,INT套){
    //启用2D纹理
    gl.glEnable(GL10.GL_TEXTURE_2D);

    //绑定我们的纹理名
    gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId);

    //设置纹理包装方法
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_S,套);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_WRAP_T,套);

    //启用纹理坐标数组和加载(激活)我们
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,tempTextureBuffer);
}

公众最终无效平局(GL10 GL,浮法X,浮动Y,浮动W,浮球小时,浮腐){
    gl.glPushMatrix();
    gl.glTranslatef(X,Y,0);
    gl.glRotatef(腐烂,0,0,1);
    gl.glScalef(W,H,0); //缩放,会首先执行。
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
    gl.glPopMatrix();
}

}
 

解决方案

您GLSurfaceView(Stage类)应该是获取触摸事件的类。所以,你应该将这个方法添加到它:

  @覆盖
公共布尔的onTouchEvent(MotionEvent事件){
    最终诠释行动= event.getAction()及MotionEvent.ACTION_MASK;
    浮动的x,y;
    INT pointerIndex;

    如果(动作== MotionEvent.ACTION_DOWN){
        pointerId = event.getPointerId(0);
        X = event.getX();
        Y = event.getY();
        pointerIndex = 0;
    } 其他 {
        pointerIndex = event.getActionIndex();
        pointerId = event.getPointerId(pointerIndex);
        X = event.getX(pointerIndex);
        Y = event.getY(pointerIndex);
    }

    //现在,你有你的x和y,你的动作(上升,下降等),和指针指数。
}
 

请记住,你已经缩小你的GLSurfaceView的虚拟维度,所以你应该做同样的X和Y(你开始使用X和Y之前添加此):

  X = X * W /屏幕宽度;
Y = Y * H / screenHeight;
 

有关的MotionEvent的更多信息(如何降低处理触摸/达等),请参阅的 Android的该类的文档

更新:

有关翻译,你需要有四个成员变量:

  • 已存x和y的联系。
  • 保存的X和Y的精灵。

最初设定所有的人都为无效值如-1。当你拿到ACTION_DOWN事件,保存事件x和y和精灵的X和Y的变量。

在ACTION_MOVE,检查其中的一个,如果它是-1。如果不是,就意味着你拖动。所以,你得到新的x和y的挽救了一个的差异,并将其添加到保存的X和Y这将是你的精灵的新位置。

在ACTION_UP,只需设置保存的值回-1(或至少把你正在检查在ACTION_MOVE的)。

缩放是一个有点复杂。你需要寻找ACTION_POINTER_DOWN的指针指数> 0。一旦你有,你救了第二个指针的值,也就像翻译。您还需要保存精灵的原始缩放倍率。然后,当你得到ACTION_MOVE或ACTION_POINTER_MOVE,你看看,看看这两个指针是present,如果是这样,得到他们的差(-1的伎俩)。但此时的差将构成的缩放因子,而不是位置。

I have a problem on dunno how to add touch or long click to manipulate the OpenGL translate and scale parameter?

Currently my coding is displaying a texture in the middle of the mobile screen, and I want to drag and scale the texture with finger, So how do I manipulate the OpenGL translate and scale parameter?

This is my main class:

import android.app.Activity;
import android.os.Bundle;
import android.view.WindowManager;

public class MainActivity extends Activity {

private Stage stage;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //screen setting
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);

    setContentView(R.layout.main_layout);
    stage = (Stage)findViewById(R.id.my_stage);
}

@Override
protected void onPause() {
    super.onPause();
    stage.onPause();
}

@Override
protected void onResume() {
    super.onResume();
    stage.onResume();
}
}

this is my 2nd sub class:

import android.content.Context;
import android.opengl.GLES10;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class Stage extends GLSurfaceView{

/* Stage width and height */
private float w, h;

/* Screen width and height */
private int screenWidth, screenHeight;

/* Our native vertex buffer */
private FloatBuffer vertexBuffer;

private Texture tex;

public Stage(Context context, AttributeSet attrs) {
    super(context, attrs);
    setEGLConfigChooser(8, 8, 8, 8, 0, 0);
    setRenderer(new MyRenderer());
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    float vertices[] = {
            -0.5f, -0.5f,  0.0f,  // 0. left-bottom
            0.5f, -0.5f,  0.0f,  // 1. right-bottom
            -0.5f,  0.5f,  0.0f,  // 2. left-top
            0.5f,  0.5f,  0.0f   // 3. right-top
    };

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
    vbb.order(ByteOrder.nativeOrder());
    vertexBuffer = vbb.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    tex = new Texture(R.drawable.kdk);

}

private final class MyRenderer implements GLSurfaceView.Renderer {

    public final void onDrawFrame(GL10 gl) {

        gl.glClear(GLES10.GL_COLOR_BUFFER_BIT);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        tex.prepare(gl, GL10.GL_CLAMP_TO_EDGE);
        tex.draw(gl, (w / 2), (h / 2), tex.getWidth(), tex.getHeight(), 0);

    }

    public final void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glClearColor(0, 0, 0, 1.0f);

        if(width > height) {
            h = 600;
            w = width * h / height;
        } else {
            w = 600;
            h = height * w / width;
        }
        screenWidth = width;
        screenHeight = height;

        gl.glViewport(0, 0, screenWidth, screenHeight);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrthof(0, w, h, 0, -1, 1);
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    public final void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // Set up alpha blending
        gl.glEnable(GL10.GL_ALPHA_TEST);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

        // We are in 2D. Why needs depth?
        gl.glDisable(GL10.GL_DEPTH_TEST);

        // Enable vertex arrays (we'll use them to draw primitives).
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

        // Enable texture coordination arrays.
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        tex.load(getContext());
    }



}

}

this is my third sub class:

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES10;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.util.Log;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;

public class Texture {

/**
 * The OpenGL ES texture name associated with this texture.
 */
protected int textureId;

/**
 * The horizontal and vertical dimensions of the image.
 */
protected int width, height;

/**
 * The resource identifier for the image we want to load.
 */
int resourceId;

/**
 * Whether or not we should generate mip maps.
 */
boolean mipmaps;

/**
 * The buffer containing texture mappings.
 */
private FloatBuffer tempTextureBuffer = null;

Texture(int resourceId, boolean mipmaps) {
    this.resourceId = resourceId;
    this.textureId = -1;
    this.mipmaps = mipmaps;
}

Texture(int resourceId) {
    this(resourceId, false);
}

/**
 * Generates a new OpenGL ES texture name (identifier).
 * @return The newly generated texture name.
 */
private static final int newTextureID() {
    int[] temp = new int[1];
    GLES10.glGenTextures(1, temp, 0);
    return temp[0];
}

public final int getWidth() {
    return width;
}

public final int getHeight() {
    return height;
}

public final void load(Context context) {
    // Load the bitmap from resources.
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inScaled = false;
    Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), resourceId, opts);

    // Update this texture instance's width and height.
    width = bmp.getWidth();
    height = bmp.getHeight();

    // Create and bind a new texture name.
    textureId = newTextureID();
    GLES10.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

    // Load the texture into our texture name.
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

    // Set magnification filter to bilinear interpolation.
    GLES10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    if(mipmaps) {
        // If mipmaps are requested, generate mipmaps and set minification filter to trilinear filtering.
        GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
        GLES10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
    }
    else GLES10.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);

    // Recycle the bitmap.
    bmp.recycle();

    // If texture mapping buffer has not been initialized yet, do it now.
    if(tempTextureBuffer == null)
        buildTextureMapping();
}

/**
 * Builds the texture mapping buffer.
 */
private void buildTextureMapping() {
    // The array of texture mapping coordinates.
    final float texture[] = {
            0, 0, // The first vertex
            1, 0, // The second vertex
            0, 1, // The third vertex
            1, 1, // The fourth vertex
    };

    // Create a native buffer out of the above array.
    final ByteBuffer ibb = ByteBuffer.allocateDirect(texture.length * 4);
    ibb.order(ByteOrder.nativeOrder());
    tempTextureBuffer = ibb.asFloatBuffer();
    tempTextureBuffer.put(texture);
    tempTextureBuffer.position(0);
}

/**
 * Deletes the texture name and marks this instance as unloaded.
 */
public final void destroy() {
    GLES10.glDeleteTextures(1, new int[] {textureId}, 0);

    // Setting this value to -1 indicates that it is unloaded.
    textureId = -1;
}

public final boolean isLoaded() {
    return textureId >= 0;
}

public final void prepare(GL10 gl, int wrap) {
    // Enable 2D texture
    gl.glEnable(GL10.GL_TEXTURE_2D);

    // Bind our texture name
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);

    // Set texture wrap methods
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, wrap);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, wrap);

    // Enable texture coordinate arrays and load (activate) ours
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tempTextureBuffer);
}

public final void draw(GL10 gl, float x, float y, float w, float h, float rot) {
    gl.glPushMatrix();
    gl.glTranslatef(x, y, 0);
    gl.glRotatef(rot, 0, 0, 1);
    gl.glScalef(w, h, 0); // Scaling will be performed first.
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
    gl.glPopMatrix();
}

}

解决方案

Your GLSurfaceView (Stage class) should be the class that gets touch events. So you should add this method to it:

@Override
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction() & MotionEvent.ACTION_MASK;
    float x, y;
    int pointerIndex;

    if (action == MotionEvent.ACTION_DOWN) {
        pointerId = event.getPointerId(0);
        x = event.getX();
        y = event.getY();
        pointerIndex = 0;
    } else {
        pointerIndex = event.getActionIndex();
        pointerId = event.getPointerId(pointerIndex);
        x = event.getX(pointerIndex);
        y = event.getY(pointerIndex);
    }

    // Now you have your x and y, your action (up, down, etc), and pointer index.   
}

And remember that you have scaled the virtual dimensions of your GLSurfaceView, so you should probably do the same with x and y (add this just before you start using x and y):

x = x * w / screenWidth;
y = y * h / screenHeight;

For more information regarding the MotionEvent (how to handle touch down/up etc) please refer to the Android documentation for this class.

Update:

For translation, you need to have four member variables:

  • Saved x and y for the touch.
  • Saved X and Y of the sprite.

Initially set all of them to an invalid value such as -1. When you get the ACTION_DOWN event, save the event x and y and sprite X and Y in the variables.

On ACTION_MOVE, you check one of them if it is -1. If it is not, it means you are dragging. So you get the difference of the new x and y with the saved one, and add it to saved X and Y. This will be the new position of your sprite.

On ACTION_UP, simply set saved values back to -1 (or at least set the one you are checking on ACTION_MOVE).

Scaling is a little bit more complicated. You need to look for ACTION_POINTER_DOWN with a pointer index > 0. Once you have that, you save the values of the second pointer, too, just like the translation. You also need to save the original scaling factor of the sprite. Then whenever you get ACTION_MOVE or ACTION_POINTER_MOVE, you look to see if both pointers are present (the trick with -1), and if so, get their difference. But this time the difference will constitute to your scaling factor, not the position.

这篇关于如何申请拖放和规模在Android中的OpenGL ES的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆