1
General discussions / I was looking at SFML Transform.cpp and Transformable.cpp
« on: September 21, 2015, 07:35:06 am »
Transformable code keeps track of what transforms have been applied and updates the transform if need be.
Transform code provides methods for combined translation and rotation, and combined translation and scale.
For example, suppose we have a method called translate and rotate that does what you'd expect, and which returns a fresh new Transform with the given data.
Rotating around a point with the method rotate(angle, centerX, centerY) will return a transform that is exactly the same as matrix multiplication of translate(centerX, centerY) * rotate(angle, 0, 0) * translate(-centerX, -centerY). In fact thats how the matrix expression for the combined translation rotation was generated. Formula for basic rotation around the origin, scaling around the origin, shearing around the origin and translating can be found on wikipedia, and they can be matrix multiplied to generate other matrices.
"Rotating around a given center" or "Scaling around a given center" are so common that it makes sense for us to combine the formula and provide it as rotate(angle, centerX, centerY), which is exactly what SFML does.
So I was wondering why not just combine all of the transforms that way and throw in shear for good measure, using the standard opengl style of matrix order? For example, a shear around a point, followed by a rotation around a different point, followed by a scale around a third point, followed by a translation:
I don't know if this will be useful to anyone here, or whether using it (well namely the method of generating it) could speed up the implementation of SFML Transformable as I haven't really given it much thought.
Here is how I generated the equations:
The left most matrix is obviously a scale(k,h) around point(s,t), the right most is a shear(f,g) around point (q,r), and the middle is rotation(theta) around point(x,y).
The resulting matrix is specifically what you would get for first shearing, then rotating, then scaling around specific points.
The function I provided tacks on translation after doing those three things in that specific order (translation as a last operation is fairly simple and not worth typing out so I didn't, in general you would need to multiply the transformation matrix as well)
Note that you get a different matrix if you want to do those things in a different order. All in all there are 4 operations, so there are 4! = 24 unique transformation matrices, which would be generated similar to the above one, gotten by multiplying 4 matrices together, one matrix for each fundamental kind of operation: rotation about a point, translation, shear about a point and scale about a point, in all possible different orders.
if you had functions for each possible order, 24 functions in all, you could compute a transform for an arbitrary shear around a point, rotation around a point, scale around a point and translation in whatever order all while only making a single function call. And 24 isn't so high that you'd thrash the I-Cache.
Just food for thought.
Transform code provides methods for combined translation and rotation, and combined translation and scale.
For example, suppose we have a method called translate and rotate that does what you'd expect, and which returns a fresh new Transform with the given data.
Rotating around a point with the method rotate(angle, centerX, centerY) will return a transform that is exactly the same as matrix multiplication of translate(centerX, centerY) * rotate(angle, 0, 0) * translate(-centerX, -centerY). In fact thats how the matrix expression for the combined translation rotation was generated. Formula for basic rotation around the origin, scaling around the origin, shearing around the origin and translating can be found on wikipedia, and they can be matrix multiplied to generate other matrices.
"Rotating around a given center" or "Scaling around a given center" are so common that it makes sense for us to combine the formula and provide it as rotate(angle, centerX, centerY), which is exactly what SFML does.
So I was wondering why not just combine all of the transforms that way and throw in shear for good measure, using the standard opengl style of matrix order? For example, a shear around a point, followed by a rotation around a different point, followed by a scale around a third point, followed by a translation:
Code: [Select]
typedef
struct
{
float v[16];
} Transform;
Transform
transform
( float shcx
, float shcy
, float shvx
, float shvy
, float rcx
, float rcy
, float angle
, float sccx
, float sccy
, float scvx
, float scvy
, float tx
, float ty
)
{
const float cosine = cos (angle);
const float sine = sin (angle);
const float a = -shvy * scvx * sine + scvx * cosine;
const float b = shvx * scvx * cosine - scvx * sine;
const float c = shvy * scvy * cosine + scvy * sine;
const float d = shvx * scvy * sine + scvy * cosine;
const float x = tx + scvx * (rcx * (1 - cosine) + rcy * sine) + shvy * scvx * shcy * sine - shvx * scvx * shcx * cosine + sccx * (1 - scvx);
const float y = ty + scvy * (rcy * (1 - cosine) + rcy * sine) - shvx * scvy * shcx * sine - shvy * scvy * shcy * cosine + sccy * (1 - scvy);
const Transform r =
{ a, c, 0, 0
, b, d, 0 0
, 0, 0, 1, 0
, x, y, 0, 1
};
return r;
}
(notice in the above struct initialization you have to conceptually flip the math matrix across the perceived diagonal. If you format it in a list and look at the indexes you will see that it maps correctly to opengl's way of doing things)I don't know if this will be useful to anyone here, or whether using it (well namely the method of generating it) could speed up the implementation of SFML Transformable as I haven't really given it much thought.
Here is how I generated the equations:
The left most matrix is obviously a scale(k,h) around point(s,t), the right most is a shear(f,g) around point (q,r), and the middle is rotation(theta) around point(x,y).
The resulting matrix is specifically what you would get for first shearing, then rotating, then scaling around specific points.
The function I provided tacks on translation after doing those three things in that specific order (translation as a last operation is fairly simple and not worth typing out so I didn't, in general you would need to multiply the transformation matrix as well)
Note that you get a different matrix if you want to do those things in a different order. All in all there are 4 operations, so there are 4! = 24 unique transformation matrices, which would be generated similar to the above one, gotten by multiplying 4 matrices together, one matrix for each fundamental kind of operation: rotation about a point, translation, shear about a point and scale about a point, in all possible different orders.
if you had functions for each possible order, 24 functions in all, you could compute a transform for an arbitrary shear around a point, rotation around a point, scale around a point and translation in whatever order all while only making a single function call. And 24 isn't so high that you'd thrash the I-Cache.
Just food for thought.