Generating transformation matrices

Started by
4 comments, last by bzt 4 years, 8 months ago

Hi guys,

 

I've an OpenGL question, which is quite math ad linear algebra related.

Let's assume we have two coordinate systems, S (scene) and O (object). I'd like to place O inside S, so I need O' (in S coordinates). Using the following transformation matrices I can do that: rotation, scale, displacement. So far so good. I have two questions though:

 

1) assuming the place of O' is specified with 4 points (zerus, and one for each axii unit vector end points) how can I calculate the required transformation matrices?

It's a "simple" case, as let's say points are P0, P1, P2, P3 and x = P0->P1, y = P0->P2, z = P0->P3. Also |x| = |y| = |z| (all has the same length) and they enclose 90 degree with each other. This surely can be solved using standard GL transformations easily, I just need an algorithm to calculate the matrices from P0, P1, P2, P3.

 

2) the more difficult question, how can I do the same if O' can be distorted, so |x| != |y| != |z| and their angle is not necessarily 90 degree? (Imagine that you "sit" on O, so O' became stretched and it's top became larger and moved to the side, so that angle(x, y) = 80 degree for example). How to get the required transformation matrices in this universal case, when you only know P0, P1, P2, P3?

 

Hope it's clear what I'm asking. I need an algorithm to generate a transformation matrix that I can then use to transform all points in O into O'.

bzt

Advertisement
50 minutes ago, bzt said:

 how can I calculate the required transformation matrices?

The transformation matrix for an object is (in this representation matrix indices are columns 0, 1, 2, 3, vector indices vector elements x, y, z):


template<typename T>
inline static mat4_t<T> translate( const mat4_t<T>& m, const vec3_t<T>& v ) {
	mat4_t<T> result{m};	
	result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
	return result;
}
Quote

using standard GL transformations easily

GL has no linear algebra functions any more. But there are a lot of helper libs, like for example glm.

Quote

2) the more difficult question, how can I do the same if O' can be distorted, so |x| != |y| != |z| and their angle is not necessarily 90 degree? (Imagine that you "sit" on O, so O' became stretched and it's top became larger and moved to the side, so that angle(x, y) = 80 degree for example). How to get the required transformation matrices in this universal case, when you only know P0, P1, P2, P3?

That would be scaling and shear i think.


template<typename T>
inline static mat4_t<T> scale( const mat4_t<T>& m, const vec3_t<T>& v ) {
	mat4_t<T> result{m};
	result[0] = m[0] * v[0];
	result[1] = m[1] * v[1];
	result[2] = m[2] * v[2];
	result[3] = m[3];
	return result;
}

Unfortunately i have no ready made shear matrix example, sorry ...

 

You have 2 coordinate systems O and S and the matrix A that transforms between them. Each coordinate system is described by a set of vectors/points (\(s_0, s_1\) etc.).  So:

\(A \cdot o_n = s_n\)

where n is just enumerator for your points or vectors (I recommend using vectors - you need just 3 of them to describe your system and you can calculate them from your points). You want to find the matrix A. So this might help:

https://yutsumura.com/find-a-matrix-that-maps-given-vectors-to-given-vectors/

This is a general approach and should also help you with this:

1 hour ago, bzt said:

2) the more difficult question, how can I do the same if O' can be distorted, so |x| != |y| != |z| and their angle is not necessarily 90 degree? (Imagine that you "sit" on O, so O' became stretched and it's top became larger and moved to the side, so that angle(x, y) = 80 degree for example). How to get the required transformation matrices in this universal case, when you only know P0, P1, P2, P3? 

Don't have the time to think about @Green_Baron answer, but maybe his suggestions are easier and more effective for your specific needs. In any case, the technique of the link should give you the matrix you are looking for. If you need to find a decomposition of that matrix into basic transformation (rotations, scaling, translations) you might want to read about singular value decomposition:

https://en.wikipedia.org/wiki/Singular_value_decomposition

It basically says that every matrix can be decomposed into 2 rotation matrices and 1 scaling matrix: \(A = R_1 \cdot S \cdot R_2\). The SVD calculates those matrices. However, this isn't a basic technique anymore and probably not part of GLM or most other linear algebra libraries written for games. The library "Eigen" has it, but I wouldn't use it for games. Implementing it yourself (efficiently) is also not something you do in a couple of hours because SVD is not easy to understand if you don't know much about linear algebra.

 

Greetings

 

It may be that the previous responses have given you the answers you need (I'm not sure), but I'll just mention that you could try simply loading the basis vectors into a matrix directly. Using row vectors (this would be transposed for column vectors), it would look like this:

- First row of matrix is P1 - P0, followed by a zero.
- Second row of matrix is P2 - P0, followed by a zero.
- Third row of matrix is P3 - P0, followed by a zero.
- Fourth row of matrix is P0, followed by a one.

Whether this is what you want depends I suppose on what exactly it means for the object to be distorted. But, ultimately scaling and shearing results in (potentially) non-orthogonal and non-unit-length basis vectors anyway, so it seems possible that your points (P0, P1, P2, P3) may already be a correct description of what you want.

Thank you all for your responses!

@Green_Baron: It was a long time ago when I worked with GL, did not know linear algebra functions were removed, good to know! I think that your second code is the answer.

@DerTroll: thank you for the yutsumura link, that's what I was looking for! I was thinking about something like Solution 1, but yeah, Solution 2 (same as Green Baron's answer) is way better. It's so trivial, that I haven't even considered it... My bad!

@Zakwayda: thanks for this clear and simple description of the solution!

Cheers,
bzt

This topic is closed to new replies.

Advertisement