1
\$\begingroup\$

I am trying to create a generic camera class for a game engine, which works for different types of cameras (Orbital, GDoF, FPS), but I have no idea how to go about it.

I have read about quaternions and matrices, but I do not understand how to implement it. Particularly, it seems you need "Up", "Forward" and "Right" vectors, a Quaternion for rotations, and View and Projection matrices.

For example, an FPS camera only rotates around the World Y and the Right Axis of the camera; the 6DoF rotates always around its own axis, and the orbital is just translating for a set distance and making it look always at a fixed target point.

The concepts are there; implementing this is not trivial for me.

SharpDX seems to have has already Matrices and Quaternions implemented, but I don't know how to use them to create a camera.

Can anyone point me on what am I missing, what I got wrong?

I would really enjoy if you could give a tutorial, some piece of code, or just plain explanation of the concepts.

\$\endgroup\$
4
  • \$\begingroup\$ Most of the things you mentioned in "UP, Forward and Right vectors I read they are needed, also a quaternion for rotations, and View and Projection matrices" serve the same purpose. If you have an Up, Forward and Right vector, then that forms the basis (the three spatial axes) for your view matrix. The view matrix also includes a position in the 4th column. You really do not need to store anything more than a view matrix and projection matrix in a camera, all that other stuff can be figured out from the view matrix. \$\endgroup\$ Jun 6, 2014 at 0:12
  • \$\begingroup\$ @AndonM.Coleman, I do realize some of them are reduntant, I am more worried about implementation side of things. So the way I said is it the way to go? By this I mean, I will use the matrix to pass to the shaders. But what about rotations? Shouldn't I use a quaternion for that? I really confused on how to implement it, as I said I read quite a few material before asking. But still I am confused. \$\endgroup\$
    – Morphex
    Jun 6, 2014 at 1:35
  • \$\begingroup\$ @Panda Pajama - The problem is not really a how to "create", I just want to understand how everything actually works together, although it seems I actually managed to come close to what I want. For example, to apply the rotation correctly what operations and what order should I do them? \$\endgroup\$
    – Morphex
    Jun 6, 2014 at 14:24
  • \$\begingroup\$ @Morphex: What have you tried? \$\endgroup\$ Jun 7, 2014 at 5:41

1 Answer 1

3
\$\begingroup\$

Ok, I'll give it a shot...

Your camera will need much of the same functionality as your regular entities in the game. Specifically, it will need to have both a position and orientation in your game world.

A simple 3D vector can be used to store the world position whilst a unit quaternion can be used to represent its rotation from some reference direction. I should stress here that only unit quaternions can be used to represent rotations. This is to say that the norm/magnitude/length of the quaternion should be equal to 1.0.

The unit quaternion represents a rotation from some reference vector - usually the "forward" vector (0, 0, 1). OpenGL uses a right-handed coordinate system where the z-axis points out of the screen. So unless you have a good reason for using something different, I would choose (0, 0, 1) to be your reference "forward" vector. Together, the quaternion rotation and forward vector represent an orientation.

This is really all that you need for the positioning and orientation of a camera. A suitable maths library should provide the functions necessary for manipulating the camera's rotation quaternion. For example, Unity provides the Quaternion.LookRotation function. With a similar function you can orient your camera to point in a given direction:

Vector3 direction = new Vector3(1.0, 0.0, 0.0); // Right
camera.rotation = Quaternion.LookRotation(direction);

To rotate the camera by some given unit quaternion q, you can simply multiply this by the camera's unit quaternion rotation on the left:

camera.rotation = q * camera.rotation;

Note that you don't need to normalise the result since the Hamilton product of two unit quaternions is itself a unit quaternion. Suitable 3D maths libraries will provide a constructor or static factory function for creating unit quaternions from Euler angles or from an angle about a given axis (angle-axis).

When rendering you will need to supply OpenGL or DirectX with a view matrix. This is in fact the inverse of the camera's transformation matrix. Now, if you are using a quaternion for the camera's rotation, you will need to convert this quaternion to a rotation matrix, R. You will also need to convert the camera's position into a translation matrix, T. Multiply these two matrices together in order to find the camera's transformation matrix. Matrix multiplication is not commutative; the order of multiplication matters and which order you choose depends on the kind of behavior you want.

Finally, your camera will need a projection matrix. You can think of this as the lens of the camera. You will probably want to use a perspective projection for a FPS game. For other games you may or may not want to use an orthographic projection. There is plenty of information available on finding/calculating these matrices so I won't elaborate.

That's all you really need. I should mention that you can use matrices instead of quaternions to represent the camera's rotation. This is generally more of a personal preference than a performance or memory efficiency consideration.

You can take a look at the small 3D maths library I am currently working on if you are interested in the mathematics side; such as how to calculate a "look at" quaternion.

\$\endgroup\$
1
  • \$\begingroup\$ That was exactly what I need. A Simple explanation that made me implement the camera! I was missing the point of doing the quaternion rotation based on what I consider a forward vector. \$\endgroup\$
    – Morphex
    Jun 7, 2014 at 14:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .