android–gluProject函数如何工作?我无法理解

android–gluProject函数如何工作?我无法理解,第1张

概述我需要显示一个方形多边形,其宽度为屏幕宽度的100%,然后,我必须缩放它(使用Z轴),直到多边形边框为屏幕边框设置为止.我正在尝试使用gluProject将3D坐标投影到2D屏幕坐标.如果屏幕坐标为0或与宽度或高度匹配,则它将触摸屏幕边框.问题是出现了问题,使用gluProject返回的outputCoords

我需要显示一个方形多边形,其宽度为屏幕宽度的100%,然后,我必须缩放它(使用Z轴),直到多边形边框为屏幕边框设置为止.

我正在尝试使用gluProject将3D坐标投影到2D屏幕坐标.如果屏幕坐标为0或与宽度或高度匹配,则它将触摸屏幕边框.

问题是出现了问题,使用gluProject返回的outputCoords数组给出了这些值:0,0,0.5,但我的方块以sreen为中心,并且Z = -5.0f !!!!

我不明白这些价值……

这是我用于在屏幕上获取方形poligon的2D投影的代码:

此代码位于GLSurfaceVIEw类的onSurfaceCreated方法上,它必须在另一个方法中使用?哪里?

/////////////// NEW CODE FOR SCAliNG THE AR IMAGE TO THE DESIRED WIDTH /////////////////        mg.getCurrentModelVIEw(gl);          mg.getCurrentProjection(gl);           float [] modelMatrix = new float[16];        float [] projMatrix = new float[16];                modelMatrix=mg.mModelVIEw;        projMatrix=mg.mProjection;        int [] mVIEw = new int[4];        // Fill this with your window wIDth and height        mVIEw[0] = 0;        mVIEw[1] = 0;        mVIEw[2] = 800; //wIDth        mVIEw[3] = 480; //height        // Make sure you have 3 components in this array even if the screen only needs 2        float [] outputCoords = new float[3];        // objX, objY, objZ are the coordinates of one of the borders        glu.gluProject(-1.0f, -1.0f, 0.0f, modelMatrix, 0, projMatrix, 0, mVIEw, 0, outputCoords, 0);

这是我的方形课:

public class Square {//Buffer de verticesprivate floatBuffer vertexBuffer;//Buffer de coordenadas de texturasprivate floatBuffer textureBuffer;//Puntero de texturasprivate int[] textures = new int[3];//El item a representarprivate Bitmap image;//Definición de verticesprivate 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 texture[] ={    //MapPing coordinates for the vertices    0.0f, 1.0f,    1.0f, 1.0f,    0.0f, 0.0f,    1.0f, 0.0f};//Inicializamos los bufferspublic 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 dibujadopublic 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 texturaspublic 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 mipmapprivate 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;    }}}

解决方法:

gluProject确实完成了固定功能转换管道的功能:

>通过附加1作为第四个坐标,将3D顶点扩展为齐次坐标:v [3] = 1.
>然后将该同质顶点乘以模型视图矩阵和投影矩阵:v’= P * M * v.
>然后出现了分裂.通过除以第四个坐标,我们考虑透视失真(如果你有一个正交投影,例如使用glOrtho,那么v'[3] == 1并且没有透视失真):v“= v’/ v'[3] .
>现在,观察体积(场景的可见区域)中的所有内容都已转换为标准化设备坐标,即[-1,1] – 立方体.所以需要做的是将其转换为屏幕坐标[0,w] x [0,h]:x = w *(v“[0] 1)/ 2和y = h *(v”[1] 1 )/ 2.最后,z坐标从[-1,1]变换为[0,1],得到写入深度缓冲区的归一化深度值:z =(v“[2] 1) / 2.

因此理解z值发生的关键是要意识到,相机的距离(视图空间中的z值)首先被投影矩阵转换为[-1,1]范围,具体取决于近-far range(放入glOrtho,glFrustum或gluPerspective的近和远值).然后将该归一化值转换为[0,1]范围,以得到写入深度缓冲区的最终深度值,并且该gluProject计算为窗口坐标的z值.

所以你实际得到的东西(0,0,0.5)是你屏幕的左下角,深度为0.5.使用正交矩阵(没有任何透视失真)和身份模型视图矩阵,这将等于(左,下,(远近)/ 2)的坐标,其中bottom,left,near和far是相应的参数你放入glOrtho函数调用(或具有类似功能的东西).因此,顶点位于观察体积的近远距离和左下角的中间(从相机看).但是这不适用于透视投影,因为在这种情况下,从视图空间z坐标到深度值的变换不是线性的(当然,尽管仍然是单调的).

由于你放入顶点(-1,-1,0),这可能意味着你的模型视图矩阵是标识,你的投影矩阵对应于用glOrtho创建的矩阵(-1,1,-1,1,-1,1 ),它也几乎是单位矩阵(虽然具有镜像z值,但因为输入z为0,你可能不会注意到它).因此,如果这些不是您期待的值(当然,在了解了gluProject的工作原理之后),也可能只是因为您的矩阵未被正确检索而您只是获得了身份矩阵而不是您的实际模型视图和投影矩阵.

所以我认为你的gluProject功能没有任何问题.您还可以查看this question的答案,以便更深入地了解OpenGL的默认转换管道.虽然随着顶点着色器的出现,某些阶段可以以不同的方式计算,但您通常仍然遵循惯用模型 – >查看 – >投影方法.

总结

以上是内存溢出为你收集整理的android – gluProject函数如何工作?我无法理解全部内容,希望文章能够帮你解决android – gluProject函数如何工作?我无法理解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1116322.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-29
下一篇 2022-05-29

发表评论

登录后才能评论

评论列表(0条)

保存