Skip to content Skip to sidebar Skip to footer

Translation After Rotation

I'm using OpenGL ES 2.0 for Android. I'm translating and rotating a model using the touch screen. My translations are only in the (x, y) plane, and my rotation is only about the

Solution 1:

I had the same problem. However i was using C# with OpenGL (SharpGL) and using a rotation Matrix.

Translation after rotation was required to keep rotation point at center of screen. As a CAD type application does. Problem was mouse translations are not always parallel to screen after rotations.

I found a fix here.

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

or

NewTranslationPosition = oldTranslationPosition + rotationMatrix.Transposed * UserTranslationIncrement.

Many many thanks to reto.koradi (at OpenGL)!

So I roughly coded in 3D like:

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

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

float[] rotMatrix = newfloat[16]; //Rotational matrixprivatevoidopenGLControl_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);

}

privatevoidbuttonTransLeft_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;

 }

 privatevoidbuttonTransRight_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;

  }

publicvoidTransposeRotMatrixFindPoint(refdouble x, refdouble y, refdouble z)
    {
        //Multiply [x,y,z] by Transpose Rotation matrix to generate new [x,y,z]double Xt = 0; //Tempoary variabledouble 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;
    }

Solution 2:

This is an old post, but I'm posting the solution that worked best for me for posterity.

The solution was to keep a separate model matrix that accumulates transformations as they occur, and multiply each transformation by this matrix in the onDrawFrame() method.

//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);

Then the accumulated matrix is used to position the object.

Solution 3:

Here's how I think about translations and rotations: you are not moving the object, you are moving the origin of the coordinate system. Thinking about it this way, you'll need an extra translation on your first behaviour.

The finger motion is a translation that should be aligned to the XY axes of the screen, so as you've worked out, should be done before rotation. Then your rotation takes place, which rotates the coordinate system of the object around that point. If you want the object to be drawn somewhere else relative to that point, you'll need to do another translation first to move the origin there.

So I think your final sequence should be something like

translate(dx, dy) ; rotate(A) ; translate(cx, cy) ; draw()

where cx and cy are the distance between the centre of the map and the point being looked at. (Might simplify to -dx, -dy)

Hope this helps.

Solution 4:

You should use your first method, although mathematically the second one makes more sense. There is a difference between how OpenGL and Android store matrices. They are arrays after all, but are the first 4 values a row or a column?

That's why it is "backwards". Check this for more info, or read about row major vs column major matrix operations.

I noticed that the first method "backwards" works as intended.

Mathematically:

Suppose you want to rotate around a point (x1, y1, z1). The origin of your object is (Ox, Oy, Oz).

Set Origin:

Matrix.setIdentityM(mModelMatrix, 0);

Then move the point you want to rotate about to the origin:

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

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

Then move it back:

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

Then move it where you want:

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

However, on the backward thinking, you do it in reverse order.

Try: Set Origin:

Matrix.setIdentityM(mModelMatrix, 0);

Then do stuff in reverse order:

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);

I hope this helps.

Edit

I may have miss understood the question: Here is what worked for me is:

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?

In my Shader, i have mViewProjection * mModelMatrix * a_Position;

Are you using the vertex shader to do the final multiplication?

Try to do static translate/ rotate (with constant values) instead of controlling the translation with the touch screen. If it works fine, probably you have a bug somewhere else

Post a Comment for "Translation After Rotation"