Why are matricies used in computer graphics? - performance

I understand how to apply matrices in computer graphics, but I don't quite understand why this is done. For example in translation: to translate vector (x, y, z) by vector (diffX, diffY, diffZ) you could simply just add the vectors together instead of creating a translation matrix:
[1 0 0 diffX]
[0 1 0 diffY]
[0 0 1 diffZ]
[0 0 0 1 ]
and then multiplying the vector by the matrix to get (x+diffX, y+diffY, z+diffZ). Surely applying matrices like this would be wasteful of performance and memory?

Related

Can I always assume that an mvp matrix with corner value !=1 is performing scaling?

Assume I have a modelview projection matrix, mvp and I know that mvp[3][3] !=1 and mvp[3][3] > 0
Can I assume that the model matrix performed the scaling or since the projection matrix itself performs scaling this number is not useful without the original matrices?
No, this value alone does not tell you much. Consider a diagonal matrix like the following:
d 0 0 0
0 d 0 0
0 0 d 0
0 0 0 d
d is an arbitrary number.
This matrix is essentially the homogeneous equivalent of the identity matrix and does not perform any transformation at all. The uniform scaling part in the upper left 3x3 block is cancelled out by the perspective divide. You can always multiply the matrix by the inverse of the m33 entry to somewhat normalize it (this will preserve the transformation). For the above matrix, you would then get:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
And in this form, you can easily see that it is the identity. Moreover, you can examine the upper left 3x3 block to find out if there is a scaling (depending on your definition of scaling, calculating the determinant of the 3x3 block and checking for 1 is one option as Robert mentioned in the comments).

Transformed Primitives - Compute the inverse of a matrix without using any function

Let's say if I need to transform a cylinder, first I need to use a scaling matrix (sx, sy, sz) and multiply it with a translation matrix (tx, ty, tz) to form a new matrix that combined by these two matrix. => M = T*S.
Then I want to compute the inverse of a matrix M^-1 without using any function, I know that the inverse of a scaling matrix has a scale factors (1/sx, 1/sy, 1/sz) and a inverse of a translation matrix has (-tx, -ty, -tz), but how can I get M^-1 without any function in C++ ?
Suppose you want to scale a vector by some factors Sx, Sy, and Sz. The transformation matrix for this looks like:
Sx 0 0 0
0 Sy 0 0
0 0 Sz 0
0 0 0 1
Then, you want to translate the vector by some factors Tx, Ty, and Tz. The transformation matrix for this now looks like:
Sx 0 0 Tx
0 Sy 0 Ty
0 0 Sz Tz
0 0 0 1
The inverse of this matrix specifically is
1/Sx 0 0 -Tx/Sx
0 1/Sy 0 -Ty/Sy
0 0 1/Sz -Tz/Sz
0 0 0 1
.. as long as Sx, Sy, and Sz are all != 0.
Depending on your application, you may be better off writing a general purpose matrix inversion method. Note that there are cases in which a transformation (or any) matrix is not invertible... like if your scaling factor in one or more of the dimensions is 0. More generally, a matrix is invertible if and only if its determinant is nonzero.

Converting points into another coordinate system

There are 3 points in 3D space. There are 2 orthogonal coordinate systems with the same origin. I know coordinates of those 3 points in both coordinate systems. Given a new point with its coordinates in the first coordinate system, how can I find its coordinates in the second coordinate system?
I think it's possible to get a rotation matrix using given points which does this, but I did not succeed doing this.
You can do it using matrix inverses. Three matrix-vector multiplications (e.g. transforming three 3D vectors by a 3x3 matrix) is equivalent to multiplying two 3x3 matrices together.
So, you can put your first set of points in one matrix, call it A:
0 0 1 < vector 1
0 1 0 < vector 2
2 0 0 < vector 3
Then put your second set of points in a second matrix, call it C. As an example, imagine a transform that scales by a factor of 2 around the origin and flips the Y and Z axes:
0 2 0 < vector 1
0 0 2 < vector 2
4 0 0 < vector 3
So, if A x B = C, we need to find the matrix B, which we can find by finding the A-1:
Inverse of A:
0 0 0.5
0 1 0
1 0 0
The multiply A-1 x C (in that order):
2 0 0
0 0 2
0 2 0
This is a transform matrix B that you can apply to new points. Dot-product multiply the vector by the first column to get the transformed X, second column to get the transformed Y, etc.

how do I apply a wieght to a bone?

If I were to assign every vertex to a bone/matrix, how would I edit the transformation matrix so some of the vertexes are transformed less?
For example, if I have the matrix
cos sin 0 0
-sin cos 0 2
0 0 1 0
0 0 0 1
What do i do to it to make the vertex rotate less?
Quoting paddy
"Those sin and cos terms are all supposed to be supplied with an angle. eg sin(theta). So, since you are most likely in control of that, just reduce the angle."
So change the angle by multiplying by a value -1 to 1 and that will change the direction/amount it changes.

Minimum Tile Ordering

Minimizing Tile Re-ordering Problem:
Suppose I had the following symmetric 9x9 matrix, N^2 interactions between N particles:
(1,2) (2,9) (4,5) (4,6) (5,8) (7,8),
These are symmetric interactions, so it implicitly implies that there exists:
(2,1) (9,2) (5,4) (6,4) (8,5) (8,7),
In my problem, suppose they are arranged in matrix form, where only the upper triangle is shown:
t 0 1 2 (tiles)
# 1 2 3 4 5 6 7 8 9
1 [ 0 1 0 0 0 0 0 0 0 ]
0 2 [ x 0 0 0 0 0 0 0 1 ]
3 [ x x 0 0 0 0 0 0 0 ]
4 [ x x x 0 1 1 0 0 0 ]
1 5 [ x x x x 0 0 0 1 0 ]
6 [ x x x x x 0 0 0 0 ]
7 [ x x x x x x 0 1 0 ]
2 8 [ x x x x x x x 0 0 ]
9 [ x x x x x x x x 0 ] (x's denote symmetric pair)
I have some operation that's computed in 3x3 tiles, and any 3x3 that contains at least a single 1 must be computed entirely. The above example requires at least 5 tiles: (0,0), (0,2), (1,1), (1,2), (2,2)
However, if I swap the 3rd and 9th columns (and along with the rows since its a symmetric matrix) by permutating my input:
t 0 1 2
# 1 2 9 4 5 6 7 8 3
1 [ 0 1 0 0 0 0 0 0 0 ]
0 2 [ x 0 1 0 0 0 0 0 0 ]
9 [ x x 0 0 0 0 0 0 0 ]
4 [ x x x 0 1 1 0 0 0 ]
1 5 [ x x x x 0 0 0 1 0 ]
6 [ x x x x x 0 0 0 0 ]
7 [ x x x x x x 0 1 0 ]
2 8 [ x x x x x x x 0 0 ]
3 [ x x x x x x x x 0 ] (x's denote symmetric pair)
Now I only need to compute 4 tiles: (0,0), (1,1), (1,2), (2,2).
The General Problem:
Given an NxN sparse matrix, finding an re-ordering to minimize the number of TxT tiles that must be computed. Suppose that N is a multiple of T. An optimal, but unfeasible, solution can be found by trying out the N! permutations of the input ordering.
For heuristics, I've tried bandwidth minimization routines (such as Reverse CutHill McKee), Tim Davis' AMD routines, so far to no avail. I don't think diagonalization is the right approach here.
Here's a sample starting matrix:
http://proteneer.com/misc/out2.dat
Hilbert Curve:
RCM:
Morton Curve:
There are several well-known options you can try (some of them you have, but still):
(Reverse) Cuthill-McKee reduced the matrix bandwidth, keeping the entries close to the diagonal.
Approximage Minimum Degree - a light-weight fill-reducing reordering.
fill-reducing reordering for sparse LU/LL' decomposition (METIS, SCOTCH) - quite computationally heavy.
space filling curve reordering (something in these lines)
quad-trees for 2D or oct-trees for 3D problems - you assign the particles to quads/octants and later number them according to the quad/octant id, similar to space filling curves in a sense.
Self Avoiding Walk is used on structured grids to traverse the grid points in such order that all points are only visited once
a lot of research in blocking of the sparse matrix entries has been done in the context of Sparse Matrix-Vector multiplication. Many of the researchers have tried to find good reordering for that purpose (I do not have the perfect overview on that subject, but have a look at e.g. this paper)
All of those tend to find structure in your matrix and in some sense group the non-zero entries. Since you say you deal with particles, it means that your connectivity graph is in some sense 'local' because of spatial locality of the particle interactions. In this case these methods should be of good use.
Of course, they do not provide the exact solution to the problem :) But they are commonly used in exactly such cases because they yield very good reorderings in practice. I wonder what do you mean by saying the methods you tried failed? Do you expect to find the optimum solution? Surely, they improve the situation compared to a random matrix ordering.
Edit Let me briefly go through a few pictures. I have created a 3D structured cartesian mesh composed of 20-node brick elements. I matched the size of the mesh so that it is similar to yours (~1000 nodes). Also, number of non-zero entries per row are not too far off (51-81 in my case, 59-81 in your case, both however have very different distributions) The pictures below show RCM and METIS reorderings for non-periodic mesh (left), and for mesh with complete x-y-z periodicity (right):
Next picture shows the same matrix reordered using METIS and fill-reducing reordering
The difference is striking - bad impact of periodicity is clear. Now your matrix reordered with RCM and METIS
WOW. You have a problem :) First of all, I think there is something wrong with your rcm, because mine looks different ;) Also, I am certain that you can not conclude anything general and meaningful about any reordering based on this particular matrix. This is because your system size is very small (less than roughly 10x10x10 points), and you seem to have relatively long-range interactions between your particles. Hence, introducing periodicity into such small system has a much stronger bad effect on reordering than is seen in my structured case.
I would start the search for a good reordering by turning off periodicity. Once you have a reordering that satisfies you, introduce periodic interactions. In the system you showed there is almost nothing but periodicity: because it is very smal and because your interactions are fairly long-range, at least compared to my mesh. In much larger systems periodicity will have a smaller effect on the center of the model.
Smaller, but still negative. Maybe you could change your approach to periodicity? Instead of including periodic connectivities explicitly in the matrix, construct and reorder a matrix without those and introduce explicit equations binding the periodic particles together, e.g.:
V_particle1 = V_particle100
or in other words
V_particle1 - V_particle100 = 0
and add those equations at the end of your matrix. This method is called the Lagrange multipliers. Here is how it looks for my system
You keep the reordering of the non-periodic system and the periodic connectivities are localized in a block at the end of the matrix. Of course, you can use it for any other reorderings.
The next idea is you start with a reordered non-periodic system and explicitly eliminate matrix rows for the periodic nodes by adding them into the rows they are mapped onto. You should of course also eliminate the columns.
Whether you can use these depends on what you do with your matrix. Lagrange multiplier for example introduce 0 on the diagonal - not all solvers like that..
Anyway, this is very interesting research. I think that because of the specifics of your problem (as I understand it - irregularly placed particles in 3D, with fairly long-range interactions) make it very difficult to group the matrix entries. But I am very curious what you end up doing. Please let me know!
You can look for a data structure like kd-tree, R-tree, quadtree or a space filling curve. Especially a space filling curve can help because it reduce the dimension and also reorder the tiles and thus can add some new information to the grid. With a 9x9 grid it's probably good to look into peano curves. The z order morton curve is better for power of 2 grids.

Resources