繁体   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