如何用手指移动 OpenGL 方块?

2023-11-29

其实我有一个申请安卓1.5使用 GLSurfaceView 类在屏幕上显示一个简单的正方形。

我想学习如何添加新功能,即移动用手指触摸的方块的功能。我的意思是,当用户触摸方块并移动手指时,方块应该粘在手指上,直到手指释放屏幕。

任何教程/代码示例/帮助将不胜感激。

My code:

public class MySurfaceView extends GLSurfaceView implements Renderer {  
private Context context;
private Square square;
private float xrot;                 //X Rotation
private float yrot;                 //Y Rotation
private float zrot;                 //Z Rotation
private float xspeed;               //X Rotation Speed
private float yspeed;               //Y Rotation Speed
private float z = -1.15f;           //Profundidad en el eje Z
private float oldX; //valor anterior de X, para rotación
private float oldY; //valor anterior de Y, para rotación
private final float TOUCH_SCALE = 0.2f;     //necesario para la rotación

//create the matrix grabber object in your initialization code  
private MatrixGrabber mg = new MatrixGrabber();           

private boolean firstTimeDone=false; //true si la aplicación ya ha sido inicializada.

public MySurfaceView(Context context, Bitmap image) {
    super(context);
    this.context = context;
    setEGLConfigChooser(8, 8, 8, 8, 16, 0); //fondo transparente
    getHolder().setFormat(PixelFormat.TRANSLUCENT); //fondo transparente
    //Transformamos esta clase en renderizadora
    this.setRenderer(this);
    //Request focus, para que los botones reaccionen
    this.requestFocus();
    this.setFocusableInTouchMode(true);
    square = new Square(image);                                 
}

public void onSurfaceCreated(GL10 gl, EGLConfig config) {       
    gl.glDisable(GL10.GL_DITHER);               //dithering OFF
    gl.glEnable(GL10.GL_TEXTURE_2D);            //Texture Mapping ON
    gl.glShadeModel(GL10.GL_SMOOTH);            //Smooth Shading 
    gl.glClearDepthf(1.0f);                     //Depth Buffer Setup
    gl.glEnable(GL10.GL_DEPTH_TEST);            //Depth Testing ON
    gl.glDepthFunc(GL10.GL_LEQUAL);
    gl.glClearColor(0,0,0,0); //fondo transparente
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);         
    //Cargamos la textura del cubo.
    square.loadGLTexture(gl, this.context);
}

public void onDrawFrame(GL10 gl) {
    //Limpiamos pantalla y Depth Buffer
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glLoadIdentity();
    //Dibujado
    gl.glTranslatef(0.0f, 0.0f, z);         //Move z units into the screen
    gl.glScalef(0.8f, 0.8f, 0.8f);          //Escalamos para que quepa en la pantalla
    //Rotamos sobre los ejes.
    gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);   //X
    gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);   //Y
    gl.glRotatef(zrot, 0.0f, 0.0f, 1.0f);   //Z
    //Dibujamos el cuadrado
    square.draw(gl);    
    //Factores de rotación.
    xrot += xspeed;
    yrot += yspeed;         


    if (!firstTimeDone)
    {       
        /////////////// NEW CODE FOR SCALING THE AR IMAGE TO THE DESIRED WIDTH /////////////////            
        mg.getCurrentProjection(gl); 
        mg.getCurrentModelView(gl);                     
        float [] modelMatrix = new float[16];
        float [] projMatrix = new float[16];
        modelMatrix=mg.mModelView;
        projMatrix=mg.mProjection;          
        int [] mView = new int[4];
        mView[0] = 0;
        mView[1] = 0;
        mView[2] = 800; //width
        mView[3] = 480; //height
        float [] outputCoords = new float[3];
        GLU.gluProject(-1.0f, -1.0f, z, modelMatrix, 0, projMatrix, 0, mView, 0, outputCoords, 0);

        int i=0;
        System.out.print(i);
       // firstTimeDone=true;
    }
}

//si el surface cambia, resetea la vista, imagino que esto pasa cuando cambias de modo portrait/landscape o sacas el teclado físico en móviles tipo Droid.
public void onSurfaceChanged(GL10 gl, int width, int height) {
    if(height == 0) {                       
        height = 1;                         
    }
    gl.glViewport(0, 0, width, height);     //Reset Viewport
    gl.glMatrixMode(GL10.GL_PROJECTION);    //Select Projection Matrix
    gl.glLoadIdentity();                    //Reset Projection Matrix
    //Aspect Ratio de la ventana
    GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
    gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select Modelview Matrix
    gl.glLoadIdentity();                    //Reset Modelview Matrix        

}

public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    switch (event.getAction()) 
    {
        case MotionEvent.ACTION_MOVE:
            //Calculamos el cambio
            float dx = x - oldX;
            float dy = y - oldY;
            xrot += dy * TOUCH_SCALE;
            yrot += dx * TOUCH_SCALE;
            //Log.w("XXXXXX", "ACTION_MOVE_NO_ZOOM");
            break;
    }
    oldX = x;
    oldY = y;
    return true; //El evento ha sido manejado
}

public void zoomIn(){ 
    z=z+0.2f;   
    if (z>-1.0f)
        z=-1.0f;
}
public void zoomOut(){ 
    z=z-0.2f; 
    if (z<-20.0f)
       z=-20.0f;
}
public void rotateL(){ 
    zrot=zrot+3.0f; 
}
public void rotateR(){ 
    zrot=zrot-3.0f; 
}   
public void reset()
{
    xrot=0;
    yrot=0;
    zrot=0;
    xspeed=0;
    yspeed=0;
    z = -5.0f;
}
}

这是我的方形课程:

public class Square {
//Buffer de vertices
private FloatBuffer vertexBuffer;
//Buffer de coordenadas de texturas
private FloatBuffer textureBuffer;
//Puntero de texturas
private int[] textures = new int[3];
//El item a representar
private Bitmap image;
//Definición de vertices

private float vertices[] = 
{ 
    -1.0f, -1.0f, 0.0f,     //Bottom Left
    1.0f, -1.0f, 0.0f,      //Bottom Right
    -1.0f, 1.0f, 0.0f,      //Top Left
    1.0f, 1.0f, 0.0f        //Top Right
};
/*  
private float vertices[] = 
{ 
-0.8f, -0.8f, 0.0f,     //Bottom Left
0.8f, -0.8f, 0.0f,      //Bottom Right
-0.8f, 0.8f, 0.0f,      //Top Left
0.8f, 0.8f, 0.0f 
};
*/
//Coordenadas (u, v) de las texturas    
/*
private float texture[] = 
{           
    //Mapping coordinates for the vertices
    0.0f, 0.0f,
    0.0f, 1.0f,
    1.0f, 0.0f,
    1.0f, 1.0f
};
*/
private float texture[] =
{
    //Mapping coordinates for the vertices
    0.0f, 1.0f,
    1.0f, 1.0f,
    0.0f, 0.0f,
    1.0f, 0.0f
};
//Inicializamos los buffers
public Square(Bitmap image) {
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuf.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);

    this.image=image;
} 
//Funcion de dibujado
public void draw(GL10 gl) {
    gl.glFrontFace(GL10.GL_CCW);
    //gl.glEnable(GL10.GL_BLEND);
    //Bind our only previously generated texture in this case
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    //Point to our vertex buffer
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    //Enable vertex buffer
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    //Draw the vertices as triangle strip
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    //gl.glDisable(GL10.GL_BLEND);      
}
//Carga de texturas
public void loadGLTexture(GL10 gl, Context context) {
    //Generamos un puntero de texturas
    gl.glGenTextures(1, textures, 0);       
    //y se lo asignamos a nuestro array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
    //Creamos filtros de texturas
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
    //Diferentes parametros de textura posibles GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);     
    /*
    String imagePath = "radiocd5.png";
    AssetManager mngr = context.getAssets();
    InputStream is=null;
    try {
        is = mngr.open(imagePath);
    } catch (IOException e1) {  e1.printStackTrace();   }
    */
    //Get the texture from the Android resource directory
    InputStream is=null;
    /*
    if (item.equals("rim"))
        is = context.getResources().openRawResource(R.drawable.rueda);
    else if (item.equals("selector"))
        is = context.getResources().openRawResource(R.drawable.selector);
    */      
    /*
    is = context.getResources().openRawResource(resourceId);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);
    } finally {
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }
    */
    Bitmap bitmap =image;       
    //con el siguiente código redimensionamos las imágenes que sean mas grandes de 256x256.
    int newW=bitmap.getWidth();
    int newH=bitmap.getHeight();
    float fact;
    if (newH>256 || newW>256)
    {
        if (newH>256)
        {
            fact=(float)255/(float)newH; //porcentaje por el que multiplicar para ser tamaño 256
            newH=(int)(newH*fact); //altura reducida al porcentaje necesario
            newW=(int)(newW*fact); //anchura reducida al porcentaje necesario   
        }
        if (newW>256)
        {
            fact=(float)255/(float)newW; //porcentaje por el que multiplicar para ser tamaño 256
            newH=(int)(newH*fact); //altura reducida al porcentaje necesario
            newW=(int)(newW*fact); //anchura reducida al porcentaje necesario
        }
        bitmap=Bitmap.createScaledBitmap(bitmap, newW, newH, true);
    }       
    //con el siguiente código transformamos imágenes no potencia de 2 en imágenes potencia de 2 (pot)
    //meto el bitmap NOPOT en un bitmap POT para que no aparezcan texturas blancas.
    int nextPot=256;
    int h = bitmap.getHeight();
    int w = bitmap.getWidth();
    int offx=(nextPot-w)/2; //distancia respecto a la izquierda, para que la imagen quede centrada en la nueva imagen POT
    int offy=(nextPot-h)/2; //distancia respecto a arriba, para que la imagen quede centrada en la nueva imagen POT
    Bitmap bitmap2 = Bitmap.createBitmap(nextPot, nextPot, Bitmap.Config.ARGB_8888); //crea un bitmap transparente gracias al ARGB_8888
    Canvas comboImage = new Canvas(bitmap2);
    comboImage.drawBitmap(bitmap, offx, offy, null);
    comboImage.save();

    //Usamos Android GLUtils para espcificar una textura de 2 dimensiones para nuestro bitmap
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);

    //Checkeamos si el GL context es versión 1.1 y generamos los Mipmaps por Flag. Si no, llamamos a nuestra propia implementación
    if(gl instanceof GL11) {
        gl.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap2, 0);
    } else {
        buildMipmap(gl, bitmap2);
    }   
    //Limpiamos los bitmaps
    bitmap.recycle();
    bitmap2.recycle();
}
//Nuestra implementación de MipMap. Escalamos el bitmap original hacia abajo por factor de 2 y lo asignamos como nuevo nivel de mipmap
private void buildMipmap(GL10 gl, Bitmap bitmap) {
    int level = 0;
    int height = bitmap.getHeight();
    int width = bitmap.getWidth();
    while(height >= 1 || width >= 1) {
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
        if(height == 1 || width == 1) {
            break;
        }
        level++;
        height /= 2;
        width /= 2;
        Bitmap bitmap2 = Bitmap.createScaledBitmap(bitmap, width, height, true);
        bitmap.recycle();
        bitmap = bitmap2;
    }
}
}

你看过Android教程代码吗?他们在 OpenGL ES 1 和 2 中提供了与此非常相似的示例。

在 OpenGL ES 1 教程中,有一个部分专门用于处理触摸事件。http://developer.android.com/resources/tutorials/opengl/opengl-es10.html#touch

因此,您需要将 glrotatef 命令中的 AddMotion 部分修改为 gltranslatef;

edit

看起来您对坐标转换比对象选择更感兴趣。因此,无论您触摸屏幕上的任何位置,图像都会移动到该位置(而不是触摸并拖动图像,这意味着选择)。 你关于 winZ 的问题让我觉得你正在尝试 gluunproject 。 如果是这种情况,您已经知道了 winZ,因为您通过“z”变量将相机从对象平移回来。既然你的 z 是负数,为什么不试试这个呢?

假设您已在活动中为 GLSurfaceView 设置 GLWrapper:

    mGLView.setGLWrapper(new GLWrapper() {
        public GL wrap(GL gl) {
            return new MatrixTrackingGL(gl);
        }

    });

然后,在你的 GLSurfaceView/Renderer 子类中......

public float[] unproject(GL10 gl, float x, float y) {
    mMatrixGrabber.getCurrentState(gl);
    int[] view = {0,0,this.getWidth(), this.getHeight()};
    float[] pos = new float[4];
    float[] result = null;
    int retval = GLU.gluUnProject(x, y, -z, 
            mMatrixGrabber.mModelView, 0,
            mMatrixGrabber.mProjection, 0,
            view, 0, 
            pos, 0);
    if (retval != GL10.GL_TRUE) {
        Log.e("unproject", GLU.gluErrorString(retval));
    } else {
        result = new float[3];
        result[0] = pos[0] / pos[3];
        result[1] = pos[1] / pos[3];
        result[2] = pos[2] / pos[3];
        result = pos;
    }
    return result;
}

然后你可以修改你的 TouchEvent 处理程序以包含

    switch (event.getAction()) 
    {
        case MotionEvent.ACTION_MOVE:
            //Calculamos el cambio
            float dx = x - oldX;
            float dy = y - oldY;
            xrot += dy * TOUCH_SCALE;
            yrot += dx * TOUCH_SCALE;
            //Log.w("XXXXXX", "ACTION_MOVE_NO_ZOOM");
            touching = true;
            break;
        case MotionEvent.ACTION_UP:
            xrot = 0;
            yrot = 0;
            zrot = 0;
            touching = false;
            break;
    }

并将下一部分放在其他平移/缩放/旋转调用之前的绘制方法中:

    if (touching) {
        float[] point = unproject(gl, oldX, (this.getHeight() - oldY));
        if (point == null) {
            Log.e("Draw", "No Point");
        } else {
            gl.glTranslatef(point[0], point[1], 0);
        }
    }

希望这能给您带来您想要的结果。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用手指移动 OpenGL 方块? 的相关文章

随机推荐

  • xampp 上的 LDAP 配置

    我一直在尝试在 xampp localhost 上配置 ldap 我在 php ini 文件中启用了 ldap 扩展 我也尝试过更改系统变量 我不断收到此错误 LDAP 功能不存在 加载模块 ldap php 模块或使用编译有 ldap 支
  • UITabBarController 仅显示其 UITabBar 的一半(屏幕外)

    当我从 UIViewController 呈现 UITabBarController 后 我的 UITabBar 没有完全显示 请你告诉我我做错了什么吗 我的代码是 some method LoggedInViewController lv
  • R:熔化和铸造

    我有一个这样的数据集 CASE ID c C1 C1 C2 C2 C2 C3 C4 PERSON ID c 1 0 7 8 1 20 7 PERSON DIVISION c Zone 1 NA Zone 1 Zone 3 Zone 1 Zo
  • if($variable) 究竟是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 关于PHP中的if语句 在 PHP 脚本中 像这样的 if 语句检查什么 我已经多次看到它在脚本中使用 现在我真的很想知道它 寻找 什么 它没有缺少任何东西 它只是 if 语句中的一个普通变量 我在任
  • 在asp.net中显示按月和年分组的记录

    我需要按我的 asp net 页面上显示的日期 月和年 对记录进行排序 任何想法 建议都会有帮助 这是我目前拥有的代码 table width 40 border 0 style margin left auto margin right
  • 使用 pandas 转换 Excel 样式日期

    我必须解析一个 xml 文件 该文件为我提供 Excel 样式的日期时间 例如 42580 3333333333 Pandas 是否提供了一种将该数字转换为常规数字的方法datetime object 好吧 我认为最简单的事情就是构建一个T
  • 如何修复空指针异常

    我一直在尝试修复这个空指针异常 但我不能 我知道它指向一个空对象 但我不知道如何修复它 我是 Java 编程的初学者 所以如果这是一个愚蠢的问题 请不要生气 这是我的代码 import android app Activity import
  • 是漂亮计数器惯用语的错误还是格式不正确的静态订单惨败?

    以下代码在 clang 中崩溃 x86 64 pc linux gnu 上的版本 5 0 0 3 16 04 1 但在 gcc 9 2 0 中运行良好 struct Registry static int registerType int
  • 文件发布到文件系统后运行 Target

    我正在尝试创建发布配置文件 它将所有已发布的文件复制到各个文件夹 不幸的是我读到不可能直接通过publishUrl建议发布到一个文件夹并从中复制所有文件 我设法编写了复制目标功能 但目标运行的顺序是错误的 我尝试通过 构建 gt 发布 We
  • 从 ASP.NET MVC 3 开始,MicrosoftAjax.js、MicrosoftMvcAjax.js 和 MicrosoftMvcValidation.js 是否已过时?

    Are MicrosoftAjax js MicrosoftMvcAjax js and MicrosoftMvcValidation js从 ASP NET MVC 3 开始已过时 我在网上找不到太多关于此的信息 但从我读到的内容来看 这
  • 来自 bash shell 的 XMLA/SOAP 命令

    我需要从 bash shell 中调用 icCube 的管理 API 发送 SOAP 命令的最简单方法是什么
  • url 检查器 VBA,重定向时显示重定向的 url

    我对 EXCEL VBA 很陌生 我有点困于寻找一种方法来创建一个宏来显示 url 是否仍然处于活动状态 200 ok 或者可能会被重定向 如果是这样 我想知道到什么 URL 当它根本不起作用时 则返回正确的代码以及 URL 不起作用的原因
  • 使用 VBA 删除数字周围的文本

    我需要从单元格内的数字中删除所有文本 然后将两个数字拆分到两个单元格中 并将格式设置为数字 而不是文本 该单元格包含以下格式的文本 数字 between 150 000 and 159 999 per annum between 60 an
  • 如何在SQL Server中将XML数据转换为行列数据

    我有一个要求 数据库中有 XML 数据 我需要从数据库中以行和列的形式提取这些数据 我的 XML 就像
  • Hibernate Native SQL 映射到带有选择示例的实体

    我尝试创建本机 SQL 查询并使用参数映射到实体类 但失败了 return public List
  • iPhone 中的 HttpBasicAuthentication

    在我的 iPhone 应用程序中 我试图在 iPhone 上显示来自我的服务器的图像 这需要授权 我正在尝试使用 NSURLConnection 来获取图像 但它并没有要求我提供用户凭据 即它根本不会使用 didReceiveAuthent
  • 用于在 R 中访问 Cassandra 数据库的包

    我努力了R卡桑德拉 and RJDBC但不幸的是 这些绑定似乎仅适用于旧的 Cassandra 1 x Cassandra 2 x 中是否有任何绑定R语言 这不是真的 当前版本RJDBC与 Cassandra 2 X 配合使用 下载具有 C
  • 如何将用户输入限制为 DataGridView 中的几个值

    我需要想出一种方法来限制用户输入除1 or 2在我的 dgv 的专栏中 我有它 因此用户只能输入数字 但我需要进一步的限制来满足FOREIGN KEY限制 有任何想法吗 当前验证到位 Private Sub dgvCategories Ed
  • 在 R Shiny 的数据表中添加工具提示

    我正在尝试使用 JS 脚本添加工具提示attr函数 一些编写的脚本没有给出所需的结果 为数据表的第一列添加工具提示 由于我是新的 JS 脚本 因此无法调试错误 任何人都可以建议我为什么下面的代码没有给出我正确的结果 这是一段代码 libra
  • 如何用手指移动 OpenGL 方块?

    其实我有一个申请安卓1 5使用 GLSurfaceView 类在屏幕上显示一个简单的正方形 我想学习如何添加新功能 即移动用手指触摸的方块的功能 我的意思是 当用户触摸方块并移动手指时 方块应该粘在手指上 直到手指释放屏幕 任何教程 代码示