簡體   English   中英

輪換后翻譯

[英]Translation after rotation

我正在使用OpenGL ES 2.0 for Android。 我正在使用觸摸屏翻譯和旋轉模型。 我的翻譯僅在(x,y)平面上,我的旋轉僅在z軸附近。 想象一下,直接向下看桌面上的地圖並移動到地圖上的各種坐標,並能夠圍繞您正在看的點旋轉地圖。

問題是,在旋轉之后,我的后續翻譯將更長時間與屏幕上指針的運動匹配,軸是不同的。

我嘗試的一切都給了我兩種行為中的一種,一種相當於:

Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, Xposition, Yposition, 0.0f);
Matrix.rotateM(mModelMatrix, 0, rotationAngle, 0.0f, 0.0f, 1.0f);

這允許我按預期進行平移(無論旋轉如何,屏幕上/下移動模型上下移動,左/右移動模型左右)。 問題是旋轉是圍繞物體的中心,我需要旋轉大約是我正在看的點,這與物體的中心不同。

我能得到的其他行為相當於:

Matrix.setIdentityM(mModelMatrix, 0);
Matrix.rotateM(mModelMatrix, 0, rotationAngle, 0.0f, 0.0f, 1.0f);
Matrix.translateM(mModelMatrix, 0, Xposition, Yposition, 0.0f);

這給了我想要的旋轉,總是關於我正在看的點。 問題是在輪換后,翻譯是錯誤的。 屏幕上的左/右沿着旋轉的軸以不同的角度平移對象。

我需要一些方法來同時獲得這兩種行為。 它需要圍繞我正在看的點旋轉, 沿着手指在屏幕上移動的方向平移。

這甚至可能嗎? 我是否基本上試圖將量子力學與牛頓物理學相協調,注定要失敗?

我不想列出我嘗試過的所有技巧,因為我想以全新的視角考慮所有可能性。

編輯:我仍然完全堅持這一點。

我有一個從世界坐標中的(0,0,0)開始的對象。 我的視圖是俯視對象的z軸,我想限制平移到x / y平面。 我還想僅圍繞z軸旋轉對象。 旋轉中心必須始終是屏幕的中心。

我正在用觸摸屏控制平移,所以無論旋轉方式如何,我都需要手指以相同的方式移動物體。

旋轉后,我的所有翻譯都會在旋轉的坐標系上開始,這意味着對象不會隨着指針在屏幕上移動。 我試圖按照休費舍推薦的那樣進行第二次翻譯,但我無法弄清楚如何計算第二次翻譯。 還有另外一種方法嗎?

我有同樣的問題。 但是我使用C#和OpenGL(SharpGL)並使用旋轉矩陣。

需要旋轉后的平移以將旋轉點保持在屏幕的中心。 作為CAD類型的應用程序。 問題是旋轉后鼠標翻譯並不總是與屏幕平行。

我在這里找到了解決辦法。

(Xposition, Yposition) = (Xposition, Yposition) + mRotation.transposed() * (XIncr, YIncr)

要么

NewTranslationPosition = oldTranslationPosition + rotationMatrix.Transposed * UserTranslationIncrement.

很多感謝reto.koradi(在OpenGL上)!

所以我大致用3D編碼:

double gXposition = 0;
double gYposition = 0;
double gZposition = 0;

double gXincr = 0;
double gYincr = 0;
double gZincr = 0;

float[] rotMatrix = new float[16]; //Rotational matrix

private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
{

  OpenGL gl = openGLControl.OpenGL;

  gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

  gl.LoadIdentity();
  gl.MultMatrix(rotMatrix); //This is my rotation, using a rotation matrix
  gl.Translate(gXposition, gYposition, gZposition); //translate second to keep rotation at center of screen

  DrawCube(ref  gl);

}

private void buttonTransLeft_Click(object sender, EventArgs e)
{
        double tX = -0.1;
        double tY = 0;
        double tZ = 0;

        TransposeRotMatrixFindPoint(ref tX, ref tY, ref tZ);

        gXposition = gXposition + tX;
        gYposition = gYposition + tY;
        gZposition = gZposition + tZ;

 }

 private void buttonTransRight_Click(object sender, EventArgs e)
 {

        double tX = 0.1;
        double tY = 0;
        double tZ = 0;

        TransposeRotMatrixFindPoint(ref tX, ref tY, ref tZ);


        gXposition = gXposition + tX;
        gYposition = gYposition + tY;
        gZposition = gZposition + tZ;

  }

public void TransposeRotMatrixFindPoint(ref double x, ref double y, ref double z)
    {
        //Multiply [x,y,z] by Transpose Rotation matrix to generate new [x,y,z]
        double Xt = 0; //Tempoary variable
        double Yt = 0; //Tempoary variable
        Xt = (x * rotMatrix[0, 0]) + (y * rotMatrix[0, 1]) + (z * rotMatrix[0, 2]);
        Yt = (x * rotMatrix[1, 0]) + (y * rotMatrix[1, 1]) + (z * rotMatrix[1, 2]);
        z = (x * rotMatrix[2, 0]) + (y * rotMatrix[2, 1]) + (z * rotMatrix[2, 2]);

        //or try this 
        //Xt = (x * rotMatrix[0, 0]) + (y * rotMatrix[1, 0]) + (z * rotMatrix[2, 0]);
        //Yt = (x * rotMatrix[0, 1]) + (y * rotMatrix[1, 1]) + (z * rotMatrix[2, 1]);
        //z = (x * rotMatrix[0, 2]) + (y * rotMatrix[1, 2]) + (z * rotMatrix[2, 2]);


        x = Xt;
        y = Yt;
    }

這是一篇很老的帖子,但我發布的解決方案最適合后人。

解決方案是保留一個單獨的模型矩陣,在發生轉換時累積轉換,並在onDrawFrame()方法中將每個轉換乘以此矩陣。

//Initialize the model matrix for the current transformation
Matrix.setIdentityM(mModelMatrixCurrent, 0);
//Apply the current transformations
Matrix.translateM(mModelMatrixCurrent, 0, cameraX, cameraY, cameraZ);
Matrix.rotateM(mModelMatrixCurrent, 0, mAngle, 0.0f, 0.0f, 1.0f);
//Multiply the accumulated transformations by the current transformations
Matrix.multiplyMM(mTempMatrix, 0, mModelMatrixCurrent, 0, mModelMatrixAccumulated, 0);
System.arraycopy(mTempMatrix, 0, mModelMatrixAccumulated, 0, 16);

然后累積的矩陣用於定位對象。

以下是我對翻譯和旋轉的看法:您沒有移動對象,而是移動坐標系的原點。 以這種方式思考,你需要額外翻譯你的第一個行為。

手指運動是一個應該與屏幕的XY軸對齊的平移,所以你應該在旋轉之前完成。 然后進行旋轉,圍繞該點旋轉對象的坐標系。 如果您希望將對象繪制在相對於該點的其他位置,則需要先進行另一次轉換以將原點移動到那里。

所以我認為你的最終序列應該是這樣的

translate(dx,dy); 旋轉(A); 翻譯(cx,cy); 畫()

其中cx和cy是地圖中心和被觀察點之間的距離。 (可以簡化為-dx,-dy)

希望這可以幫助。

你應該使用你的第一種方法,雖然數學上第二種方法更有意義。 OpenGL和Android存儲矩陣之間存在差異。 畢竟它們是數組,但前4個值是行還是列?

這就是它“倒退”的原因。 請查看信息以獲取更多信息,或閱讀有關行主要與列主要矩陣操作的信息。

我注意到第一種方法“向后”按預期工作。

數學:

假設您想圍繞一個點(x1,y1,z1)旋轉。 你的對象的起源是(Ox,Oy,Oz)。

設定原產地:

Matrix.setIdentityM(mModelMatrix, 0);

然后將要旋轉的點移動到原點:

Matrix.translateM(mModelMatrix, 0, -x1, -y1, -z1);

然后是Matrix.rotateM(mModelMatrix,0,rotationAngle,0.0f,0.0f,1.0f);

然后將其移回:

Matrix.translateM(mModelMatrix, 0, x1, y1, z1);

然后將其移動到您想要的位置:

Matrix.translateM(mModelMatrix, 0, x, y, z);

但是,在反思中,你會以相反的順序進行。

嘗試:設置原點:

Matrix.setIdentityM(mModelMatrix, 0);

然后以相反的順序執行操作:

Matrix.translateM(mModelMatrix, 0, x, y, z);

Matrix.translateM(mModelMatrix, 0, x1, y1, z1);

Matrix.rotateM(mModelMatrix, 0, rotationAngle, 0.0f, 0.0f, 1.0f);

Matrix.translateM(mModelMatrix, 0, -x1, -y1, -z1);

我希望這有幫助。

編輯

我可能錯過了解這個問題:這對我有用的是:

Matrix.setIdentityM(mModelMatrix, 0);

Matrix.translateM(mModelMatrix, 0, x1, y1, z1);

Matrix.rotateM(mModelMatrix, 0, rotationAngle, 0.0f, 0.0f, 1.0f);

Matrix.Multiply(mViewProjection, 0, mProjection, 0, mCameraView, 0);  //something like this, but do you have the right order?

在我的Shader中,我有mViewProjection * mModelMatrix * a_Position;

您是否使用頂點着色器進行最終乘法?

嘗試進行靜態平移/旋轉(使用常量值),而不是使用觸摸屏控制平移。 如果它工作正常,可能你在其他地方有一個bug

暫無
暫無

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

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