Why is my Rotation not centered?

Started by
6 comments, last by Trienco 11 years ago

After much reading, trial and error, I managed to get the following code:


void Game::Draw()
{
    mat4 mProjection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
    mat4 mView = glm::lookAt(cameraPosition, cameraTarget, headsUp);

    mat4 mModel = mat4(1.0f);
    quat qModelRotation = quat(vec3(object.rotationX, object.rotationY, object.rotationZ)); //values are in degrees 0~360 already
    mat4 mModelRotation = mat4_cast(qModelRotation); //quat to mat4
    mModel = mModel * mModelRotation; //applying the rotation to my model
    //mModel = mModel * mModelTranslation * mModelRotation; //this if I put translation as well

    mat4 MVP = mProjection * mView * mModel;
    //send MVP to the shader, where gl_Position = vertex * MVP;
}

The object's rotating fine on the Z-axis, around it's center, but in the X and Y axis it's rotating around one of it's edges, why?

My object's a cube with values from -1 to 1 only.

I've been suggested to translate to the origin, rotating, and then translating, but I'm multiplying the rotation with the model without any translation and it's center is still off.

Advertisement

Unless there's some matrix multiplication order difference between OpenGL and DirectX I'm not aware of, the construction of your MVP matrix seems backwards. Shouldn't it be mModel * mView * mProjection?

Similarly, to construct your mModel matrix, I believe the order of transforms should be (SRT) Scaling, Rotation, Translation.

[size="2"]Currently working on an open world survival RPG - For info check out my Development blog:[size="2"] ByteWrangler

mModel * mModelTranslation * mModelRotation

This is the wrong way around. It should be rotation * scalation * translation and then, as Postie said, Model * View * Projection. If you applie the translation first, the cube will still rotate around the origin, thus having its rotation center offset.

I've followed this tutorial, where it stated that the matrix multiplication is the inverse of the operations (http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/).

I tried inverting the order though, but then my objects doesn't show anymore.

**edit**: This gave me the idea to change the initial Z position of the rotating object to -1.0f, and now it seems to be rotating around it's center.

I don't know what this relates though, my object's maximum length is 2 (-1 to +1), so am I supposed to add half the object's length in order to rotate around it's center? (though with this I discovered how to rotate around a specific point)

Now I think there might be something throwing the calculations off, since I set the object's XYZ to 0 when I create it... or there's something wrong with my rotation calc, I'm not sure.

Probably depends on the matrix implementation. If you want to make sure, write:


model = rotation * (scalation * transformation);

MVP = model * (view * projection);

Still nothing showing up?

I removed the scale and translation so I could just figure the rotation part, so I tested it like this:

model = model * rotation;

MVP = model * (view * projection);

And nothing shows. I can see that my object is still moving it's xyz and so is the camera, but it's not showing on screen.

I'm really concerned now with this rotation center, it would be really annoying to calculate the center of the object's Z position every time I load so I can add half to the initial position... what I find weird though is that the Z axis rotation is perfectly fine, just the XY that are going on the most far Z border of the object (tested with a couple objects now, it's always centered in the farthest Z vertex).

glm uses the same convention as GLSL. and OpenGL Matricies should thus be multiplied such that

FinalMatrix = Projection * View * Model

so your rotation should be constructed as

Model = RotationAroundOrigin * TranslationFromOrigin * RotationAroundObjectCenter

edit: Just saw your comment: //values are in degrees 0~360 already

Most math functions normally take angles in Radians, and this could also be part of the problem.

double edit:

I'm really concerned now with this rotation center, it would be really annoying to calculate the center of the object's Z position every time I load so I can add half to the initial position

The simplest thing to do is keep your rotation and position separated and build up the model matrix every frame from a position and orientation. Makes it easier to understand these incremental changes to the object.

So Model = Translate * Orient * Parent, where for un-attached object the Parent matrix is the Identity matrix.

Saying that operations are in reverse order has always annoyed me. At university when we were taught OpenGL still using glTranslate and glRotate, they told us "OpenGL is applying your transformations in reverse order". At which point I thought "that has to be just about the most idiotic way to look at it and is only useful if you love getting head aches from trying to keep track of your transformation hierarchy".

The simple matter of fact was that in OpenGL all transformations happened relative to the existing transformation. glTranslate followed by glRotate would move your object to its position and then rotate it around its center. Unfortunately, many people insist on looking at transformations to be in "world space", so what was actually very neat and intuitive appeared completely backwards to them.

So after a quick test with glm (and coming to the conclusion that my own library is doing matrix multiplication backwards to let me stick to "object space"), the only important thing for you is to decide if you want to think "local" or "global".

If you prefer to think about transformation to use object space, for example "move plane forward by 5 units and make it pull up 90°", you do

result = glm::translate(glm::mat4(1.0f), 0,0,5) * glm::rotate(glm::mat4(1.0f), 90, 1,0,0);

If you rather think global (outside forces pushing your plane around), "push plane 5 units to the south and rotate it 90° around the east-west axis", you do it the other way round

result = glm::rotate(glm::mat4(1.0f), 90, 1,0,0) * glm::translate(glm::mat4(1.0f), 0,0,5);

So basically, if you put your matrix on the left it's "global" and if you put it to the right it's "local".

That also means that even though you probably learned that the view transformation is applied afterwards, when thinking "local" it is actually the very first transformation to be done (ie, it's left of your model transformation).

Bottom line, whenever somebody tells you about the correct order for your transformations without mentioning if they are supposed to be based on object or world space: ask.

f@dzhttp://festini.device-zero.de

This topic is closed to new replies.

Advertisement