Unfortunately, I do not know of a good book that teaches exactly what you are trying to figure out here, especially for OGL.
I wrote an example program for XNA that does a 3rd person camera that circles the target without using LookAt, but I’m not sure that helps you in OGL. I’m actually hoping to switch to OGL soon as I stopped doing XNA years ago and want to teach OGL now. I’ve been working on rewriting my DirectX11 very basic “game engine” in OGL and I hope to do a tutorial on that once I get it finished and put it on my YouTube channel, VirtuallyProgramming.com.
Speaking of that, you might want to check out my vector and especially matrices videos. That’s just math stuff and so it’s not specific to OGL, XNA, or DX. I do go straight into HLSL and Phong shading after that though. LOL :whistle: But, hopefully I’ll start a fairly basic OGL series of videos by this fall. (Possibly even in the next couple of months if the stars align just right.)
I’ve been pretty impressed with this book when it comes to game math. I haven’t read it cover to cover, but I own it and have flipped through it a bit. I don’t know that it covers exactly what you are doing here though.
So, what you’re trying to do is not all that difficult after you’ve done it a couple times. There are several principles regarding matrices that you need to know.
First of all, I would use GLM. I’m going to myself and I am extremely comfortable with the math. There’s nothing wrong with writing your own, but you need to understand the math first. If you want to write your own, what I would suggest is using both your own and GLM. Use GLM to make sure it works and that your logic is correct and then switch out the function/method with your own.
I did that with LookAt and built my own LookAt function a couple of years ago. I confirmed mine was correct by swapping it out with the built in LookAt function. The program worked exactly the same whether it used mine or theirs. And I did get a better understanding of the math and how it all works under the hood that way. Now I just use GLM.
So, first of all, with the View matrix. Yes, you could in theory start with an identity matrix, but you have to get the view matrix initially loaded. An identity matrix is an empty matrix and does not at all contain what should be inside a view matrix. My matrix video covers what should be in a view matrix. (Unless you are super solid on Vector algebra, watch the vector video first. I know it’s a few hours, but - as biased as I am - I think it’s worth the time.)
You need the look at function to initially build the view matrix. It needs to contain 3 mutually perpendicular vectors and a position value. I would probably initialize to an identity matrix and then use LookAt in my initialization code to set my starting view matrix. Now that I think about it, you could probably use an identity matrix if you take into account the inverse thing and are willing to start out with a zero’ed position and orientation.
Now what you often see is the view matrix rebuilt every frame using LookAt. I try to avoid that. After I build it once, I move it using matrix math.
The key trick here is that the view matrix is inversed. It’s exactly like a world/object matrix of an object except it’s inversed. (Also, scale probably doesn’t make sense with a view matrix.) The whole point of the view matrix is it does the exact opposite of whatever you tell it to do. This gets into how a view matrix works and why which I cover in my video.
So, I use the inverse function to change it back to normal. Or I inverse any operation, such as a rotation I apply against it.
Get that working first before trying to make a chase camera. Make a first person camera that way, so that you know that you understand that part.
But you can use the rotation and translation functions to build rotation and translation matrices and then apply those to your view matrix to move your camera.
Just multiply the view matrix by a rotation matrix and it will rotate the view matrix, but you are probably going to have to use an inverse rotation matrix or inverse the view matrix, apply the rotation, than inverse it again. I would have to do it in order to tell you the exact math, but it is pretty straight forward if you understand the view matrix is an inversed world matrix for the camera and that it only works if it is inversed. And that means you have to take that into consideration any time you work with it directly.
(The reason it is inversed is that the camera never actually moves; it’s job is to move the entire game world around the “camera” - a the origin - to trick the viewer into believing the camera moved. So, to rotate right you rotate the entire game world left. To move forward, you move the entire game world backwards. That is why it’s inversed.)
The cheat is to build a brand new view matrix every frame with LookAt and then you don’t need to know any of this. But once you stop doing that and just let the view matrix store the camera info from frame to frame, you need to know that it is inversed.
Also, the order of multiplication matters when working with matrices. MyMatrix = RotationMatrix * MyMatrix is totally different than MyMatrix = MyMatrix * RotationMatrix. One should rotate around the local axis and the other rotates around the global axis.
Also, when rotating or scaling, you usually have to move the object to the origin (world center), apply the math, then move it back. You just subtract the position of the object to bring it to the origin, apply the operation, then add the same position you subtracted to put it back where it was after rotating or scaling.
With a rotation, if you don’t do this it will orbit the origin rather than rotating around it’s own center.
And it turns out that is how you make a 3rd person orbiting camera: just don’t move the camera to the origin when rotating it.
So, probably the final “secret” here is that you can link matrices together.
Maybe the most obvious way to see this is to do a chase camera. My game object has it’s own world matrix, right. That world matrix has the position and orientation of my game object.
My camera has a view matrix, which is the same thing, but inverted.
Wait. Let me explain this using two world matrices before we confuse it by throwing in a view matrix.
So, you need to understand rigid animation.
When I make a car model, I am going to make the body of the car as one model/mesh and then make the four wheels as separate models/meshes. In Blender, I will parent them together. This tells my program when it imports the model that there is a parent child relationship between the meshes. My code needs to take that into account.
Each mesh has it’s own world matrix allowing the wheels and car body to be controlled separately. The parent-child attachment/relationship is done by multiplying the wheel matrix by the car body matrix.
When you multiply/combine the wheel matrix with the body matrix, you will get the wheel position, orientation, (and scale) relative to the car body. So when drawing the car body you use it’s world matrix. But when drawing the wheels, you use the wheel’s matrix times the body matrix. When you do this, the wheel is relative to the car body. So, if you move the car body using its world matrix the wheels will remain attached. But when you move the wheels by changing the wheel matrix, it does not affect the car body. So you can rotate the wheels without affecting the car body. The “secret” is keeping the matrices separate except when you want the wheel position and orientation you use both the parent matrix and the child matrix by multiplying them together.
You can chain them as deep as you like. You can have grandchildren, great-grandchildren, or great-great-great-great-great-great-great-great-grandchildren. Each just gets its own matrix and you have to multiply them all together to find out how to place the great-great-great-great-great-great-great-great-grandchild into the scene.
You can apply this same concept to the view matrix to make a 3rd person chase camera that orbits the object. Just use the object’s matrix and multiply the view matrix times that in order to make the view matrix a child of the parent object. Also, don’t move the view matrix to the origin when rotating it so that it orbits the object rather than rotating on it’s own axis.
Probably start by doing a view matrix on its own and get it to orbit the origin. (Remember you need at least 3 objects in your scene to see motion.) Once you get the view matrix camera to orbit the origin, you can than multiply it time the object’s matrix to make it a child of the object.
You also may need to rotate the view matrix camera on it’s own local axis to make it look at the object after the rotation. Using the LookAt function to rebuild it is the easy way to do that because you just always have it look at the (local) origin which as a child is actually the center of its parent. You can probably de-construct the view matrix to extract the position.
Or, you could do the math to make it look at the local origin which is a bit more complicated. This looks like it kind of gets into that, but I need to go get ready for work now.