PDA

View Full Version : Transforming + Rotating an object without going weird?



joehot200
12-18-2013, 08:14 AM
Hi, i guess im fairly advanced in lwjgl however this is a newbie question.

When i rotate an object and then translate the object (its a model ship in a VBO), the object rotates around the centeral point where it first spawned and not from its own centre.
When i translate the object and then rotate it the ship rotates around the centre but does not translate the right way (so the ship always moves the same direction).

How can i fix this?

Thanks.

Edit: Am using the glRotatef() and glTranslatef().

thokra
12-18-2013, 09:22 AM
Just to get a clue where we can pick you up, do you have a basic understanding of linear algebra?

joehot200
12-18-2013, 09:35 AM
No, i don't unfortunatley. I may be using it or whatever however i do not actually know a lot of the names of the code i am using as i often copy it from elsewhere and change bits around to learn what certain pieces do.
I actually work more with lwjgl rather than opengl, though the calls/code are the same.
I also don't go to school (i am 13), so don't expect me to be able to understand cosigns etc so well.

thokra
12-18-2013, 10:36 AM
Even though you're 13, if you're into this stuff, I recommend reading Lengyel's book, "Mathematics for 3D Game Programming and Computer Graphics". It's good learning material and when I look up the most common stuff, this is the book I go to. If you're not solid in 3D math, don't slip anything. Read it, understand it and be amazed at how awesome math is. ;)


i often copy it from elsewhere and change bits around to learn what certain pieces do

That's fine if you're trying to figure out what a specific funtion does. However, if you want to really do 3D programming, there is absolutely no way around the appropriate math portions.


I actually work more with lwjgl rather than opengl, though the calls/code are the same.

The interface doesn't change how the encapsulated GL calls operate. LWJGL is just a wrapper usable with Java (since OpenGL implementations are usually implemented in C and LWJGL needs to interface with the C library through the JNI).


I also don't go to school (i am 13)

At that age, aren't you supposed to go to school? (Don't know where you're coming from.)

Regarding your problem at hand, for now, it should suffice to know that matrix rotation leads to rotation of a position around the origin, i.e. (0, 0, 0, 1), of the current coordinate system. There is nothing you can change about that, but there's a simple trick to rotate around an arbitrary point in space: you translate the center of your object to the origin, then rotate, and then translate it back to whatever position you want it to be located at. If the original and resulting position are the same, you effectively rotated around your objects center.

Now, a translation is nothing more than moving a point from one place to another. To achieve the above, in 3D you'll need a 3D vector to describe the direction of the translation and the distance you want to translate the object. The distance is implicit - it is the length of the translation vector. So, if you have a vertex at position (1, 1, 1) and want to translate it to the origin, you'll need a translation vector (-1, -1, -1). The resulting position will be (0, 0, 0) (because (1,1, 1) + (-1, -1, -1) = (0, 0, 0))

To translate it back to where it came from, you'll need to translate in the inverse direction, i.e. you need to negate the translation vector: (-1, -1, -1) then becomes -1 * (-1, -1, -1) = (1, 1, 1). Apply that to the current position (0, 0, 0) and you'll get (0, 0, 0) + (1, 1, 1) = (1, 1, 1). And where back to our original position.

Does that make sense to you? Does it help?

joehot200
12-18-2013, 12:22 PM
I just typed a whole reply... and it didnt appear when i posted it. :S

Anyway your answer was very good, very informative and helpful, however could you post the exact code in the exact order i need? Certain sites say i should put the code in different orders or backwards etc, and it confuses me.

In england home "education" is allowed. Unfortunatley a lot of home "educated" people don't actually educate themselves, unlike me.

I will look into the book, thanks. Will probably get it too.

I did have a longer reply however i am too tired to type it all out again. Thanks a lot for the informative reply. I do not get that on many forums.

thokra
12-19-2013, 02:47 AM
however could you post the exact code in the exact order i need?

I'll first go into the math a bit.

1. Assuming you know the center of your object to be at point C. For each vertex, a translation T encoded into a translation matrix MT needs to be applied which translates in direction -C, i.e. for each vertex vi, the initial transformation is vi' = MT * vi (with i in [0, #vertices]).

2. Then a rotation R follows, encoded in a rotation matrix MR. For each translated vertex vi', a rotation is applied as follows: vi'' = MR *vi'.

3. Afterwards, the rotated vertices are translated by MT-1. For each rotated vertex vi'', the final position results vi''' from vi''' = MT-1 * vi''.

The reason I seperate the steps like that is simple: you'll probably implement the above exactly the same way using the fixed-function pipeline, i.e. you first call glTranslatef(), then glRotatef() and then glTranslatef() again. However, what you actually end up with is a concatenated transformation matrix, which encodes both translations and the rotation: vi''' = MT-1 *MR * MT * vi = (MT-1 * MR * MT) * vi =Mcomplete * vi

Expressing this in fixed-function OpenGL can be achieved in more than one way, but the usual approach is this (let's assume you want to rotate your object about the y-axis and an angle of 45.0 degrees):

// assume top of the MODELVIEW stack is the identity M_ident

// This is equal to computing M_ident * M_complete = M_complete
glTranslatef(Cx, Cy, Cz);
glRotatef(45.f, 0.f, 1.f, 0.f);
glTranslatef(-Cx, -Cy, -Cz);

// This is then equal to v_i''' = M_complete * v_i (with i in [0, VERTEX_COUNT]).
drawObject();

HTH! If you have any further questions, let us know.


I do not get that on many forums.

That's what seperates us from the masses. ;)

joehot200
12-19-2013, 06:58 AM
Unfortunatley that did not work.
(Using spaces in links due to site denying links)

My current code is:
http://pastebin.com/1a2Nk6HC

The problem is:
http://youtube.com/watch?v=6Rviu9dXBKw&feature=youtu.be

Thanks.

thokra
12-19-2013, 07:10 AM
The video is funny. :D

So, you obviously want the ship to sail along a path, right?

joehot200
12-19-2013, 07:17 AM
Yes, i would like it to sail in a straight line and turn at the ship's location and not the origin location before translation.

thokra
12-19-2013, 07:30 AM
But that works just the same. As long as the direction of the ship doesn't change, you translate along this direction. As soon as you hit a point where the ship is supposed to be rotated, you first translate to the origin, then rotate, translate back and then sail along the new direction.

Translating like that normally involves linear interpolation between points of rotation. Beware that, depending on the length of the line segments, translation speeds will vary, but you'll see that yourself. ;) It's a different topic and should be tackled separately once you got the basic stuff down.

For some path, defined with n control points, the (pseudo) code might look a little like this:



// move along a path
Vector3 currentPoint = start;
Vector3 nextPoint = currentPoint + 1;
Vector3 position = currentPoint;

while(nextPoint != end)
{
// We reached a control point, rotate here
if(position == nextPoint)
{
rotateShip(position, angle);

// set the new interval for interpolaton
currentPoint = nextPoint;
nextPoint = nextPoint + 1;
}
else
{
// set position to a new point in the interval [currentPoint, nextPoint]
translateShip();
}

renderShip();
}


The linearly interpolated position is computed with: position = currentPoint + (nextPoint - currentPoint) * n (where n is in [0, 1]). To calculate the angle between the current direction of the ship and the direction of the ship at the next control point, you can take the angle of the current direction and the x-axis and the angle of the next direction and the x-axis, compute the difference and then rotate accordingly.

joehot200
12-19-2013, 08:28 AM
Im not understanding this. Whatever order or whatever i select, it just doesn't work. I know i'm probably being dumb. :(
glTranslatef(-0, -0, -plus);
glRotatef(rotate, 0.f, 1.f, 0.f);
glTranslatef(0, 0, plus);

Oh i saw your edit. But i still just don't get it. I want to be able to drive the ship around with the arrow keys, im not understanding your points business :S.
Also i would like to be able to translate and rotate at the same time.

Now trying glTranslatef(0, 0, plus);
if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)){
rotate++;
}
glTranslatef(0, 0, -plus);
glRotatef(rotate, 0.f, 1.f, 0.f);
glTranslatef(0, 0, plus);
, it still isn't working. Even though the ship is at the centre it still rotate's around the ships spawn point when its translated back out.

Alphaomega86
12-25-2013, 02:23 AM
As i can see here, you are still using fixed function matrix pipeline of OpenGL. Did you set the matrix mode to MODELVIEW?`

glMatrixMode(GL_MODELVIEW);

This may fix your problem.

Aleksandar
12-25-2013, 01:42 PM
Well, let's try to finish this agony. ;)
Although you haven't got a linear algebra I hope you'll understand the following guidelines:

1. The ship is probably drawn in the at coordinate-system's origin (the center of the ship is at (0,0,0)). If not, translate it to the origin.

2. The transformations can be thought of using global or local coordinate-system. If you "think" in global coordinate-system, transformations are executed in opposite order considering the way they appear in the code.
For example, consider the following sequence:

glTranslatef(x,0,0);
glRotatef(a,0,0,1);
glTranslatef(0,y,0);
DrawObject();

The object is first translated down the Y-axis, then rotated around the Z-axis of the global coordinate-system, then translated along X-axis of the global coordinate-system.

But if you "think" in local coordinate-system, then transformations are done in the exact order they appear in the code. So, local coordinate-system is translated along its (local) X-axis, then rotated around its (local) Y-axis, and finally translated along its (local) Y-axis. After all those transformations of the local coordinate-system the object is drawn using it. The result is the same. These are just two ways of thinking. The first moves object along global axes, while the second moves local coordinate-system along local axes.

In your case, probably the following will do the trick:

glTranslatef(x,0,z);
glRotatef(a,0,1,0);

a - azimuth of the ship, (x,0,z) - position of the ship

Both x and z coordinates must be calculated according to previous position and azimuth.