Elias
Elias

Reputation: 305

translating buffer after rotating

I want to be able to rotate a quad from the center. To do this I am following these steps:

  1. translate to (0, 0)
  2. rotate
  3. move back to destination point

I am stuck at point three. When I have rotated the matrix I want to move it one point to the right relative to the screen, but it moves one point to the right relative to the rotation instead.

enter image description here

Here is my code:

var moveBackX = ((-usedSprite.originX)/usedViewWidth);
var moveBackY = (((usedSprite.originY)))/usedViewHeight;
//The translation is already at (0, 0, 0)
mat4.rotateZ(mvMatrix, mvMatrix, rotation);
mat4.translate(mvMatrix, mvMatrix, [(moveBackX)/scaleX, moveBackY/scaleY, 0.0]);

mat4.translate(mvMatrix, mvMatrix, [((xPos)/scaleX), (-(yPos)/scaleY), 0.0]);

How do I fix this?

Upvotes: 0

Views: 97

Answers (2)

user1501157
user1501157

Reputation:

You must apply the translation in what we call "world space" instead of "local space". It seem your mat4.translate() function performs translation in local space.

To be more clear, what is going on with your translation function, is that the translation vector is multiplied by the rotation/scale part of the transformation matrix, which produce this translation along the local axes of your object (i.e local space). To prevent that, you should simply add the translation vector to the translation part of your transformation matrix.

Lets assume the following transformation 4x4 matrix:

Xx Xy Xz 0 // <- X axis
Yx Yy Yz 0 // <- Y axis
Zx Zy Zz 0 // <- Z axis
Tx Ty Tz 1 // <- Translation

Where :

mat4[ 0] = Xx; mat4[ 1] = Xy;  mat4[ 2] = Xz; mat4[ 3] = 0; 
mat4[ 4] = Yx; mat4[ 5] = Yy;  mat4[ 6] = Yz; mat4[ 7] = 0; 
mat4[ 8] = Zx; mat4[ 9] = Zy;  mat4[10] = Zz; mat4[11] = 0; 
mat4[12] = Tx; mat4[13] = Ty;  mat4[14] = Tz; mat4[15] = 1;

The rotation/scale part (axes) is the 3x3 matrix defined within [0] to [10] (excluding [3], [7] and [11]). The translation part are [12], [13] and [14].

To add a translation to this transformation matrix in world space, you simply have to do this:

mat4[12] += TranslationX;
mat4[13] += TranslationY;
mat4[14] += TranslationZ;

Upvotes: 2

Tamas Hegedus
Tamas Hegedus

Reputation: 29936

You just have to change the order of the transformations to:

mat4.rotateZ(mvMatrix, mvMatrix, rotation);
mat4.translate(mvMatrix, mvMatrix, [(moveBackX)/scaleX, moveBackY/scaleY, 0.0]);

mat4.translate(mvMatrix, mvMatrix, [((xPos)/scaleX), (-(yPos)/scaleY), 0.0]);

Here is a little demonstration using Context2D:

const ctx = maincanvas.getContext('2d');

maincanvas.width = 320;
maincanvas.height = 240;

function drawRect(color) {
  ctx.strokeStyle = color;
  ctx.beginPath();
  ctx.rect(0, 0, 50, 50);
  ctx.stroke();
}

ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.translate(100, 0);
drawRect('#ff8888');
ctx.rotate(Math.PI/12);
drawRect('#ff0000');

ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.rotate(Math.PI/12);
drawRect('#88ff88');
ctx.translate(100, 0);
drawRect('#00ff00');
canvas {
  width: 320px;
  height: 240px;
  border: 1px solid black;
}
<canvas id='maincanvas'></canvas>

Upvotes: 3

Related Questions