3

I'm a 4th year computer engineering student and have some experience with Android dev.

I am working on an application that has a 3D component to it which requires me to be able to rotate it around. I was looking at the example at the android resources site.

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.html

This example does not talk about rotation around the z-axis. I have already tried using Quaternion for the rotations but I don't understand how to get rotations around the z-axis.

Once you rotate something, the axis are no longer the same (x,y) so how can you find out how much to rotate in which axis?

I was wondering if anyone can help me with learning how to just be able to rotate around an object. like the example above but also around the z-axis. I have already spend about 24 hours searching and trying to figure this out.

The bigger issue is that once you rotate 90 degrees around the y-axis how can you detect that the next rotation (going vertically on the touchscreen) should be around the z-axis.

Thank you in advance.

Maqsood
  • 478
  • 6
  • 10
  • Consider just using Unity3D to do the job, in 5 minutes. (once you get familiar with it.) 1, drop in model, 2, drop in "orbit" script. – Fattie May 26 '14 at 13:24

4 Answers4

1

Add xAngle and yAngle to the current matrix.

Matrix.rotateM(matrix, 0, xAngleADD, matrix[1], matrix[5], matrix[9]);
Matrix.rotateM(matrix, 0, yAngleADD, matrix[0], matrix[4], matrix[8]);
gl.glMultMatrixf(matrix, 0);
Kyle
  • 51
  • 1
0

You can also rotate the camera around the center instead of rotating the object.

kaoD
  • 1,534
  • 14
  • 25
0

Your question isn't quite right. Don't ask "Once you rotate something, the axis are no longer the same (x,y) so how can you find out how much to rotate in which axis?", ask "how can I rotate around global axes rather than local axes?". You want a rotation around your global x always to be a rotation around global x, not a rotation around your object's local x axis. You don't rotate differently according to the current state, you just change what you're conceptually rotating around.

First of all, you're probably storing, say rotX, rotY and rotZ and calling glRotatef to apply a rotation? That's not good enough for what you want to do. What you're doing is describing orientation by Euler angles. You'll always encounter gimbal lock, which is where some values for one of the axes turn the other two axes into the same axis. So you lose a degree of freedom. Check out the article for a proper explanation.

Because you'll be very happy with them as an OpenGL coder, suppose you were instead storing object orientation directly as a matrix called M. You store the rotation as the matrix you apply to achieve the rotation. There's no explicit concept of angles or axes.

Suppose you want to rotate around x. You generate a suitable rotation matrix around the x axis, call it R. Such a matrix would be the thing OpenGL would build internally to carry out glRotatef(angle, 1, 0, 0).

Then you actually have two options — replace M with MR or replace M with RM. Matrix multiplication isn't commutative, so those aren't the same. Just like using the OpenGL matrix stack to translate six to the left and then rotate by 40 degrees produces a different result to rotating by 40 degrees and then translating six to the left.

In this case R is the object, so MR is postmultiplication and RM is premultiplication. Multiplication of matrices creates a matrix that, when applied to a vector, has the same effect as applying the second one and then applying the first one. So if you postmultiplied, you'd get the result as though you'd rotated the object by the new rotation and then all the ones that preceded it. That's obviously the wrong way around. You want the new modification to take effect after all other modifications to date. So you premultiply. And then store the result as the new M.

That's all there is to it, actually. You can knock up a quick proof of concept using the GL matrix stack explicitly, like:

// ... I assume the modelview stack is active, M is an array of 16 floats ...

// ensure whatever's on the stack currently is kept safe
glPushMatrix();

    // but we don't actually care what it was, so load the identity
    glLoadIdentity();

    // build our rotation matrix first
    glRotatef(changeAroundX, 1, 0, 0);
    glRotatef(changeAroundY, 0, 1, 0);

    // multiply by M. OpenGL postmultiplies by the newer matrix, so this
    // is premultiplying M by whatever we just loaded
    glMultMatrixf(M);

    // read the new M back
    glGetFloatv(GL_MODELVIEW_MATRIX, M);

// and pretend we never touched the stack
glPopMatrix();

Then use glMultMatrixf(M) in place of glRotatef to apply the current object rotation. This is only a proof of concept because you'll quickly get some nasty numerical errors in M, just resulting from the high amount of manipulation you're doing to it. You can fix M as you go along but if you already have quaternion code and are happy with them, it might be smarter to go down that route. Just replace the logical matrix ops with the quaternion equivalents.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • Android doesn't currently have glGetFloatv -- what would you use in its place? –  Mar 08 '11 at 05:52
  • In that case you'll likely have to write a quick bit of matrix (or quaternion or other) maths for yourself. Luckily it's relatively easy — the man pages for glRotate tell you exactly what to fill into each cell to make the relevant matrix and matrix multiplication is easy to implement. – Tommy Mar 09 '11 at 13:23
  • Thanks. I tried to follow the man pages but I ended up with a situation where I can change my cube's rotation arbitrarily, but *only* along the cube's original axes. So, if I rotate the cube around the up-down axis, 180 degrees, and then try to rotate it up, it rotates down. The key piece I seem to be missing is how to apply a rotation using the current axes against a rotated matrix. It's a fundamental mathematical background failure, unfortunately. –  Mar 09 '11 at 17:59
  • That's the point of the multiplication step. Store orientation directly as a matrix. When you want to add a rotation, create a rotation matrix. Multiply the stored orientation by the rotation matrix and store that back again. The man pages are useful just as a reference to the standard formula for a rotation matrix. – Tommy Mar 09 '11 at 18:53
-1

I recommend you to read this book link

Specifically your question: see part 3.3.1

Max
  • 16,679
  • 4
  • 44
  • 57