If you are working in 2D and only need the angle, keeping the angle separately yourself seems like a good option. It might be possible to retrieve the 2D rotation from the transformation matrix, but perhaps only if only certain transformations have been made.
Indeed, the sample code in the ApplyMatrix() documentation gives us a clue:
Code:float ct = cos(PI/9.0);
float st = sin(PI/9.0);
// Matrix for rotation around the Y axis
applyMatrix( ct, 0.0, st, 0.0,
0.0, 1.0, 0.0, 0.0,
-st, 0.0, ct, 0.0,
0.0, 0.0, 0.0, 1.0);
If you had access to the transformation matrix, the "ct" and "st" elements from the first row could be used to work out the angle (by applying inverse sin and cos operations and working out what quadrant it is in), but... and this is a big but... that is making a massive assumption about the contents of the rest of the matrix. If the "-st" element, for example, is not the same as the negative of the "st" element, some operation other than a simple rotation must have been performed.
An alternative solution!I did some tinkering and came up with these handy functions.
Code:
// Returns a 4-element float array with transform information
// { originX, originY, rotationInRadians, scale }
// Only works for P2D display mode
float[] getTransform()
{
// Origin
float x0 = screenX(0, 0);
float y0 = screenY(0, 0);
// Location of (1, 0) on X-axis
float x1 = screenX(1, 0);
float y1 = screenY(1, 0);
// Rotation determined by angle of X-axis
float rot = atan2(y1 - y0, x1 - x0);
// Scale determined by distance of a point 1 unit from the origin
float sc = dist(x0, y0, x1, y1);
return new float[] { x0, y0, rot, sc };
}
// Pass a float array containing transform information
// { originX, originY, rotationInRadians, scale }
void setTransform(float[] xyrs)
{
resetMatrix();
translate(xyrs[0], xyrs[1]); // Origin
rotate(xyrs[2]);
scale(xyrs[3]);
}
Apologies if there are any typos and it doesn't work; I've had to transcribe this from another PC without net access (and this PC doesn't have Processing installed).
I (re-)wrote this as a function returning an array of values in case you decide you wish to remember multiple transformation states (in which case setting simple variables in-line will be a major hassle!).
Example usage:
Code:size(640, 480, P2D); // This only works for P2D mode
float[] txSave1 = null, txSave2 = null;
// Arbitrary translate(x, y), rotate(rot) and scale(s) calls...
txSave1 = getTransform();
float rotation = txSave1[2]; // for example
// More transformations...
txSave2 = getTransform();
// blah...
setTransform(txSave1); // Easy!
// Back at saved transform #1 to do stuff...
pushMatrix(); // call this #3
setTransform(txSave2);
// Back at saved transform #2 to do stuff...
popMatrix();
// Back at saved transform #3 to do stuff...
In testing this, I discovered that non-uniform scaling - using scale(scaleX, scaleY), where scaleX and scaleY aren't equal - in combination with rotations, produces weird output. It seems that sheer is introduced. I tried retrieving scaleY by measuring the distance from the transformed origin to transformed (0,1), but it didn't work out, so I've left it as assuming uniform scaling.
If you want to use non-uniform scaling, you're on your own! ;o)
If you only need the current rotation, you could use a simplified version of the getTransform function.
Code:float getRotation()
{
return atan2(screenY(1,0)-screenY(0,0), screenX(1,0)-screenX(0,0));
}
-spxl