# OpenGL Programming/Modern OpenGL Tutorial Navigation

# Keyboard input[edit | edit source]

- glutKeyboardFunc
- glutSpecialFunc
- glutSpecialUpFunc
- glutGetModifiers() == GLUT_ACTIVE_SHIFT or GLUT_ACTIVE_CTRL or GLUT_ACTIVE_ALT

Beware: GLUT's special() callback is called repetitively when the press is hold down.

# Coordinates system[edit | edit source]

There are several ways to position the (X,Y,Z) axis triplet.

- Z-is-up : used in Blender, this means (X,Y) is the ground, and Z is the altitude
- Y-is-up : used in OpenGL, this means (X,Y) is like a wall, so Y is the altitude, and Z is going closer/farther to that wall
- right-handed / left-hand : OpenGL and Blender use a right-handed coordinates system, which means you can represent it using your right hand, with X on the thumb, Y on the index, and Z on the middle finger. A left-handed coordinates system, as used by DirectX, can be represented similarly using the left hand.

Using the Blender Z-is-up coordinates system in OpenGL can be tempting, but introduces issues:

- .obj files are usually in Y-is-up, requiring changes when loading them (or when exporting them from Blender)
- the camera is in Y-is-up, so if you use a Z-is-up coordinates system, by default the camera is at (0,0,0)
*and*it faces the*bottom*. This is quite confusing when rotating the camera, because, for instance, if your camera is looking on the horizon towards the Y axis, and you rotate on the Z axis to look left or right, you'll actually rotate the view on the Y axis (barrel roll). When transforming the camera, you'd have to imagine that you shoot the video from your feet. - other engines such as Irrlicht and Ogre also use Y-is-up

Consequently we'll stick with Y-is-up in this book.

# Positioning the camera[edit | edit source]

There's no built-in concept of camera in OpenGL. We have to somewhat cheat to implement it.

Our technique is the following: instead of thinking how to move our camera in a fixed world, we're thinking how to move the entire world around our camera.

For instance, moving the camera for 3 units on the X axis is the same as moving the whole world for -3 units on the X axis. Same for all other axis and for rotations.

Keep this in mind when working with the camera. The end-result will feel completely intuitive, but whenever you work with the camera, if you forget that we've been cheating in the first place, you'll get the wrong transformations.

# Camera control[edit | edit source]

We'll start with an intuitive implementation:

- left/right rotates on the camera Y axis
- up/down moves forwards/backwards
- page_up/page_down rotates on the camera X axis

```
/* code here */
```

To go forwards/backwards, we use `glm::translate`

. There are two forms:

`glm::translate(transformation_matrix, glm::vec3(dx, dy, dz))`

: applying`transformation_matrix`

, then move in (dx,dy,dz) expressed in the new coordinates system`glm::translate(glm::mat4(1), glm::vec3(dx, dy, dz)) * transformation_matrix`

: applying`transformation_matrix`

, then move in (dx,dy,dz) expressed in the coordinates system as it was before the translation- in the case of a camera translation, don't forget that we cheat and move the whole world, not the camera; consequently the above meaning is reversed for the world2camera matrix.

For instance, if your existing `transformation_matrix`

rotates your camera 90° to the right, and then translate along Z:

- with the first form you will translate the camera's new left (along world's Z axis),
- while with the second form your will translate the camera forwards (along world's X axis).

This implementation has usability issues: when rotating the camera left/right while it's bent, we're not used to rotate our entire body on this bended axis. Instead, we're used to rotate just our head on the world straight Y axis. So we need to translate the world Y axis to the camera's local coordinates:

```
glm::vec3 y_axis_world = glm::mat3(transforms[MODE_CAMERA]) * glm::vec3(0.0, 1.0, 0.0);
transforms[MODE_CAMERA] = glm::rotate(glm::mat4(1.0), -delta_rotY, y_axis_world) * transforms[MODE_CAMERA];
```

Last, let's implementing strafing:

```
/* code here */
```