# Scale Matrix Transform without moving primitive

So I have the following....

GLbyte vShaderStr[] =
"attribute vec4 vPosition;    \n"
"uniform mat4 move;           \n"
"uniform mat4 scale;           \n"
"void main()                  \n"
"{                            \n"
"   gl_Position = vPosition;  \n"
"   gl_Position = move * gl_Position;  \n"
"   gl_Position = scale * gl_Position;  \n"
"}                            \n";
...
void glScale2D(float y, float x){
float zoom[16] = {
x, 0, 0, 0,
0, y, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
GLint projectionUniform = glGetUniformLocation(userData.programObject, "scale");
glUniformMatrix4fv(projectionUniform, 1, 0, &zoom[0]);
}
...
glScale2D(userData.widthScreen/userData.heightScreen, userData.heightScreen/userData.widthScreen);


This works, however, it also moves the primitive so it goes from...

To...

Is there a matrix I can use to scale the primitive without moving it?

It seems that the problem here is that you have only one coordinate space, a fusion between the world space and the object space. Scaling your object impacts its position because the coordinate space where the scaling occurs isn't centered on the origin object.

To fix this issue, you need to have two different coordinate spaces: the object space, and the world space. You set the vector of your object in its own object space, around its point of irigin, which is the one you will scale, and then you use the world space to put the object at the right position.

You need to represent your object in its own coordinate space :

      X     Y    Z
a:   0.0  -0.5  0.0
b:   1.0   0.5  0.0
c:  -1.0   0.5  0.0


Here, a triangle centered around the origin point (0;0;0).

Then, you transform the object space with a scale matrix, let's say with twice the size in both X and Y. You do that by multiplying a scaling matrix, just like you did in your code. You get :

      X     Y    Z
a:   0.0  -1.0  0.0
b:   2.0   1.0  0.0
c:  -2.0   1.0  0.0


And finally, you transform the object-space coordinate system to a world-space coordinate system by multiplying with an object-to-world matrix. In this case, this matrix would be a translation matrix, given that you don't want your object to be at the origin point of the screen. Let's say you want the center of this object to be at (10.0; 20.0; 0.0). With the translation applied, you get :

      X     Y    Z
a:  10.0   9.0  0.0
b:  12.0  11.0  0.0
c:   8.0  11.0  0.0


As you can see, the position of the object isn't impacted by the scale anymore. You can change the scaling ratio of the object without impacting its position in the world.

You can apply a 2D or 3D scaling matrix along the major axis by multiplying the x/y/z components by the appropriate scaling value. Here are two examples of scaling matrices, in 2D, and 3D, using row matrices.

2D: | 0.5f, 0.0f |
| 0.0f  0.5f |

| 0.5f, 0.0f, 0.0f |
3D: | 0.0f, 0.5f, 0.0f |
| 0.0f, 0.0f, 0.5f |

| 1.0f, 0.0f, 0.0f |
3D: | 0.0f, 2.0f, 0.0f |
| 0.0f, 0.0f, 1.0f |


These will each scale a vertex by half along each axis. The third example demonstrates a scaling of 2.0, on only the Y axis. Again, using row matrices. These are simply modifications of the identity matrices.

EDIT I suspect the source of your problem is that you are performing scaling to the object in the incorrect coordinate space. Applying scaling to an object in world space will scale it relative to the world origin. You most likely want to scale it relative to the objects origin, which means you need to scale the object when operating on object coordinates.

• Actually It seems to have worked when I only scale 1 axis. This seems to make sense to me for some reason. I changed to glScale2D(1, userData.heightScreen/userData.widthScreen); and because it does not scale the y it does not it does not move. I think your answer still missed my question, how do you scale the y without moving the triangle up. Jun 17, 2013 at 15:11
• Applying a scaling matrix to a vector will not perform translation, everything should scale around the origin. If the origin of your object is in the top left hand corner, then it will scale relative to that, and not relative to the center. Make sure you are following the correct order of operations when performing matrix operations on a vertex. ISROT - Identity, Scale, Rotate, Orbit, Translate
– Evan
Jun 17, 2013 at 15:13
• Makes sense so if I would change my origin from the center to the left hand corner this would help fix the issue right? Makes sense to that, any chance of including that in the answer to make it more applicable? Jun 17, 2013 at 15:38