It seems that some basic computer graphics knowledge is missing.
Normally you have two matrices for the camera (viewMatrix and projectionMatrix), both are 4x4 matrices. The viewMatrix stores the camera position and orientation relative to world coordinates. The projection matrix stores the projection.... in your case it is an orthographic projection. The projection matrix does NOT contain any information about the camera position or orientation.
Then you have a modelMatrix for each geometry. This matrix stores the position, scale, and orientation of a 3D object, relative to world coordinates.
So when rendering, you want to transform each vertex of a geometry in the following way:
First, you need to transform the vertex, which is stored in model coordinates, to world coordinates: $vec4 vertexWorldCoordinates = modelMatrix * vec4(vertex,1)$
**Now you have each vertex of an object in world coordinates.
The next step is to convert them to camera coordinates. Camera coordinates have nothing to do with projection! They are the coordinates related to the camera position and orientation. $vertexCameraSpace = viewMatrix * vertexWorldCoordinates$
Now you have translated your vertices into camera coordinates. The next step is to translate them into screen coordinates by applying the projection matrix.
$vertexProjectedCoordinates = projectionMatrix * vertexCameraSpace$.
The final step is to bring the vertex projection coordinates to normalized device coordinates. In the case of a perspective projection (everything far away becomes smaller) you have to do the following: $vertexNormalizedDeviceCoordinates = vertexProjectedCoordinates / vertexProjectedCoordinates.w$. Here $vertexProjectedCoordinates.w$ is the 4th value of the vector.
In the case of orthographic projection, there is no need to divide by the value $vertexProjectedCoordinates.w$, since this value is always 1
.
Now let's talk about how to apply these matrices without storing each transformation in a separate vector: Matrices can be applied directly one after the other. So you can write: $vertexProjectedCoordinates = projectionMatrix * viewMatrix * modelMatrix * vec4(vertex, 1)$.
You can combine matrices, which results in a matrix. So let's combine the projection matrix and the view matrix: $viewProjectionMatrix = projectionMatrix * viewMatrix$. This leads to better performance when computing this matrix on the CPU instead of the GPU. This is because: each vertex would have to calculate the multiplication of both matrices, and each vertex gets the same value from it. So, calculate the combined matrices and load them on the GPU.
On the GPU you then only need: $vertexProjectedCoordinates = viewProjectionMatrix * modelMatrix * vec4(vertex, 1)$. You can also combine the modelMatrix and the viewProjectionMatrix in the same way...
Okay, now let's take a look at your questions:
I'm trying to figure out how to move a camera in orthographic 3D.
Since the projection matrix is separate from the view matrix, camera movement works the same for orthographic cameras as it does for perspective cameras. You have to change the viewMatrix, then the position / orientation of the camera changes.
As you can see, I'm already at the point where I can move the object in all three dimensions (X, Y and Z) without changing its shape.
Here I would think about moving not the object, but the camera.... But I don't know what the final result will do... So maybe moving the object is the right choise.
What I need now is a good and practical way to zoom and change the angle of view.
zoom: what does zoom mean? As I understand it, you want to scale the camera projection to see more/less of the scenario. To do this, you need to change the projection matrix.
Changing the angle of view: I hope you don't mean the field of view, because orthographic projections don't have a field of view. Do you mean the camera orientation (rotating the camera)? Then you just need to multiply your viewMatrix by a rotation matrix. Note that $viewMatrix * rotationMatrix$ is not the same as $rotationMatrix * viewMatrix$, because matrix multiplications are not commutative!
The camera is positioned using a lookAt function. But something tells me that you don't want to use the lookAt function as the primary tool for moving the camera?
The lookAt
function is a nice function to initialize the camera position / orientation. You can perform transformations (translations, rotations) by multiplying matrices by the viewMatrix. Note that after some time (if you rotate a lot) the floating point precision introduces small errors into the viewMatrix. Then you need to orthonormalize the top 3x3 part of your viewMatrix. You can do this by simply creating a new viewMatrix using the function lookAt
.
How do you normally zoom? By scaling the scene or by moving the camera? With my current code, moving the camera does not affect the size of an object.
Moving the camera will not work! As I said before, you need to change the projectionMatrix. If you use the library "GLM" you can use the function "ortho".
BTW: please take a look at the following tutorial. This tutorial discribes the different matrices, what they represent and how to change them: OpenGL tutorial matrices