0
$\begingroup$

My goal is to update camera parameters given a velocity vector so that the camera points in the direction of the velocity vector. How should one compute the update matrix for the camera parameters?

$\endgroup$
8
  • $\begingroup$ when you say camera points, you mean to change the look at direction to conform with the velocity vector or just the position of the camera? $\endgroup$ – gallickgunner Jun 10 at 22:37
  • $\begingroup$ @gallickgunner Thank you for the question. I meant to say I need both the position and the look direction should conform with the velocity vector $\endgroup$ – Amir Jun 11 at 1:06
  • $\begingroup$ @gallickgunner Let me give you a better picture of what I actually need to do. In the framework I am using I need to set the camera's look direction (look_dir), the distance (dis) from the camera to look_dir, azimuth and elevation manually. Initially I was thinking I should first compute the rotation matrix replace the camera rotation matrix with the updated one, but it seems that this is not possible and I need to manually compute these camera parameters. I'm not entirely sure how to obtain these parameters starting from a given velocity vector. Do you know how I can do this? $\endgroup$ – Amir Jun 11 at 3:10
  • 1
    $\begingroup$ I still don't understand why you want to change the look_dir to that of the velocity vector. Also azimuth and elevation, are you using trackball style camera defined using spherical coordinates? A normal camera usually is defined by side, up, look_at and the position vectors. For the camera's position you could do something as simple as divide the velocity vector by 60 if let's say the app is running at 60 FPS then add it to the position, so after 1 complete second it's where it should be. If you wanna change the look_at as well you could lerp between the original and the velocity? $\endgroup$ – gallickgunner Jun 11 at 5:36
  • $\begingroup$ @gallickgunner I'm not sure what the camera type is but it's possible that it's a trackball style camera. What you suggested in terms of dividing the velocity vector by a number and adding it to the previous one is what I am going to use temporarily. However, this only works well if I assume that velocity vector does not rotate the camera and only moves the camera in space. I'm also not entirely sure if this would work for a trackball camera. $\endgroup$ – Amir Jun 15 at 17:01
1
$\begingroup$

The velocity vector becomes your forward vector, just normalize it. The up direction doesn't change, use whatever version up the camera usually uses. The last vector (call it the "right hand" vector) is the cross product of up, and forward. Then, do a second cross with the forward vector and the right hand vector to guarantee an orthonormal basis.

The last bit needed is the translation which will have to come from somewhere.

The exact ordering of all the operations is going to depend on the setup you are using. Is up direction y or z ect.

Once the matrix if formed, find its inverse. (Since you went through the trouble of making sure it is orthonormal, the inverse is equivalent to the transpose.)

This is the new view matrix.

Edit: When dealing with Azimuth and Elevation you can extract the angles from a vector using the geometric asin and acos functions. For example:

    vec3d fwd = target_point - camera_point; // generate a vector somehow
    fwd = normalize(fwd); // normalize it
    float azimuth = acos( fwd.x );
    float elevation = asin( fwd.y );  // extract angles
    if( fwd.z < 0 ) { elevation = -elevation; } // fix quadrant based sgn(z)

The above assumes that z is the up axis, and that azimuth/elevation are given in radians.

Now that the look direction is decided. Save it off to the side, and begin turning the camera. A good approach to turning the camera is to have a "radians per a second" turn rate. Get the time delta between updates from the system. And use those values to compute how much the camera should turn each frame just by computing the total number of radians that is needed for each direction.

    float time_delta_in_seconds = elapsed_seconds_since_last_frame();
    const float radians_per_second = 0.1; // slowish
    float turn_amount = time_delta_in_seconds * radians_per_second;
    float turn_amount = min(radians_to_turn, turn_amount); // don't overlook
    radians_to_turn -= turn_amount; // update  - converges on zero

So each frame:

  1. update the velocity vector
  2. compute the new camera settings but don't use them, save them
  3. compute your camera turn amount and update the camera with the new values

Make the 3 steps independent and the camera will just keep turning, chasing the velocity vector.

Handling user intervention seems self evident, if the user turns the camera disable the auto camera turning. If you want the camera to start turning after some preset amount of time, then just set a timer that enables auto turning and reset it every time the user moves the camera.

While this isn't the best system for auto camera following, it works and should (hopefully) get you going. The camera turning will be very mechanical since the turn rate is fixed. But once its all set its not to hard to add acceleration using the same ideas.

It just occurred to me that this is like 3 separate questions in one, really these should have been asked separately. At any rate, this should help some I hope.

$\endgroup$
12
  • $\begingroup$ Thank you for your response. The issue is I am not sure how to use the View matrix due to the setup of the camera in the framework I am using. In this framework, I can only set the camera's look direction (look_dir -- has components x, y, z), the distance (dis) from the camera to look_dir, azimuth and elevation manually. In some simple scenarios you can imagine look_dir being equivalent to velocity_vec but there are two issues with this: 1) I don't want to camera to have a sudden shift like 2) Velocity vector does not always determine where the camera looks. $\endgroup$ – Amir Jun 15 at 16:44
  • $\begingroup$ However, in my case it is okay if look_dir becomes equivalent to the velocity vector after some time (say 1 second -- assuming each second has 30 frames or so). However, I am not sure how to update all of the parameters such as look_dir, dis, azimuth and elevation given a velocity vector. Maybe I should use the View Matrix in some way for this? I would appreciate if you can help me with this. $\endgroup$ – Amir Jun 15 at 16:49
  • $\begingroup$ Thats the beauty of using a vector and the approach I outlined above. The velocity vector has that info built into it. Once you have the matrix built you can extract all the other information from the matrix itself. (I can add an edit showing that if you need, but I won't probably get to it today sorry) $\endgroup$ – pmw1234 Jun 15 at 17:15
  • $\begingroup$ I'd highly appreciate it if you can update your answer and include the new solution. Also, would you mind looking through the comments I posted above that were exchanged with another user before posting your updated solution? I think those comments might also provide you some more information on what I need. Really appreciate it $\endgroup$ – Amir Jun 15 at 17:41
  • $\begingroup$ This documentation for the framework I am using might be helpful as well: mujoco.org/book/haptix.html#uiCamera $\endgroup$ – Amir Jun 16 at 4:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.