PDA

View Full Version : rotating an object around a defined point



aiscape
01-26-2003, 02:24 AM
Hi!
I've written a function that should rotate my object around a defined
point by a defined angle, but somethings wrong with it. When calling this function repeatedly using the same parameters in the windows draw function the motion of my object describes something like an ellipse and its center isn't 0,0,0.

void CMyObject::RotateAroundY(GLdouble _ang, GLdouble _x, GLdouble _y,
GLdouble _z)
{
_ang = _ang * PI / 180.0;

m_yrotationsmatrix[0] = cos(_ang);
m_yrotationsmatrix[2] = -sin(_ang);
m_yrotationsmatrix[8] = sin(_ang);
m_yrotationsmatrix[10] = cos(_ang);

glMatrixMode(GL_MODELVIEW);
glLoadMatrixd(m_modelmatrix);

GLdouble tcx = -(m_modelmatrix[12] - _x);
GLdouble tcy = -(m_modelmatrix[13] - _y);
GLdouble tcz = -(m_modelmatrix[14] - _z);

m_translationsmatrix[12] = tcx;
m_translationsmatrix[13] = tcy;
m_translationsmatrix[14] = tcz;
glMultMatrixd(m_translationsmatrix);

glMultMatrixd(m_yrotationsmatrix);

m_translationsmatrix[12] = -tcx;
m_translationsmatrix[13] = -tcy;
m_translationsmatrix[14] = -tcz;
glMultMatrixd(m_translationsmatrix);

glGetDoublev(GL_MODELVIEW_MATRIX,m_modelmatrix);
}

I've tested these values:
_x,_y,_z = 0;
Initial m_modelmatrix[12] = -3;
m_modelmatrix[13] = 0;
m_modelmatrix[14] = 0;

Any idea what's wrong?
Thanks.

Jambolo
01-26-2003, 02:59 AM
How about this instead:



glPushMatrix();
glTranslatef( _x, _y, _z );
glRotatef( -_ang, 0.f, 1.f, 0.f );
DrawThing();
glPopMatrix();

aiscape
01-26-2003, 03:55 AM
Hi!
If I do it this way, my object doesn't store the transformations. What I want is something like: rotate object around a point, take the new position and rotate it once more around this point. The object must provide and compute all information. Your answer inn't OO-Code. The function that I posted is the rotatearound-method. Any drawing is not to be allowed inside it.
Aiscape

jwatte
01-26-2003, 08:54 AM
Because you mentioned wanting an "OO" design, I figured I'd describe my approach to that, first. But don't worry, there's a bit of math at the end, addressing the original point of how to rotate a piece of geometry around a specific point.

The design I like is one that has three separate components:

The thing deciding what to draw.
The thing deciding how to draw.
The thing doing the drawing.

In reality, "what to draw" would be your scene graph, "how to draw" would be your mesh, and "doing the drawing" would be your renderer abstraction. Your scene graph probably uses some instance meta-data or an instance interface to keep track of things like position and orientation.

Which is a long way of saying:

Your call should end up looking something like:




SceneGraph::renderStuff() {
foreach visible item in allItems {
renderer->drawMesh( item.mesh, item.shader, item.pos, item.ori );
}
}


The actual math of setting up the viewing matrix should probably be inside the renderer, not inside the item, because otherwise each item needs to know about things like what your camera is (or whether you're rendering for, say, a projected shadow).

Thus, using GL commands only, your drawMesh() might look like this:




Renderer::drawMesh( mesh, material, pos, ori ) {
material->setupState();
glLoadIdentity();
glTranslatef( -camera.pos.x, -camera.pos.y, -camear.pos.z );
glRotatef( -camera.angle, camera.up.x, camera.up.y, camera.up.z );
glTranslatef( pos.x, pos.y, pox.z );
glRotatef( ori.angle, ori.x, ori.y, ori.z );
setupPointers( mesh.pointers() );
drawLists( mesh.lists() );
}


After doing this for a little bit, you'll realize that keeping "ori" as a quaternion, and doing the position/orientation math using quaternions and vectors is easier, and then you spit out the combined modelview into a matrix and load it with LoadMatrix().

If you have geometry that's currently centered around some local origin X, then to rotate around this origin, you want to actually perform these operations in squence:




Translate object by -localOrigin
Plain rotation (around 0,0,0)
Translate object by +localOrigin


If you in addition want the object positioned somewhere other than at its local origin in the "world" space, you'd have to add that offset to the last translation in this squence. That would be the camera position in the above pseudo-code.

Typically, the "local origin" is set by a 3d model artist inside the modeling program, as the "pivot" or "node" point for the object. Most often, the exporter will pre-bake the "offset by -localOrigin" into the exported data, so you don't have to do that yourself.

If you're getting oval or lopsided rotation, then it's likely that your notion of "local origin" for the geometry in question isn't actually the point you want. The local origin usually needs to be the apparent center of mass for the rotation to look good.

quentapole
01-26-2003, 07:33 PM
Iam not sure but I think you can try using
quaternions to rotate the object. You can rotate about the original axis and it also prevents gimbal lock

V-man
01-26-2003, 07:46 PM
>>>If you're getting oval or lopsided rotation, then it's likely that your notion of "local origin" for the geometry in question isn't actually the point you want. The local origin usually needs to be the apparent center of mass for the rotation to look good.<<<

I think you forgot to provide an algorithm for computing the center of mass. http://www.opengl.org/discussion_boards/ubb/smile.gif

jwatte
01-26-2003, 10:14 PM
Computing the apparent center of mass? Easy:




while( !curArtist &amp;#0124; &amp;#0124; curArtist->clue() < CLUE_THRESHOLD ) {
curArtist = find( gArtists.begin(), gArtists.end(), SomeArtist );
centerOfMass = curArtist->estimateApparentCenterOfMassFor( mesh );
}

return centerOfMass;