OpenGL : non rotated 4x4 matrix - opengl

Let's say that I have a 4x4 matrix like this:
a11 a12 a13 tx
a21 a22 a23 ty
a31 a32 a33 tz
a41 a42 a43 w
Is it true to say that the non rotated matrix is :
1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 w
?

In general, the statement is wrong. By removing the left 3 columns, also other effects than just the rotation are removed. For example, scaling factors as well as skewing is also stored in this region. Also, by maintaining the w value, the result could contain some other things than just translation.
If you assume that the original matrix was only composed by rotations and translations, then the assumption is true. Although in this case, removing only the upper 3x3 matrix would yield the same result since the last row will be [0, 0, 0, 1] anyway.

Related

OpenGL: How are base vectors laid out in memory

this topic has been discussed quite a few times. There are a lot of information on the memory layout of matrices in OpenGL on the internet. Sadly different sources often contradict each other.
My question boils down to:
When I have three base vectors of my matrix bx, by and bz. If I want to make a matrix out of them to plug them into a shader, how are they laid out in memory?
Lets clarify what I mean by base vector, because I suspect this can also mean different things:
When I have a 3D model, that is Z-up and I want to lay it down flat in my world space along the X-axis, then bz is [1 0 0]. I.e. a vertex [0 0 2] in model space will be transformed to [2 0 0] when that vertex is multiplied by my matrix that has bz as the base vector for the Z-axis.
Coming to OpenGL matrix memory layout:
According to the GLSL spec (GLSL Spec p.110) it says:
vec3 v, u;
mat3 m;
u = v * m;
is equivalent to
u.x = dot(v, m[0]); // m[0] is the left column of m
u.y = dot(v, m[1]); // dot(a,b) is the inner (dot) product of a and b
u.z = dot(v, m[2]);
So, in order to have best performance, I should premultiply my vertices in the vertex shader (that way the GPU can use the dot product and so on):
attribute vec4 vertex;
uniform mat4 mvp;
void main()
{
gl_Position = vertex * mvp;
}
Now OpenGL is said to be column-major (GLSL Spec p 101). I.e. the columns are laid out contiguously in memory:
[ column 0 | column 1 | column 2 | column 3 ]
[ 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 ]
or:
[
0 4 8 12,
1 5 9 13,
2 6 10 14,
3 7 11 15,
]
This would mean that I have to store my base vectors in the rows like this:
bx.x bx.y bx.z 0
by.x by.y by.z 0
bz.x bz.y bz.z 0
0 0 0 1
So for my example with the 3D model that I want to lay flat down, it has the base vectors:
bx = [0 0 -1]
by = [0 1 0]
bz = [1 0 0]
The model vertex [0 0 2] from above would be transformed like dis in the vertex shader:
// m[0] is [ 0 0 1 0]
// m[1] is [ 0 1 0 0]
// m[2] is [-1 0 0 0]
// v is [ 0 0 2 1]
u.x = dot([ 0 0 2 1], [ 0 0 1 0]);
u.y = dot([ 0 0 2 1], [ 0 1 0 0]);
u.z = dot([ 0 0 2 1], [-1 0 0 0]);
// u is [ 2 0 0]
Just as expected!
On the contrary:
This: Correct OpenGL matrix format?
SO question and consequently the OpenGL Faq states:
For programming purposes, OpenGL matrices are 16-value arrays with base vectors laid out contiguously in memory. The translation components occupy the 13th, 14th, and 15th elements of the 16-element matrix, where indices are numbered from 1 to 16 as described in section 2.11.2 of the OpenGL 2.1 Specification.
This says that my base vectors should be laid out in columns like this:
bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0 0 0 1
To me these two sources which both are official documentation from Khronos seem to contradict each other.
Can somebody explain this to me? Have I made a mistake? Is there indeed some wrong information?
The FAQ is correct, it should be:
bx.x by.x bz.x 0
bx.y by.y bz.y 0
bx.z by.z bz.z 0
0 0 0 1
and it's your reasoning that is flawed.
Assuming that your base vectors bx, by, bz are the model basis given in world coordinates, then the transformation from the model-space vertex v to the world space vertex Bv is given by linear combination of the base vectors:
B*v = bx*v.x + by*v.y + bz*v.z
It is not a dot product of b with v. Instead it's the matrix multiplication where B is of the above form.
Taking a dot product of a vertex u with bx would answer the inverse question: given a world-space u what would be its coordinates in the model space along the axis bx? Therefore multiplying by the transposed matrix transpose(B) would give you the transformation from world space to model space.

Fourth row of VP Matrix

If have a quesstion regarding matrix multiplication.
What's the information stored in the fourth row of a View Projection Matrix?
I thought rotation and scaling information is stored in the upper 3x3 Matrix, translation then in the fourth column with the last element set to 1.
Im struggling because i get following results for my VP Matrix:
When applying no rotation and no translation (note all values are rounded):
0.34 0 0 0
0 0.61 0 0
0 0 -1 -0.2
0 0 -1 0
Applying translation by -100:
0.34 0 0 0
0 0.61 0 -61.73
0 0 -1 -0.2
0 0 -1 0
Translation by -100, then rotate 30° on positive X-Axis, afterwards rotate 180° on positive Y-Axis:
-0.34 0 -3 0
0 0.53 0.3 -53.46
0 -0.5 0.86 49.8
0 -0.5 0.8 50
It doesnt look right to me. The funny part: It works. So whats the information of this line?
0 -0.5 0.8 50
Thanks for helping!
To me, your matrix looks a bit odd. Normally, the fourth row would contain the 4th component of the homogeneous coordinate frame, that is, something like [x,y,z]/w which would need to add up to 1 across the row for affine transformation. I guess your matrix works because the odd numbers in your fourth row are factored into the upper 3x3 part of the matrix. Did you try to change the order of your matrix concatenation, such as M'=M1*M0 vs. M'=M0*M1. A very good explanation of homogeneous coordinates is given by Jim Blinn in his Dirty Pixels and articles.
Also, this website contains a good walkthrough regarding homogeneous transforms

Inverse perspective transformation of a warped image

# Iwillnotexist Idonotexist presented his code for image perspective transformation (rotations around 3 axes): link
I'm looking for a function (or math) to make an inverse perspective transformation.
Let's make an assumption, that my "input image" is a result of his warpImage() function, and all angles (theta, phi and gamma), scale and fovy are also known.
I'm looking for a function (or math) to compute inverse transformation (black border doesn't matter) to get an primary image.
How can I do this?
The basic idea is you need to find the inverse transformation. In the linked question they have F = P T R1 R2 where P is the projective transformation, T is a translation, and R1, R2 are two rotations.
Denote F* as the inverse transformation. We can the inverse as F* = R2* R1* T* P*. Note the order changes. Three of these are easy R1* is just another rotation but with the angle negated. So the first inverse rotation would be
cos th sin th 0 0
R1* = -sin th cos th 0 0
0 0 1 0
0 0 1
Note the signs on the two sin terms are reversed.
The inverse of a translation is just a translation in the opposite direction.
1 0 0 0
T*= 0 1 0 0
0 0 1 h
0 0 0 1
You can check these calculating T* T which should be the identity matrix.
The trickiest bit is the projective component we have
cot(fv/2) 0 0 0
P = 0 cot(fv/2) 0 0
0 0 -(f+n)/(f-n) -2 f n / (f-n)
0 0 -1 0
The inverse of this is
tan(fv/2) 0 0 0
P*= 0 tan(fv/2) 0 0
0 0 0 -2
0 0 (n-f)/(f n) (f+n)/(f n)
Wolfram alpha inverse with v=fv
You then need to multiply these together in the reverse order to get the final matrix.
I also had issues to back-transform my image.
You need to store the points
ptsInPt2f and ptsOutPt2f
which are computed in the the 'warpMatrix' method.
To back-transform, simply use the same method
M = getPerspectiveTransform(ptsOutPt2f, ptsInPt2f);
but with reversed param order (output as first argument, input as second).
Afterwards a simple crop will get rid of all the black.

Euclidean distance when similar features are slightly shifted

Let us say I want to find a similar vector for a vector
a = [0 0 2 0 0 0 0 0 0]
I have two candidates:
b1 = [0 0 0 2 0 0 0 0 0], where the "feature" is just 1 position away
b2 = [0 0 0 0 0 0 0 2 0], where the "feature" is 5 positions away
Euclidean distance for (a, b1) is the same as for (a, b2). What I want is for b1 to get a higher "similarity" score. Is there a well-known method (name it, please) to deal with such problems? Some kind of fuzzy Euclidean distance?
One possible solution I can come up with is to calculate the Euclidean distance for (a, b1) with the whole b1 shifted by 1 position left, then by 2 positions left, by 3 positions left, etc., then do the same for shifting right. Every time I do it, I adjust the calculated Euclidean position by a weight which decreases as the shifting distance increases. The same procedure is then repeated for b2. Then the results are compared to find a better match.
Look at levenstein distance. It operates on strings, to find similarity (edit distance), but when modified to use on vectors it will get you higher similarity to b1 than to b2. It could be modified to compare actual values (not just match/mismatch of character)

Extrude shadow volumes to infinity

I want to use the depth-fail algorithm to make shadow volumes and all works great, but i can't figure out how to extrude the shadow volume quads to infinity.
The aim is to create the shadow volume for a triangle that is lit up from a point light. I have red that i first have to change the perspective matrix that it has no far clip pane and set the w coordinate to 0. But what are the x,y,z coordinates then?
An example would be very helpful, but i also want to understand how its done.
This link shows an example of a projection matrix. It has the form:
a 0 b 0
A = 0 d e 0
0 0 -(f+n)/(f-n) -2fn/(f-n)
0 0 -1 0
f is the far plane and you want f -> infinity.
limit f -> infinity of (f+n)/(f-n) = limit f -> infinity of (1+n/f)/(1-n/f)
and
limit f -> infinity of 2fn/(f-n) = limit f -> infinity of 2n/(1-n/f)
since
f -> infinity => n/f -> 0
your matrix with f -> infinity becomes
a 0 b 0
B = 0 d e 0
0 0 -1 -2n
0 0 -1 0
if you transform your (x,y,z,w=0) with B you'll get
x' = ax + bz
y' = dy + ez
z' = -z
w' = -z
and the perspective division gives
x' = -ax/z - b
y' = -dy/z - e
z' = 1
While x' and y' are the same as transforming (x,y,z,w=0) with A, z' is now a constant that is always equal to the far plane in normalized device coordinates.
This article shows an efficient implementation of shadow volumes with capping at infinity.