# Thread: Camera/Object Rotations in Local Axes

1. ## Camera/Object Rotations in Local Axes

Hello all,
Well, I'm new and this is my first post to these forums... I hope I'm not wearing out my welcome with the length and number of questions presented. I've tried to find answers to these questions elsewhere (books, tutorial/doc links from OpenGL.org, etc.) with no luck.
I'm having difficulty wrapping my brain around OpenGL's rotations. What I want to do is to have a number of objects (any number) in my scene, each of which I can rotate with 3DOF relative to it's own local coordinate system. Next, I'd like to be able to place the viewpoint within any one of these objects at any given time.
I did this in the past (years ago) with a 3D DOS engine which I derived from the engine developed in the book "The Black Art of 3D Programming". If I remember correctly, the engine was based on matrices (with all of the matrix math coded into the engine), but most of the work I did to enhance it worked with vectors. I was able to get true 6DOF local coordinate control of my objects (that is, pressing my "yaw", "roll" and "pitch" control keys would change the orientation of the object based on it's current orientation, not world axes). I accomplished this using some functions that I got from a guy on CompuServe's Game Developers Forum (back in the good ole days...). If I remember correctly, the program he gave me was called "yawpitch.exe", and it used two functions... one was called, I think, alt_az_to_eq() and I seem to remember getting the impression that this function's purpose was to convert from azimuth to equatorial coordinates... but I really never fully understood how the functions worked. What I did understand about the functions was that they used a lot of complex math, including many divides and a few square roots. Sorry for all the detail - I'm hoping it helps illustrate what I'm trying to do.
So, not initially worrying about camera angle, the first thing I did in my new OpenGL program (just to get things moving around on the screen) was basically this:

get_user_input(); // pitch, yaw, roll changes

total_pitch += pitch_change;
total_yaw += yaw_change;
total_roll += roll_change;

glRotatef(total_pitch, 1.0f, 0.0f, 0.0f);
glRotatef(total_yaw, 0.0f, 1.0f, 0.0f);
glRotatef(total_roll, 0.0f, 0.0f, 1.0f);
drawObject();

As you can imagine, this did not give me the local 3DOF rotations I was looking for (and I didn't expect it to). Putting off the task of digging up the "yawpitch" program and figuring out (again) how to implement it's functions, I just started fiddling around with what I had. So, I changed my program a bit, and to my complete astonishment, the local 3DOF control I was looking for materialized. I still don't exactly understand why it works and if someone could enlighten me, I'd appreciate it. Here's basically what I did in my loop:

get_user_input();
glRotatef(pitch_change, 1.0f, 0.0f, 0.0f);
glRotatef(yaw_change, 0.0f, 1.0f, 0.0f);
glRotatef(roll_change, 0.0f, 0.0f, 1.0f);
glGetFloatv(GL_MODELVIEW_MATRIX, object_matrix);
drawObject();

I'm loading/saving the matrix because I have several objects, and I'd like to keep each object's matrix around so that I can (eventually) extract information from the "current state" matrix for any given object (more on that in a moment) -- is this a good idea for a real-time engine?
So, groovy, my object now works the way I'd like it to (like an airplane in a flight sim)... but how do I get my "camera" to work the same way? I tried implementing the same incremental transformations with a separate matrix called (creatively enough) "camera", and then loading up this matrix and multiplying it with object_matrix, but it didn't work... implementing the camera this way still gives me camera rotations relative to world axes.
It looks like I could use the gluLookAt() function that I hear so much about... but I'm somewhat reluctant to stray from the core OpenGL API (I'm not really sure why... I think it's got something to do with the "purity" of this little learning project of mine). Is there an easy way to apply my rotations (like the easy way I stumbled onto 3DOF for my object) that would allow the camera to move in the same way, without using gluLookAt() or implementing my own (with that alt_az_to_eq() function that I don't understand)?
If I could get the ijk vectors out of object_matrix, I could use them, along with it's position, to get my "look at" point and "up" vector -- this would place my camera into the object, which is really what I want to do. Does this sound like the correct approach? If so, how exactly do I get these vectors out of my matrix?

Thanks a bunch,

2. ## Re: Camera/Object Rotations in Local Axes

it works because you are actually rotating by small degrees your object.

there's a theorem wich states that if angles are little enough, then the order of rotations is not meaningful (but i don't remember the name of this theorem, if it has one )

and since you're working incrementally (wich is THE WAY to go) your angles are small enough to create a local rotation.

now, i do the same (conceptually) by the use of a class i wrote, CdmyBasis, wich holds what is called a "orthonormal basis".

in this class, i hold the orientation and position of a object, and i modify its state by applying modifiers like rotate, move, place and so on.

then, i call method named make_object_mv() wich generates a modelview matrix wich reflects the state of the basis.

by keeping separate the basis from opengl, i don't need to ask the current matrix: i only need to supply it with a glLoadMatrix of glMultMatrix (in case of chained rotations, like a camera mounted on the hull of a spaceship)

and about glLookAt, it don't suit as a solution for your problem.
glLookAt needs a "up vector", wich is used to tell where the up direction is.
up exist where you really need it, like in quake: but as if understood, you're looking for a control system more resembling braeben's elite/frontier.

DMY

[This message has been edited by dmy (edited 11-26-2000).]

3. ## Re: Camera/Object Rotations in Local Axes

Howdy again,
Thanks for the response, DMY.

Originally posted by dmy:
it works because you are actually rotating by small degrees your object.
there's a theorem wich states that if angles are little enough, then the order of rotations is not meaningful
...
since you're working incrementally (wich is THE WAY to go) your angles are small enough to create a local rotation.
Hmmm.... I see a potential problem with doing it this way. The amount of my incremental rotations is based on frame rate. I determine how long the last frame took and use this amount to calculate how much to rotate in the next frame (for consistent rotation speeds regardless of framerate). So the size of my rotations is inversely proportional to the frame rate. If I were to run my simulation on a machine with an incredibly low frame rate (which I'd like to be able to do), won't this cause the rotations to deviate from being relative to the local axes, and approach being relative to the world axes? This would be weird - say, having your contorl input be equally divided between applying rotations relative to the world and local axes.

now, i do the same (conceptually) by the use of a class i wrote, CdmyBasis, wich holds what is called a "orthonormal basis".

in this class, i hold the orientation and position of a object, and i modify its state by applying modifiers like rotate, move, place and so on.
I'm not sure of the correct terminology, but doesn't "orthonormal basis" refer to the i j and k vectors that are mutually orthogonal and describe an object's local orientation relative to world axes? If so, couldn't you use your j vector (local "up") with gluLookAt()? You could also use your k vector (treating it as a point) to easily compute your target ("to") for gluLookAt(). This is what I am attempting to do, but I'm having a little trouble with maintaining my ijk vectors. (I think I just figured out what I'm doing wrong while writing this... I love it when that happens!) What I'm currently doing is storing each of the three vectors as a seperate constant matrix - each is an identity matricies with one translational component(i[12] = 1, j[13] = 1, k[14] = 1), then loading them up and applying my object's rotation to them (to keep them oriented with the object). If my thinking is correct (and it may not be) and I apply the rotations correctly (which I may not be), I should be able to get the "up" and "target" information that I need for gluLookAt(). I have yet to be 100% successful doing this.

One thing I'm trying to do is to leave all rotations to OpenGL, which has two potential benefits: (1) I don't have to get my hands too dirty messing with the rotations and matricies manually, and (2) I'm hoping to reap some performance increase if the OpenGL implementation and/or video hardware has transform and lighting capabilities, which I would expect to be significantly faster than the rotations routines and math/trig that I would otherwise do myself. Does this sound like valid reasoning?

up exist where you really need it, like in quake: but as if understood, you're looking for a control system more resembling braeben's elite/frontier.
It seems to me that any vector is a valid "up" vector for gluLookAt(), which would mean that gluLookAt can be used for complete 360 degree 3DOF rotations as long as you supply it with the correct "up" (even if "up" is really down in world space). Is this not correct?

Also, I'm not familiar with Braeben's Elite/Frontier. But I think that we're on the same wavelength here... the best example I can think of for what I'm trying to do would be any of the Descent series of games.

Thanks again,

4. ## Re: Camera/Object Rotations in Local Axes

Just a quick update: the lightbulb that went off in my head during my last post was right on the money. My ijk matricies + gluLookAt() is working perfectly now. I can switch my viewpoint from the default view at the origin to any one of my objects which have 6DOF in thier local coords. After I clean it up a bit I'll post what I wound up with to accomplish this.

Regards,

5. ## Re: Camera/Object Rotations in Local Axes

How fast is this method? Does the fact that you're doing all these matrix mults slow things down much? I'm trying to do the very same thing and was wondering how to rotate around local axes rather than world axes as well.

6. ## Re: Camera/Object Rotations in Local Axes

I've got a function that creates a rotation matrix which rotates vertices around a vector. I'm currently having a problem exactly in that stuff.

So, I start off with rotating my axises around the x axis. After that I rotate the axises around the y axis and the same according to the z axis. At the end, I hope to have a cool rotation matrix, and at least in my skybox, that is centered at the viewpoint, it works, it's rotating around my local axises. I can as well display the axises on the screen, making sure that it works. But now comes my problem. I loaded that matrix up, and wanted to move the viewer. That is, I do a glTranslatef with the negatives of the actual position. But, if I move around in the world, it begins to rotate really weird. What am I missing.

When I get that running, I'l have no problem posting that code here Punchey!

I appreciate any help from you guys out there! -Michael

7. ## Re: Camera/Object Rotations in Local Axes

So have you resigned yourself to use gluLookAt()? Or did you figure out a way to do it with plain ol' OpenGL?

8. ## Re: Camera/Object Rotations in Local Axes

Hello all,

Originally posted by Punchey:
How fast is this method? Does the fact that you're doing all these matrix mults slow things down much?
I'm not really sure how efficient this method is... my little world currently has just two simple objects (cubes), and my program's internal framerate timing is not quite working correctly. It tells me that I'm running at 100fps, which is probably close to correct, but I'm pretty sure that it's not working right because it either says 100, or 50 (nothing in between), and these numbers don't even correlate with my video refresh rate. I'm using timeGetTime(), and I think it's just a precision/rounding problem. NeHe has a tutorial up that has much better timing code (which, at first glance, looks very similar to the timing code in Quake), but I haven't had time to implement it.

As far as efficiency/speed goes, I'm currently working under the premis that if I need to do something, such as rotate an object or the camera, OpenGL's functions will be faster than ones I write myself (unless it's something simple like sticking a new number into a matrix for translation). My reasoning is twofold: (1) I'm not a C/C++ expert, and I don't know very much about optimization, or even what is considered slow/fast for a PII or greater processor (floating point math, trig, etc.), and (2) I'm assuming that the OGL driver will take advantage of hardware capabilities whenever possible which will only give me an advantage if I use OGL's functions, not if I do them myself. What I'm not sure of is wether or not a driver/video adapter that has hardware T&L capabilities (I have a GeForce II MX) will be able to use those features to accelerate matrix transformations the way I'm doing them (loading a matrix into the ModelView matrix, using glRotatef()/glTranslatef(), and then saving the matrix back to my local array variables).

Originally posted by Michael Steinberg:
...it works, it's rotating around my local axises. I can as well display the axises on the screen, making sure that it works. But now comes my problem. I loaded that matrix up, and wanted to move the viewer. That is, I do a glTranslatef with the negatives of the actual position. But, if I move around in the world, it begins to rotate really weird. What am I missing.
I'm not really sure what the problem is, but it sounds like it might be that the rotation you're applying is being applied to your star field about the world origin with your local rotations... which would look weird... are you translating the star field along with the viewer? The way I'm doing things, I think that you would be able to never apply any rotations to the star field, just translate it to the viewer's locatoion before drawing (so that you never wind up running into the skybox)... I think(?). I'll post my code when I clean it up (and figure out how/where to post it).

Originally posted by Punchey:
So have you resigned yourself to use gluLookAt()? Or did you figure out a way to do it with plain ol' OpenGL?
Well, I've come to the conclusion that using gluLookAt() is probably the best solution. I don't know much about how/where the glu functions are actually implemented, but I think there's only two possibilities, and in either case it would be better than doing it manually. As far as I can tell, the two cases are (1) the glu functions are implemented in the hardware specific driver - this would be optimal because, as I said before, this would mean that the possibility exists for hardware acceleration of functions like gluLookAt(), or (2) the glu functions are in a generic library that hardware vendors do not include in thier optimized driver. In this second case, gluLookAt() is not optimized for the hardware, and just makes calls to the core (driver) functions (glRotate, etc.). If this is the case, I could impelment my own viewing matrix manipulations that could (theoretically) be optimized to my particular needs and be more efficient than gluLookAt(). However, as I stated, I'm not that good , and anything I wrote myself would probably not be nearly as good as the stuff written by the people that really know what they are doing.

How/where should I post my code? I could just isolate the relavent code and post it in a message here, but if I can zip up the whole MSVC 6.0 project along with the textures and everything, you guys could see exatly what I'm doing and run my program to see it work.

Regards,

[This message has been edited by BradlyP (edited 11-28-2000).]

[This message has been edited by BradlyP (edited 11-28-2000).]

9. ## Re: Camera/Object Rotations in Local Axes

I implemented that rotaion stuff myself.
Okay, gonna make my problem clearer.

1000
0100
0010
0001

Now, it seemed to me, that the first row represents the x-Axis and so on. So I tried it, and if I'm at the world's origin, and only apply rotation, it rotates beautifully around the viewpoint. Now, I wanted to move, ie: apply the position-translation only to the object, not to the skybox. If I'm at the origin, the objects rotate well. Now when I'm at another place, when I rotate now, it makes really weird results. It seems that it's is not rotating around my position, but still around the origin. Maybe, I'm not too sure. Should I post some code here?

Generally, what is the way to go.
Set Rotation-matrix
Set Translation-matrix
Or the other way around? Or something else?

I can't use gluLookAt, since I have to hold my own rotation matrix, because I need to rotate the world around these axises in the matrix.

Or, how to extract an axis out of a matrix, is it so simple as I thought it would be?

10. ## Re: Camera/Object Rotations in Local Axes

Not sure if this info will help you any, but the glTranslate/glRotate functions work in the reverse order that you use them. They do this becuase of properties of matrices and matrix mathematics. Say you have coordinates for a cube that gets drawn at the world origin with no transformations applied. If you do this..

glTranslatef(0.0, 0.0, -10.0);
glRotatef(45, 0.0, 1.0, 0.0);
drawCube();

The cube first gets rotated 45 degrees around it's y-axis, then moved down the z-axis 10 units. Since the cube's coordinates center it on the world origin, it is the same as rotating it around it's local coordinate system.

glRotatef(45, 0.0, 1.0, 0.0);
glTranslatef(0.0, 0.0, -10.0);
drawCube();

The cube is first translated and then rotated. Since both of these functions basically operate on the world coordinate system you are rotating around the world's y-axis 45 degrees instead of the cube's "local" y-axis.

So generally, you'd want to do the glTranslate then glRotate. The same goes for multiplying your own matrices. If you have a matrix T for a translation and a matrix R for rotation doing T*R is like calling glTranslate/glRotate and doing R*T is like calling glRotate/glTranslate.

Does that help any? Or did I miss the real meaning of the problem and my explanations are totally irrelavent?

Page 1 of 4 1234 Last

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•