9 Replies - 765 Views - Last Post: 30 July 2013 - 06:22 PM Rate Topic: -----

#1 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Ideas on attaching a camera to a model in 3D space?

Posted 23 July 2013 - 01:00 PM

I was wondering if anyone had any ideas that might help me with the problem I am currently facing in my current 3D project.

The problem, in a nutshell, is that I cannot figure out how to attach a "follow" 3rd person camera to my model in 3D space.

I've done quite a few cameras over the past year. But pretty much all of them have been following a 2D plane of some sort. Whether we're talking 1st person or some sort of follow camera, the cameras that I've done have followed objects moving across a relatively flat plane, such as a terrain or an actual plane.

My current project is litterally in 3D space. It's basically a space ship simulator. But I'm finding that I cannot implement the camera that I had intended to implement.

Here's what I want to happen: I imagine a vector/arrow sticking up out of the top of my ship model that the camera should look at the tip of the vector. The camera should orbit around this point and (the hard part) should remain attached to this point. So, as the ship yaws, pitches, and rolls, the camera should follow it through every move and remain at the exact same spot relative to the ship.

Originally, I thought I could do this with two vectors and quickly discovered that that totally doesn't work in full 3D space. It works great when following something moving across a plane, but as soon as you go into wild maneuvers you discover that the vectors remain basically parallel to the plane they started on. It just doesn't work at all.

So, I've been working on animating a lot here lately, and I've been working with transformation matrices. This seemed like a perfect place to apply them and I've got it almost working.

The theory was to move the model with its world matrix. Then a camera look at point would be defined through a transformation matrix that would be relative to the model's world matrix. (WorldMatrix * CameraLookAt = where the lookat point is). Then a second transformation matrix would define the camera "eye" point. (WorldMatrix * CameraLookAt * EyePoint = Where the camera's eye point is at). Everything is defined relative to one another at that point. So the camera is firmly attached to the model and follows it through rolls and such.

I suspect the problem may be due to the fact that I'm using these 3 matrices to then help me define a view matrix for the camera. And as you know, the view matrix is inversed compared to other matrices. I don't know if that's part of the issue or not.

Anyway, here's the current behavior that's wrong: The camera perfectly follows the ship through rolls and yaws regardless of whether it's clockwise or counter clockwise. The problem comes when the ship pitches. When it pitches the camera does not move correctly. It looks like the ship pitches and the camera remains in its original position without following the ship. However, what "could" be happening is that the ship and the camera are rotating through opposite rotations (one rotating clockwise and the other counterclockwise for example). I'm not sure of any way to tell which is happening. Hmm, maybe I could answer that if I pay more attention to the skybox in the background; it shouldn't move if the camera is actually stationary.

Anyone have any ideas on what my problem might be? Any ideas on why it Yaws and Rolls perfectly but goes crazy for Pitch?

Anyone have totally different ideas on how to attach a camera to a space ship model?

This post has been edited by BBeck: 23 July 2013 - 01:04 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Ideas on attaching a camera to a model in 3D space?

#2 anonymous26   User is offline

  • D.I.C Lover

Reputation: 2
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Ideas on attaching a camera to a model in 3D space?

Posted 23 July 2013 - 01:56 PM

A common problem with roll, pitch and yaw is 'gimbal lock'. This is the property where rotated axes become perfectly parallel confusing the math and causing them to be locked in motion together causing unexpected behavior. Judging from what you have described it sounds like you are experiencing this because motions appear to be good within a certain range, then when you go outside that range that is when the locking behavior occurs. Your suspicion about how you are using your matrices is perfectly correct, but how would you remove this problem? Well, there are a couple of options:

1. Make sure that your motions remain within the safe range, but this is not ideal.
2. Learn about quaternions. These specifically overcome the gimbal lock issue and reduce the number of variables used for your affine transformation calculations.
Was This Post Helpful? 1
  • +
  • -

#3 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Ideas on attaching a camera to a model in 3D space?

Posted 23 July 2013 - 02:20 PM

I thought of gimbal lock as a possibility, although everything seems axis aligned at this point, and I wasn't expecting a gibal lock problem until one axis crossed over the other. Still, there's "something" fishy going on on a single axis. So maybe you're right. Maybe it is gimbal lock.

If it is a gimbal lock problem, there "is" no safe range, as you know, because I'm turning through 360 degrees on all 3 axes. This is completely "free form" (for lack of a better word) rotation. So, gimbal lock was bound to become a problem at some point just because I can't limit the range of motion like you're talking about (my space ship should be allowed unrestriced rotation through space).

Now that you bring up the subject of quaternions, I probably should have been using quaternions for a space ship program in the first place.

I'm not sure how to apply quaternions to this particular problem because I'm trying to keep the camera attached through the rotations. I could keep track of the ship's orientation with a quaternion, but then keeping the look-at point relative to the orientation of the ship, and then making the camera position relative to the look-at point is something that I'm not sure how to work quaternions into.

I've heard brief mention of using quaternions inside of transformation matrices. If this is a gimbal lock problem, then that sounds like it would fit the bill perfectly. The transformation matrices do a great job of keeping every point relative to its parents, but I believe they are all using Euler angles internally and probably prone to gimbal lock. Primarily, I'm using them for translation at this point, and not trying to rotate any of them (yet), except the model's world matrix. The rest are all defined relative to their parents and thus just move with the parent (except that this doesn't work right along one axis).

Maybe that's what causing a gimbal lock problem; since I have 3 matrices each with seperate local axes maybe they are gimbal locking between them across a single axis.

I guess I should look at the possibility of using quaternions inside transformation matrices or in parallel with transformation matrices.

Thanks! I'll give it some more thought. (I would give you a thumbs up, but for some odd reason the computer I am on right now never allows me to click on thumbs up. I'll send you a thumbs up when I can get on a computer that allows me to. But definately thanks!)
Was This Post Helpful? 0
  • +
  • -

#4 anonymous26   User is offline

  • D.I.C Lover

Reputation: 2
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Ideas on attaching a camera to a model in 3D space?

Posted 23 July 2013 - 02:26 PM

If you're using matrices then you are using 'Euler Angels' which are, of course, prone to gimbal lock. If you are going to be performing crazy rotations without restriction you would be nuts not to use quaternions.

(No problem about the thumbs-up, btw. :) )

This post has been edited by ButchDean: 23 July 2013 - 02:27 PM

Was This Post Helpful? 0
  • +
  • -

#5 IntVoid   User is offline

  • New D.I.C Head

Reputation: 7
  • View blog
  • Posts: 33
  • Joined: 21-July 13

Re: Ideas on attaching a camera to a model in 3D space?

Posted 27 July 2013 - 12:28 PM

View PostButchDean, on 23 July 2013 - 02:26 PM, said:

If you're using matrices then you are using 'Euler Angels' which are, of course, prone to gimbal lock. If you are going to be performing crazy rotations without restriction you would be nuts not to use quaternions.

(No problem about the thumbs-up, btw. :)/> )


Actually have a sample code in my last project in using quaternions and matrices to make the camera follow an object in 3D space. You would basically update the camera's matrices and look-at position with the offset matrix of the object the camera is looking at. Using a dampener on the rotations/yaws/pitch on the object helped a lot with the camera not going a million miles an hour due to movement...

sooo pretty much what ButchDean said lol.
Was This Post Helpful? 0
  • +
  • -

#6 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Ideas on attaching a camera to a model in 3D space?

Posted 30 July 2013 - 01:22 PM

A bit of an update on this issue:

It turns out that it had nothing to do with gimbal lock, although with 360 degrees of possible rotation on all 3 axes, I would not at all be surprised if gimbal lock creeps in somewhere in the future if I don't start using quaternions. It's just that the matrices use Euler angles internally and I wanted to try and avoid getting too far away from matrices as the final result must be a matrix full of Euler angles.

I did do a version where the model itself was controlled (orientation wise) with a quaternion, but that alone did not affect the problem, let alone solve it. (Although, I never went all the way and converted everything to quaternions.)

Anyway, the issue seems to have basically boiled down to my lack of understanding of game matrices, specifically applying transformation matrices and how the View matrix actually functions, really how game matrices in general function, but especially the View matrix.

I ended up backing up many steps and producing a more simple version of the problem. My program was getting more and more convoluted as I attempted to solve the problem. I kept adding and adding and adding code to try and solve it until my code started feeling really bloated and was starting to turn into spaghetti. So, I produced a very simple version where I could zoom in and focus on the problem.

I created two models in Blender neither were textured. The first was a green "ground" plane and the second was a yellow cube that I attempted to attach the camera to.

I immediately had the same problem. So, I knew it was time to deconstruct the View matrix. It seems that everywhere these days the View matrix is built for you. I believe both XNA and DirectX 11 have methods/functions that construct the View matrix for you named basically "LookAt". I've, of course been using this. At one point, I may have had a rough idea of how the View matrix actually does its magic, but I certainly was no longer aware of what the "Up" parameter in the "LookAt" functions was doing.

The reason this has not bit me in the posterior end before is because I've essentially been working confined to a 2D plane in 3D. A person avatar walks across the terrain and even if it's rough terrain the camera stays relatively level and up is the same for the model as it is for the terrain. So, here I am in this space ship simulator and I can turn in any possible orientation imaginable and "up" for the model is not the same as "up" is for the skybox, for example.

So, I deconstructed the View matrix by building my own LookAt function:

        private Matrix LookAt(Vector3 eye, Vector3 target, Vector3 up)
        {
            Vector3 zaxis = eye - target;    // The "look-at" vector.
            zaxis.Normalize();
            Vector3 xaxis = Vector3.Cross(up, zaxis);// The "right" vector.
            xaxis.Normalize();
            Vector3 yaxis = Vector3.Cross(zaxis, xaxis);     // The "up" vector.
            // Create a 4x4 orientation matrix from the right, up, and at vectors
            Matrix orientation = new Matrix(
                   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
                   );
            // Create a 4x4 translation matrix by negating the eye position.
            Matrix translation = new Matrix(
                     1,      0,      0,     0,
                     0,      1,      0,     0, 
                     0,      0,      1,     0,
                   -eye.X, -eye.Y, -eye.Z,  1
                  );
            // Combine the orientation and translation to compute the view matrix
            return (translation * orientation);
        }



This was a great education on what's going on inside the View matrix. I actually tested this against the LookAt function that was built in and verified that it produced the exact same View matrix as output using the exact same input. I couldn't really pull apart their code and look inside, but I managed to duplicate it, so that I could take a look inside.
Also, last week, I started writing a tutorial on matrices and what is going on internally inside the matrices. And so this dove-tailed right in.

I eventually realized that all of these matrices are really defining an orientation by defining three mutually perpendicular axes and the offset of their origin from the origin of the game world. You could say that it "translates things that the matrix is applied against into model (or this matrix's) space".

The "Up" vector that is fed into the LookAt function is used to define which direct this matrix regards as "above". "Up" is a bit of a misnomer, because if the matrix is turned upside down then down is "Up". "Above" would have been a more accurate term because it's really asking which direction is "Up" for this particular matrix and nothing else. It's irrelevant which direction is "Up" for the rest of the game world. It only wants to know which direction is "Up" for this one matrix, which could be any possible direction.

This lack of understanding is the first thing that messed me up.

After I figured out what was actually going on inside the View matrix and what the "Up" parameter actually did, I was (surprisingly enough) able to make this whole thing work using vectors, which is where I started off in the first place. I had been convinced that it could not be done with vectors, and then I did it with vectors.

ViewMatrix = LookAt(YellowCubesWorldMatrix.Translation + (YellowCubesWorldMatrix.Up * 1.5f) + (YellowCubesWorldMatrix.Backward * 4f), YellowCubesWorldMatrix.Translation + (YellowCubesWorldMatrix.Up * 1.5f) + YellowCubesWorldMatrix.Forward, YellowCubesWorldMatrix.Up);



1.5 is the offset for the camera upwards and 4 is the offset of the camera behind the model. This worked like a charm and followed my Yellow Cube model through every turn and roll it made on all 3 axes. I don't know any particular reason why it can't, or shouldn't, be done this way.

But I wanted to use transformation matrices. It seemed more appropriate. Or at least, I wanted to figure out how the same thing could be done with transformation matrices regardless of which was the best method to use.

That was when I discovered that I had been applying my transformation matrices "backwards" which came as a bit of a shock. I thought it would not matter. I "thought" I was really only doing translations. But I guess, if you think about it, I'm doing a rotation in the model itself. Because there is a rotation involved (at least one), the order of combining the matrices is imperative. I had to reverse the order I was applying the matrices and apply them from outside to the inside.

After that, everything worked.

            CameraMountWorldMatrix = Matrix.CreateTranslation(0f, 1f, 0f);
            CameraPositionWorldMatrix = Matrix.CreateTranslation(0f, 0f, 4f);

            Camera = CameraPositionWorldMatrix * CameraMountWorldMatrix * YellowCubesWorldMatrix;
            CameraMount = CameraMountWorldMatrix * YellowCubesWorldMatrix;
            
            //ViewMatrix = Matrix.CreateLookAt(Camera.Translation, CameraMount.Translation, Camera.Up);
            //ViewMatrix = LookAt(YellowCubesWorldMatrix.Translation + (YellowCubesWorldMatrix.Up * 1.5f) + (YellowCubesWorldMatrix.Backward * 4f),
            //      YellowCubesWorldMatrix.Translation + (YellowCubesWorldMatrix.Up * 1.5f) + YellowCubesWorldMatrix.Forward,
            //      YellowCubesWorldMatrix.Up);
            ViewMatrix = LookAt(Camera.Translation, CameraMount.Translation, Camera.Up);


This post has been edited by BBeck: 30 July 2013 - 01:28 PM

Was This Post Helpful? 0
  • +
  • -

#7 anonymous26   User is offline

  • D.I.C Lover

Reputation: 2
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Ideas on attaching a camera to a model in 3D space?

Posted 30 July 2013 - 01:41 PM

How did you test it, though? As you rightly suspect, the threat of gimbal lock is only removed by using other methods.
Was This Post Helpful? 0
  • +
  • -

#8 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Ideas on attaching a camera to a model in 3D space?

Posted 30 July 2013 - 01:59 PM

What do you mean when you ask how I tested it? And by "it" what are we talking about?
Was This Post Helpful? 0
  • +
  • -

#9 anonymous26   User is offline

  • D.I.C Lover

Reputation: 2
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Ideas on attaching a camera to a model in 3D space?

Posted 30 July 2013 - 03:48 PM

What steps did you take to see that the code works reliably?

This post has been edited by ButchDean: 30 July 2013 - 03:49 PM

Was This Post Helpful? 0
  • +
  • -

#10 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Ideas on attaching a camera to a model in 3D space?

Posted 30 July 2013 - 06:22 PM

Well, the original problem was obvious. All you had to do was rotate through the three axes and one of them would cause it to go haywire.

So, the primary test was just rotate it through all three axes and see if it goes haywire like before. When there was a problem, there was no doubt that there was a problem. So, when the problem went away, it was likewise obvious. But mostly I just took the YellowCube for a ride and tried to shake the camera loose. Nothing I did seemed to cause it to fail. Certainly, the very obvious problems that had been there before were gone.

Now don't get me wrong. Gimbal lock is bound to creep back in somewhere and I'm taking no precautions at the moment to prevent it. I would suspect it to rear its ugly head if I were to start rotating the camera mount and the camera position matrices. Now that I understand how these matrices are working internally, I realize that what I have here is three completely separate sets of axes.

Right now, everything is "fixed" and nothing rotates except the model itself. The camera mount is not intended to rotate and will likely never cause a problem. But the camera position matrix is something I intend to rotate in a circle around the Y axis. I see potential for gimbal lock between that matrix and the world matrix of the model except that since I'm planning on staying 2D with the rotation around the Y axis and so, may be able to even work around any gimbal lock problem that arises.

Honestly, I'm not sure I've even actually seen gimbal lock occur, although I'm very aware that its a real thing. As long as its not broke, I'm inclined to not fix it. Eventually, it may break and I'll have to address the problem. That's kind of the scenario here. I've been doing cameras for a couple years and never had this problem until I decided to go into unlimited rotation. But my primary problem there was a lack of understanding of the internals of the View matrix.

And back to the original question. I knew it was fixed when I figured out what was causing it, changed it, and the problem went away. But that doesn't mean I've eliminated all possibility of gimbal lock occurring in the future. I was not certain whether it was gimbal lock or not, until I figured out how to fix it.

Not knowing how to pass the parameters to the LookAt function correctly was kind of a glaring error on my part. It's kind of amazing that I got away with passing the parameter incorrectly for years. And applying the transformation matrices in the wrong order was kind of another big error on my part.

I did do some testing. For example, I experimented with the order I was applying my matrices in. Any order other than outer to inner caused things to go haywire. It also helped that I got the whole thing working with vectors. Once I started defining my View matrix correctly and then got it working with vectors, it gave me a working standard to compare everything against. I knew "conceptually" what I wanted all along, it just was not acting the way I expected. And I figured out that my understanding of the View matrix was wrong, and that I was wrong about the order of the transformation matrices being applied did not matter.

This post has been edited by BBeck: 30 July 2013 - 06:29 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1