In our process of using OpenGL and OSG, we always involve vertex coordinates and transformations of coordinates (multiplied by vectors and matrices), which is often seen as the use of column vectors in OpenGL, where the line vectors are used in OSG, Because the difference between the row vector and the column vector leads to the multiplication of the matrix with the left and right multiply points, this paper makes a relatively complete explanation of this problem.
Row vector and column vector1. The line vector and column vectors are defined as follows:In linear algebra, a line vector is a 1xn matrix that consists of a row containing n elements.
In linear algebra, a column vector is a nx1 matrix that consists of a column containing n elements.
2. Left multiply and right multiplyTo put it simply, the left-multiply (also called the front-multiply) is on the left (that is, multiplication sign), right-multiply (also known as the multiplier) is on the right (that is, after multiplication sign). For example, a left by E is ae,a right by E is the EA.
3. Transformation of line vectors and column vectorsSince the vector is actually a matrix with a dimension of 1, then according to the rule of matrix multiplication, the following situation will occur: (1) The line vector left multiplication matrix in the graphics of the general matrix are 4x4, the line vector is generally set to 1x4 matrix (homogeneous coordinates). When the row vector left multiplicative matrix (1x4) * (4x4) is obtained is a 1x4 line vector (2) row vector right multiplicative matrix this case, that is (4x4) * (1x4), according to the matrix multiplication rule, this is not allowed (3) column vector left multiplicative matrix this case, that is (4x1) * (4x4) , according to the matrix multiplication rule, this is also not allowed (4) The column vector right multiplicative matrix this case, that is (4x4) * (4x1), the resulting is a 4x1 line vector
Our three-dimensional change is to transform one coordinate to another, so the above discussion (1) (4) Fits this requirement. According to the above discussion, the following conclusions are drawn:The line vector left multiplication or right multiplication is the limit of the matrix multiplication rule, the line vector can only be left multiplication and the column vector can only right multiply the matrix, this and three-dimensional graphics science has not a little relationship. So some people say that OpenGL is right, and OSG are left, but this is not the same as OpenGL and OSG itself, which is just the definition of matrix multiplication.
Row vector column vectors and memory layouts in programming languages Suppose there is a 4x4 matrix M, we now have a vertex with a coordinate of V, the transformation of M matrix can turn it into V ', now assume that V is a row vector or V is a column vector, so there are two cases: (1) v is a row vector, then v ' = v* M (2) v is a column vector, then v ' = m*v It is possible to understand the transformation in that way. The following paragraph is a passage from the earliest designer of the OpenGL specification, where he was just trying to use column vectors to make graphics and mathematical expressions consistent, while "deceiving" readers said that OpenGL was using column vectors.
I ' m the one responsible for the ' column-major ordering ' used in OpenGL, so I'll try to explain what's going on to try to P
UT this discussion to rest.
First, there is and issues that seem to be confused. One issue is what matrices be stored in memory, and the other is whether one treats vectors as rows of coordinates or as
Columns.
I ' ll dispense with the second issue first. Recent mathematical treatments of linear algebra and related fields invariably treat vectors as columns (there is some TE Chnical reasons for this). For some reason, this have not been the case in computer graphics, where vectors were written as rows, thus transposing Eve Rything from standard mathematical usage. When I wrote the OpenGL spec, I decided to does my part to right this heinous inconsistency.
Thus the spec is written with vectors treated as columns, with a matrix correspondingly applied on the left of a column. The one difficulty is compatibility with the current GL, where vectors had been written asRows. So I come up with this subterfuge:say, that matrices in OpenGL is stored in column major order. The could rewrite the spec with everything transposed (with vectors written as rows), and everything Wou LD be exactly the same as it is, including the row major ordering of matrices.
Now there is another question: since the row vector and the column vectors are not different, then why is everyone saying that the use of the column vector in OpenGL and the OSG is used in the row vector. The answer is:
when describing matrices and vector multiplication using the C + + language, there is a difference in the way in which the matrix elements are stored in memory using the understanding of the row vectors and the way the column vectors are understood, this is where the real key lies. or according to the previous practice, assuming that the coordinates are now (38,44,50,56, 0), through the matrix M, the transformation to the coordinate value is (a) point, for this transformation, you can use the row vector and column vector to understand, these two ways of understanding is exactly the way OSG and OpenGL processing.
(1) Using the method of line vectors to understand, then our matrix is
Double M[4][4] =
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9,10,11,12},
{13,14,15,16}
};
by matrix multiplication Know v = (1, 2, 3, 0), then v ' = VM = (38, 44, 50, 56), assuming that we are coding in C + + language, because there is no matrix of this type in C + + language, it uses a two-dimensional array to store the matrix elements and is stored in the same way that the row main order is used, so the matrix M is shown in memory as in the following figure:
(2) using the column vectors to understand, then our matrix is not the above matrix, but:
Double M[4][4] =
{
{1, 5, 9, +}, {
2, 6, ten, +},
{3, 7, one,},
{4, 8, N, +}
};
by matrix multiplication, V ' = Mv
The matrix M in the C + + memory model is as follows:
You can see the difference between using a row vector and a column vector, only the difference in memory layout causes us to understand the difference between the row vector and the column vector.
From the above analysis can draw the following conclusions:
(1) using the line vector or the column vector to understand OpenGL and OSG can, in fact, there is no difference between the row vector and the column vector (2) when using the column vector to understand the transformation, all the transformation is the back multiply (right multiplication), when using the line vector to understand the transformation, All transformations are pre-multiply (left multiply) (3) OpenGL in order to show that it is using the column vector, all the matrix design is the way of the column main order, so when we are in the transformation, we need to pay attention to the matrix in C/S language memory layout of the way to store, that is to say that there is a translation matrix, The position where the translation amount Tx,ty,tz should be at the 4,8,12 position of the array
This kind of processing is very awkward in C + +, because the position of these translation variables is not contiguous, which is why many three-dimensional libraries use the line main sequence (line vector) way, because if the way of using the row vector, then the position of the three line vectors is exactly adjacent, and C/s Languages are stored in the same way. However, OpenGL also provides a function to receive a matrix of the way the main sequence of rows is used:
GLLOADTRANSPOSEMATRIXF
Glloadtransposematrixd
(4) OSG in order to make people feel that it is using the line vector, all the matrix design is based on the method of line main order. This design coincides with the storage of two-dimensional arrays in the C + + language, which is more natural to use. All transformations in OSG are left-multiplicative matrices, and it is easy to see this by looking at the implementation of the Matrix in OSG:
Double Xarray[4][4] =
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, ten, One, one},
{a
, +, +, +}}; Osg::matrixd Mat;
Mat.set ((double*) xarray);
x12 = 7
Double x12 = Mat (1, 2);