Reputation: 3590
I don't know the right term to describe it that is why I can't find it in Google. All I want is to scale the object, specifically, 2D rectangle but keep it on its XY coordinates.
My current solution is this:
glTranslatef(x, y, 0);
glScalef(scaleX, scaleY, 0);
glTranslatef(-x, -y, 0);
drawRect(x, y, width, height, texture);
I just pretend glScale as glRotate as of rotating on its center, it somewhat work but I can see the little adjustments on its coordinate when scaling to other value.
And also, which is better to do, glTranslate or just apply variables such as x,y on vertices. I can't see no difference when switching from those two but I am worrying about adding the "pushing and popping matrices" will affect the behavior of other objects on the scene and performance of my program, because I will use lots of this rectangles.
Update:
So you can visualize how simply I want to achieve
Upvotes: 5
Views: 5080
Reputation: 5555
The general pattern for a rotation by angle phi
(applies to other affine transformations as well) that keeps the point (x,y)
fixed is
TRANSLATE(-x, -y)
ROTATE(phi)
TRANSLATE(x, y)
Transformations are applied in order from top to bottom. So you're moving the point (x,y)
into the origin at (0,0)
. It will thus not be affected by the actual rotation. When you're done, the second translation reverses the effect of the first.
This is not limited to OpenGL, but rather applies to any type of graphics processing that supports affine transformations (through matrices or quaternions).
Upvotes: 0
Reputation: 14750
I suppose that <x
,y
,0
> is the position of the bottom left corner of your rectangle in the "canonical" coordinate system (I mean the one we start with).
With these assumptions, you may achieve your goal by resetting the modelview stack to identity, and then move to the object space, before doing the scaling. So you are indeed pretty close, but depending on what you did before with the modelview matrix, you could experience variations in the outcome.
The following code should do what you want:
glPushMatrix();
glLoadIdentity();
glTranslatef(x, y, 0);
// now in "object space"
glScalef(scaleX, scaleY, 0);
drawRect(0, 0, width, height, texture);
glPopMatrix();
I don't know what the draw
function does, but I suppose that it just emits a bunch of glVertex
and glTexCoord
calls, ie. it does not meddle with the modelview matrix, otherwise my code might well break it.
Note that if you wrap all object rendering with glPushMatrix
and glPopMatrix
calls, you should not need the glLoadIdentity
call, and it might even be counter productive. For instance, if you organize your object data as a hierarchy, with each sub object being relatively positioned to its container, then you will need to remove that call completely while recursively rendering the object hierarchy.
Another concern is the one of efficiency. Saving and restoring matrices are fairly costly operations. Given that your question code is using immediate mode, I supposed that it was not your main concern. It will certainly be faster to apply the object transformation by hand (that is, by computing them with your own matrix library), and submit them to opengl without any call to the opengl modelview manipulation routines. However That should be covered by another (more math oriented) question and answer.
Upvotes: 4