Our
Our

Reputation: 1035

A confusion about space transformation in OpenGL

In the book of 3D graphics for game programming by JungHyun Han, at page 38-39, it is given that

the basis transformation matrix from e_1, e_2, e_3 to u,v,n is enter image description here

However, this contradicts with what I know from linear algebra. I mean shouldn't the basis-transformation matrix be the transpose of that matrix ?

Note that the author does his derivation, but I couldn't find where is the missing point between what I know and what the author does.

The code: Vertex Shader:

#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;

uniform vec3 cameraPosition;
uniform vec3 AT;
uniform vec3 UP;
uniform mat4 worldTrans;

vec3 ep_1 = ( cameraPosition - AT )/ length(cameraPosition - AT);
vec3 ep_2 = ( cross(UP, ep_1) )/length( cross(UP, ep_1 )); 
vec3 ep_3 = cross(ep_1, ep_2);

vec4 t_ep_1 = vec4(ep_1, -1.0f);
vec4 t_ep_2 = vec4(ep_2, cameraPosition.y);
vec4 t_ep_3 = vec4(ep_3, cameraPosition.z);
mat4 viewTransform = mat4(t_ep_1, t_ep_2, t_ep_3, vec4(0.0f, 0.0f, 0.0f, 1.0f));

smooth out vec4 fragColor;
void main()
{
    gl_Position = transpose(viewTransform) * position;
    fragColor = color;
}
)glsl";

Inputs:

GLuint transMat = glGetUniformLocation(m_Program.m_shaderProgram, "worldTrans");
    GLfloat dArray[16] = {0.0};
    dArray[0] = 1;
    dArray[3] = 0.5;
    dArray[5] = 1;
    dArray[7] = 0.5;
    dArray[10] = 1;
    dArray[11] = 0;
    dArray[15] = 1;
    glUniformMatrix4fv(transMat, 1, GL_TRUE, &dArray[0]);
    GLuint cameraPosId = glGetUniformLocation(m_Program.m_shaderProgram, "cameraPosition");
    GLuint ATId = glGetUniformLocation(m_Program.m_shaderProgram, "AT");
    GLuint UPId = glGetUniformLocation(m_Program.m_shaderProgram, "UP");
    const float cameraPosition[4] = {2.0f, 0.0f, 0.0f};
    const float AT[4] = {1.0f, 0.0f, 0.0f};
    const float UP[4] = {0.0f, 0.0f, 1.0f};
    glUniform3fv(cameraPosId, 1, cameraPosition);
    glUniform3fv(ATId, 1, AT);
    glUniform3fv(UPId, 1, UP);

Upvotes: 1

Views: 143

Answers (2)

Our
Our

Reputation: 1035

Apparently, the change of basis in a vector space does changes the vectors in that vector space, and this is not what we want in here.

Therefore, the mathematics that I was applying does not valid in here.

To understand more about why we use the matrix that I have given in the question, please see this question.

Upvotes: 0

Ripi2
Ripi2

Reputation: 7198

While it's true that a rotation, scaling or deformation can be expressed by a 4x4 matrix in the form enter image description here

what your are reading about is the so called "View Transformation"

To achieve this matrix we need two transformations: First, translate to the camera position, and then rotate the camera.

The data to do these transformations are:

  • Camera position C (Cx,Cy,Cz)
  • Target position T (Tx,Ty,Tz)
  • Camera-up normalized UP (Ux, Uy, Uz)

The translation can be expressed by

enter image description here

For the rotation we define:
F = T – C and after normalizating it we get f = F / ||T-C||, also expressed by f= normalize(F)
s = normalize(cross (f, UP))
u = normalize(cross(s, f))

s, u, -f are the new axis expressed in the old coordinates system.

Thus we can build the rotation matrix for this transformation as enter image description here

Combining the two transformations in an only matrix we get: enter image description here enter image description here

Notice that the axis system is the one used by OpenGL, where -f= cross(s,u).

Now, comparing with your GLSL code I see:

  1. Your f(ep_1) vector goes in the oposite direction.
  2. The s(ep_2) vector is calculated as cross(UP, f) instead of cross(f, UP). This is right, because of 1).
  3. Same for u(ep_3).
  4. The building of V cell (0,0) is wrong. It tries to set the proper direction by using that -1.0f.
  5. For the other cells (t_ep_J components), the camera position is used. But you forgot to use the dot product of it with s,u,f.
  6. The GLSL initializer mat4(c1,c2,c3,c4) requires column-vectors as parameters. You passed row-colums. But, after, in main the use of transpose corrects it.

On a side note, you are not going to calculate the matrix for each vertex, time and time and time... right? Better calculate it on the CPU side and pass if (in column order) as an uniform.

Upvotes: 1

Related Questions