trouble with arcball rotation and translation

Hi everybody. I’m struggling pretty hard with this, and I need some help here. OK, I’m actually totally stuck. I’m trying to teach myself OpenGL to enhance some graphics in some applications we have here at the office, and I just can’t find any help with this problem.

Anyway, I’m trying to create a basic model viewer. I decided to go with the ArcBall type of interface because of how nicely it ends up working. I actually got the arcball interface working great. The problem I have is with translation.

What I would like to try to do is to translate my model in a plane parallel to the screen, regardless of it’s rotation, all while keeping the center of rotation in the center of the screen.

This seems like it should be rudimentary at best, but no combination of translations and rotations seems to do the trick. I can get center-screen rotation or screen-plane translation to be mutually exclusive, but putting it together is driving me crazy. I never took a math modeling course, or a graphics course when I was in school, so all of this is totally beyond me…even if I knew where to start, I’d still be out of luck.

Anyway, I’ve gotten the arcball working using code samples from the internet. If I posted some code, would somebody be willing to take a look and help me work through it, or at least tell me what I need to do?

Thanks,
-Langecrew-

you can try


float current_matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, current_matrix);
glLoadIdentity();
glTranslatef(x_translate_amount, y_translate_amount, 0);
glMultMatrixf(current_matrix);

whenever you have to translate the model. As for rotations, just keep using your unchanged arcball code.

Thanks a lot for the reply!!

Hmm…
I think I tried something like this before. It works great to get the shapes translating parallel to the screen plane, but I still get the center of rotation translating with the shapes. I’d like to keep the center of rotation in the center of the screen. Maybe I’m just approaching it incorrectly??

Check this out:


procedure DrawScreen;
var
  CurrentMatrix: array [0..15] of GLFloat;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;

  //adjust the camera view
  gluLookAt( CamX, CamY, CamZ,
    SubjectX, SubjectY, SubjectZ,
    0, 1 ,0);

  glPushMatrix();

    //apply the arcball rotation
    glMultMatrixf(@ArcballRotationMatrix);

    glGetFloatV(GL_MODELVIEW_MATRIX, @CurrentMatrix);
    glLoadIdentity();

    glTranslatef(TransX, TransY, 0);

    glMultMatrixf(@CurrentMatrix);

    glPushMatrix();

      //draw the scene
      DrawModel;

    glPopMatrix();
  glPopMatrix();

  SwapBuffers(TheWindowHandle);
end;

Do I have to do something weird, like applying the reverse translation only to the arcball?

Thanks again,
-Langecrew-

In that case you apply the translation first, followed by rotation. Then it will rotate about the center of the screen.

Hey, thanks for the reply!!

I’ve tried this also. But then, the problem is that my model will no longer translate left/right/up/down parallel to the screen plane.

I’m starting to get an idea of what I think I need to do, and it scares me. Right now, I’m only using a translation value for X and Y. What I think I need to do, is to add a third translation value for Z. Next, I think I need to base all three translation factors (X, Y, Z) off of the current ArcBall rotation matrix that I have, thus allowing me to translate the model parallel to the screen plane. Problem being that I have absolutely NO idea how to do something like that. I only got ArcBall working using code samples online…I have no clue how the math works (yeah, I’m embarrassed to say it) :o

Anyway, I think I’ll turn this over to the opengl math forum and see what those guys say.

Keep those suggestions coming, please!!! I’m totally lost (and feeling dumb about it too)!

Thanks again,
-Langecrew-

If I am not mistaken, something like this should do the trick :


            glPushMatrix ();
	// view pos:
          glTranslated (0.1,1.0,0.3);
	// view rotate (add arcball here) :
          glRotatef (theta, 0.0f, 0.0f, 1.0f);
// fixed grid
            glBegin (GL_LINE_LOOP);
            glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (0.0f, 0.80f);
            glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (0.87f, -0.7f);
            glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (-0.87f, -0.7f);
            glEnd ();

// moved object :
	// object pos:
          glTranslated (0.1,0.5,0.3);
    // object rotate:
//          glRotatef (theta, 0.0f, 0.0f, 1.0f);

            glBegin (GL_TRIANGLES);
            glColor3f (1.0f, 0.0f, 0.0f);   glVertex2f (0.0f, 1.0f);
            glColor3f (0.0f, 1.0f, 0.0f);   glVertex2f (0.87f, -0.5f);
            glColor3f (0.0f, 0.0f, 1.0f);   glVertex2f (-0.87f, -0.5f);
            glEnd ();
            glPopMatrix ();


Hmm…Still no dice [sigh]

What about that theory of mine stated above somewhere? I can keep the center of rotation in the center of the screen, the only problem is that the model then translates in relation to itself, not the screen plane. What if I take 3 translation factors (X, Y, Z) and base them off of the current rotation, and how it relates to the screen plane…then I could calculate out how to translate the model parallel to the screen plane, rather than having the problems I have now trying to get away with only using translation factors for X and Y.

Or something like that. I mean, as complicated as that sounds, it would work…right??

Thanks a lot for all your input!!
:slight_smile:
-Langecrew-

Hi

I was wondering : did you ever find the answer to this question? I’ve been thru the same steps as you have, all without success. My best guess would be something like :

glTranslate(ScreenTranslation) //in screen coordinates
glTranslate(+ CenterOfRotation) //CenterofRotation is the rotated-1 ScreenTranslation
glRotate(Rotation)
glTranslate(- CenterOfRotation)
glScale()
glCallLists()

but it’s unsuccessful up to now.

Desperately looking for help

Andre

For information, my code is available at
http://sourceforge.net/projects/xflr5

Here’s what I use.

float4x4 rotation = trackball.GetMatrix();
glPushMatrix();
glTranslatef(-eyePosition[0], -eyePosition[1], -eyePosition[2]);
glMultTransposeMatrixf(rotation);
render();
glPopMatrix();

I like to think about the matrices that get applied to the vertices. Lets call the translation matrix T, the rotation matrix R and the vertices being submitted by render, v. Then v’ = TRv, which I like to think of as the rotation matrix being applied to v first (because its closest to v), followed by T.

Rotations are about the origin, and we need to rotate the object while it is still at the origin. After that we can move it to whatever position we like. Notice that if your object is not modelled around the origin, you’ll need to move it there first, something along the lines of v’ = TRCv where C is a “re-centering” matrix that moves your object the origin.

I’ve submitted an snippet of arcball code to Ziggyware, which he was nice enough to app-ify. It’s XNA based, but it might be helpful if you’re still having problems and you want to look through an example: http://www.ziggyware.com/news.php?readmore=283

Well thanks for your input. However I’ve tested this sequence of instructions, but it doesn’t address Langecrew’s concern : “What I would like to try to do is to translate my model in a plane parallel to the screen, regardless of it’s rotation, all while keeping the center of rotation in the center of the screen.”

If the sequence is
glRotate()
glTranslate()
then the model will rotate about the center of the screen, but unfortunately not translate in screen axis but in model axis…

…seems to be a pretty difficult issue

andre

You know, I did have some limited success through trial and error. It got to the point where I achieved what I was trying to accomplish, but it only half-worked. Let me explain that.

Here is what I did:

First off, I was using 2 translation factors for X and Y, and I was rotating before translating which caused these to be related to the model axis as you say. I realized I needed 3 translation factors if I was going to make it work (obviously). I added a 3rd translation factor for Z.

Second, to do translation I was capturing the keyboard arrow keys, so I needed a way to relate the 2D translation to 3D. So, after collecting the 2D translation from my keyboard procedure, I built a translation matrix using my X and Y translation factors. I eventually discovered, through trial and error, a partial solution; if I was to multiply this new translation matrix by the transpose of my arcball’s rotation matrix, the resulting matrix would then contain the proper X, Y, and Z translation factors that could be applied to the model and would cause the model to translate parallel to the screen.

So, now we come to the current problem…how do I make this work more than once? I’ll explain. Right now, you can rotate, then you can translate (parallel to the screen), then you can rotate again, but when you try to translate a second time the model jumps back to where it was after the first rotation and translates from there. The model also jumps back to being a constant distance from “the camera”.

It seems like I’m so close to my solution, I can almost taste it…but I’m not there yet. This is one of those times where I need some guru to have a hearty laugh at my expense, and chime in with something like, “Hey, you’re doing this all wrong. Try reading up on mathematical concepts A, B, and C. When you know how to use them, apply them to your problem in the following way…”

Who knows. I’ll post back if I figure out more.

Have a great day!
-langecrew-

Thanks to your input above, I managed to figure it out.
Once you have performed your second rotation, you need to recalculate the screen translation vector to avoid the jump.
To do this :

  1. get the rotation matrix R
  2. transpose (or invert it) to get Rt
  3. get the new screen translation vector by rotating the object’s translation vector : Trans_Screen = Rt x gl_Trans_Vector
  4. forget about the screen z translation : Trans_screen.z = 0

Cheers

andre