簡體   English   中英

如何在OpenGL ES 2.0(Android)中取消投影屏幕坐標?

[英]How Do I UnProject Screen Coordinates in OpenGL ES 2.0 (Android)?

最近幾天,我一直在努力將應用程序的觸摸事件“取消投影”到渲染器的坐標空間中。 為了實現這一目標,我嘗試了各種自定義的非項目方法和替代技術(包括嘗試使用縮放因子和變換值來轉換坐標)無止境。 我已經得到接近(在我的觸摸稍微偏離),但是用我的努力GLU.gluUnProject已經路要走 ,通常把坐標視圖四周的中心。 “最接近”的結果是通過Xandy的方法得出的,但是即使這些結果通常也不可行 我的主要問題是如何設置視口矩陣,是否要傳遞GLU.gluUnProject正確的參數? 我的數學基於對這個問題的答案。 這是我的代碼的相關摘錄(顯示了如何設置矩陣和當前的嘗試):

    public void onSurfaceChanged(GL10 gl, int width, int height) {
            // Set the OpenGL viewport to fill the entire surface.
            glViewport(0, 0, width, height);
            ...
            float ratio = (float) width / height;
            Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }

    public void onDrawFrame(GL10 gl) {
            glClear(GL_COLOR_BUFFER_BIT);

            Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, -4.5f, 0f, 0f, 0f, 0f, 1f, 0f);
            Matrix.scaleM(mViewMatrix, 0, mScaleFactor, mScaleFactor, 1.0f);
            Matrix.translateM(mViewMatrix, 0, -mOffset.x, mOffset.y, 0.0f);

            Matrix.multiplyMM(mModelMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
            ...
    }

    public PointF convertScreenCoords(float x, float y) {
            int[] viewPortMatrix = new int[]{0, 0, (int)mViewportWidth, (int)mViewportHeight};
            float[] outputNear = new float[4];
            float[] outputFar = new float[4];

            y = mViewportHeight - y;
            int successNear = GLU.gluUnProject(x, y, 0, mModelMatrix, 0, mProjectionMatrix, 0, viewPortMatrix, 0, outputNear, 0);
            int successFar = GLU.gluUnProject(x, y, 1, mModelMatrix, 0, mProjectionMatrix, 0, viewPortMatrix, 0, outputFar, 0);

            if (successNear == GL_FALSE || successFar == GL_FALSE) {
                throw new RuntimeException("Cannot invert matrices!");
            }

            convert4DCoords(outputNear);
            convert4DCoords(outputFar);

            float distance = outputNear[2] / (outputFar[2] - outputNear[2]);
            float normalizedX = (outputNear[0] + (outputFar[0] - outputNear[0]) * distance);
            float normalizedY = (outputNear[1] + (outputFar[1] - outputNear[1]) * distance);

            return new PointF(normalizedX, normalizedY);
    }

convert4DCoords只是一個輔助函數,它將數組的每個坐標(x,y,z)除以w。 mOffsetmScaleFactor是平移和縮放參數(由給定ScaleGestureDetector我們的內GLSurfaceView

根據我已閱讀的所有內容,這應該可以正常工作,但是它始終是錯誤的,並且我不確定還有什么嘗試。 任何幫助/反饋將不勝感激!

我沒有仔細檢查您的所有數學知識,但您的某些矩陣運算和規范對我來說似乎是錯誤的。 這很可能是您問題的至少一部分。

首先看一下您所說的mViewMatrix

Matrix.setLookAtM(mViewMatrix, 0, 0f, 0f, -4.5f, 0f, 0f, 0f, 0f, 1f, 0f);
Matrix.scaleM(mViewMatrix, 0, mScaleFactor, mScaleFactor, 1.0f);
Matrix.translateM(mViewMatrix, 0, -mOffset.x, mOffset.y, 0.0f);

這不一定沒有錯。 但是大多數人可能只會調用第一部分,它是View矩陣setLookAtM()的結果。 其余的看起來更像是模型矩陣。 但是由於渲染通常只使用View和Model矩陣的乘積,因此這只是術語。 可以說,存儲在mViewMatrixmViewMatrix矩陣。

然后命名在這里變得陌生:

Matrix.multiplyMM(mModelMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

這將計算“投影”和“視圖”矩陣的乘積。 因此,這將是一個ViewProjection矩陣。 將其存儲在名為mModelMatrix的變量中會造成混淆,我想您可能已經用這種命名方式設置了陷阱。

這將導致我們調用glUnproject()

GLU.gluUnProject(x, y, 0, mModelMatrix, 0, mProjectionMatrix, 0, viewPortMatrix, 0, outputNear, 0);

基於以上內容,您要傳遞的兩個矩陣參數(視口實際上不是矩陣)是ViewProjection和Projection矩陣。 根據方法定義,您應該傳遞ModelView和Projection矩陣。

由於我們確定了您所謂的mViewMatrix對應於mViewMatrix矩陣,因此,如果僅更改該參數,則應該可以更好地工作:

GLU.gluUnProject(x, y, 0, mViewMatrix, 0, mProjectionMatrix, 0, viewPortMatrix, 0, outputNear, 0);

然后,您可以擺脫根本不是模型矩陣的mModelMatrix

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM