Register
handmade.network»Forums»basis vectors (rotation)
Roman
17 posts

Roman Shvayko.I love low-level programming and games.

basis vectors (rotation)
1 month, 2 weeks ago Edited by Roman on Dec. 8, 2020, 1:35 p.m. Reason: Initial post
Hello. I want to my character object facing where I am looking in 3D space.(character is just a box). So I am using basis vectors(right, up, forward) to construct matrix and then multiply that with the model matrix. But everything works except when the character rotates it also stretches(like a water). What I did wrong?
Code for rotation object
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
   model = scale(model, hero->size);
    
    v3 up = v3(0.0f,1.0f,0.0f);
    v3 right = normalize(cross(gameState->cameraFront,up));
    
    mat4 M = 
    {
        {
            {right.x,up.x,gameState->cameraFront.x,0.0f},
            {right.y,up.y,gameState->cameraFront.y,0.0f},
            {right.z,up.z,gameState->cameraFront.z,0.0f},
            {0.0f,0.0f,0.0f,1.0f}
        }
    };
    model = M * model;
    
    
    model = translate(model, hero->p);
    
    passUniformMatrix(opengl.shaderProgram,model,false,"model");
    glDrawArrays(GL_TRIANGLES, 0, 36);

Code for camera transforming
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
void 
cameraTransform(Camera *camera, Input *input, Game_state *gameState)
{
    beginUseProgram(opengl.shaderProgram);
    if(camera->firstMouseMove)
    {
        camera->lastMouseX = input->mouseX;
        camera->lastMouseY = input->mouseY;
        
        camera->firstMouseMove = false;
    }
    
    s32 dtMouseX = input->mouseX - camera->lastMouseX;
    s32 dtMouseY = camera->lastMouseY - input->mouseY;
    
    dtMouseX *= camera->mouseSensitivity;
    dtMouseY *= camera->mouseSensitivity;
    
    camera->yaw += dtMouseX;
    camera->pitch += dtMouseY;
    
    if(camera->pitch > 89.0f)
    {
        camera->pitch  = 89.0f;
    }
    if(camera->pitch < -89.0f)
    {
        camera->pitch = -89.0f;
    }
    
    gameState->cameraFront.x = cos(ToRadians(camera->yaw)) * cos(ToRadians(camera->pitch));
    gameState->cameraFront.y = sin(ToRadians(camera->pitch));
    gameState->cameraFront.z = sin(ToRadians(camera->yaw)) * cos(ToRadians(camera->pitch));
    
    gameState->cameraFront = normalize(gameState->cameraFront);
    
    mat4 viewMatrix = indentity();
    viewMatrix = lookAt(gameState->cameraP,
                        gameState->cameraP + gameState->cameraFront,
                        v3(0.0f,1.0f,0.0f));
    
    
    passUniformMatrix(opengl.shaderProgram,viewMatrix,false,"view");
    
    camera->lastMouseX = WINDOW_WIDTH / 2;
    camera->lastMouseY = WINDOW_HEIGHT/ 2;
    
    endUseProgram(opengl.shaderProgram);
}

Thanks in advance.
Simon Anciaux
943 posts
basis vectors (rotation)
1 month, 2 weeks ago
Are cameraFront and up guaranteed to be perpendicular (in other words, is cameraFront parallel to the ground since up is strait up) ?

If not, you need to recompute up after computing right by doing another cross product between cameraFront and right (the 3 axis of the matrix need to be perpendicular otherwise the object will be deformed).

But I'm not "fluent" with matrix transformations so maybe it's not that.
Oliver Marsh
180 posts / 2 projects

A budding game developer and programmer

basis vectors (rotation)
1 month, 2 weeks ago
Just wondering what the matrix multiplication function looks like?
Roman
17 posts

Roman Shvayko.I love low-level programming and games.

basis vectors (rotation)
1 month, 2 weeks ago
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
mat4 
operator*(mat4 a, mat4 b)
{
    mat4 result = {};
    
    for(s32 r = 0; r < 4; r++)
    {
        for(s32 c = 0; c < 4; c++)
        {
            for(s32 i = 0; i < 4; i++)
            {
                result.e[r][c] += a.e[r][i] * b.e[i][c];
            }
        }
    }
    return result;
}

Oliver Marsh
180 posts / 2 projects

A budding game developer and programmer

basis vectors (rotation)
1 month, 2 weeks ago Edited by Oliver Marsh on Dec. 9, 2020, 11:30 p.m.
Hi Roman,

I'm a bit rusty on matrix's, but one thing I did notice is the layout of the matrix - the basis vectors are laid out in column-major order that is

1
2
3
4
5
6
Matrix4 result = {{
            xAxis.x, yAxis.x, zAxis.x, 0,
            xAxis.y, yAxis.y, zAxis.y, 0,
            xAxis.z, yAxis.z, zAxis.z, 0,
            0, 0, 0, 1
        }};


instead of

1
2
3
4
5
6
Matrix4 result = {{
            xAxis.x, xAxis.y, xAxis.z, 0,
            yAxis.x, yAxis.y, yAxis.z, 0,
            zAxis.x, zAxis.y, zAxis.z, 0,
            0, 0, 0, 1
        }};


Not that that's a problem as your matrix multiplication function takes this into account, but OpenGL expects matrixes to be in the second format I believe. Not sure if this is the problem, but you could try transposing the final matrix before you send it to OpenGL.
Mārtiņš Možeiko
2162 posts / 1 project
basis vectors (rotation)
1 month, 2 weeks ago Edited by Mārtiņš Možeiko on Dec. 11, 2020, 2:17 a.m.
Unless you are talking about ancient fixed-functionality-pipeline in OpenGL 1.x, then OpenGL (same as D3D) does not care about which layout your matrix uses. You can use either layout, all you need is just correctly write out math in your shader (m * v) vs (v * m) or use GLSL layout qualifiers - like layout(row_major) vs layout(column_major).
Oliver Marsh
180 posts / 2 projects

A budding game developer and programmer

basis vectors (rotation)
1 month, 2 weeks ago
Oh yea, was thinking if you use the matrices as the same way as math P * V * M instead of the other way.
Mārtiņš Možeiko
2162 posts / 1 project
basis vectors (rotation)
1 month, 2 weeks ago Edited by Mārtiņš Možeiko on Dec. 11, 2020, 9:20 a.m.
With matrices it works the same way (vector is just the 1x4 matrix). You do either P*V*M or you do M*V*P - result will be the same for both storage formats. It works because of following basic property of matrix multiplication: https://en.wikipedia.org/wiki/Matrix_multiplication#Transpose

Oliver Marsh
180 posts / 2 projects

A budding game developer and programmer

basis vectors (rotation)
1 month, 2 weeks ago Edited by Oliver Marsh on Dec. 11, 2020, 10:34 p.m.
Does that mean you don't have to worry about the ordering in the shader or
1
P*V*M*Vertex
will work with the row-major layout (M, then V, then P) & column-major will work with
1
M*V*P*Vertex
(P first, then V, then M)? That is a neat way of doing things.
Mārtiņš Možeiko
2162 posts / 1 project
basis vectors (rotation)
1 month, 2 weeks ago Edited by Mārtiņš Možeiko on Dec. 12, 2020, 5:30 a.m.
Almost correct. Vertex also needs to be on correct side, just like other matrices.

You do "P * V * M * vertex" for column major.
Or "vertex * M * V * P" for row major.

But order of multiplication you do first does not really matter. As "((vertex * M) * V) * P" is same as "vertex * ((M * V) * P)" or even as "(vertex * M) * (V * P)".
https://en.wikipedia.org/wiki/Matrix_multiplication#Associativity
Oliver Marsh
180 posts / 2 projects

A budding game developer and programmer

basis vectors (rotation)
1 month, 2 weeks ago
Thanks Martin 😊