Saturday, June 13, 2015

c++ - Rotate Camera as an Object Manoeuvres


There are loads of questions (all of which I have looked at) on here about cameras following objects. Using them, I have successfully got my camera to follow my car when driving, but I am unable to make the camera swing right when the car turns left (so it stays directly behind it) and vice-versa.


So far, this is how I've got my camera following my object:


    camOrigin.x  = (0   +globalPos.x+velocity.x); //Camera Position
camOrigin.y = (0 +globalPos.y+velocity.y);
camOrigin.z = (100 +globalPos.z+velocity.z);

camLookingAt.x = (0 +globalPos.x+velocity.x); //Camera Looking at Object
camLookingAt.y = (0 +globalPos.y+velocity.y);
camLookingAt.z = (0 +globalPos.z+velocity.z);
camNormalXYZ.x = (0); //Camera Normal = Y
camNormalXYZ.y = (1);
camNormalXYZ.z = (0);

I have tried to use the same algebra I've used to calculate the cars direction and velocity because I figured the angle the camera moves would be the inverted angle the camera needs to move, but it didn't work.


    camOrigin.x  = (0   +globalPos.x+velocity.x-sin(rotX_rad)); //Camera Position
camOrigin.y = (0 +globalPos.y+velocity.y);

camOrigin.z = (100 +globalPos.z+velocity.z-cos(rotX_rad));

I'm unsure how to take this further.


Edit: Little drawing to help describe the movement. I'm looking to move the camera from c to d when the car turns in the left direction (and vice-versa when turning right).


enter image description here


Update:


    rotX_rad = rotX*PI/180;     //convert to radians
velocity.x = sin(rotX_rad); //calculate X coord
velocity.z = cos(rotX_rad); //calculate Z coord


//globalPos + velocity;
globalPos.x + velocity.x*delta;
globalPos.z + velocity.z*delta;

ModelViewMatrix = glm::translate(viewMatrixMovingCube,globalPos); //move/update car

ModelViewMatrix = glm::translate(ModelViewMatrix, glm::vec3(0,-48,0)); //position low on screen
ModelViewMatrix = glm::rotate(ModelViewMatrix, rotX, glm::vec3(0,1,0)); //manually turn/control rotation of car

Answer



A common base approach is to model the camera as though it were towed behind your character/vehicle on a free-swinging bar.



To do this, you keep track of an intended follow distance d and an intended height h.


Each frame, take the vector from your follow target (after it has moved) to the camera (before it has moved). Normalize it, multiply it by d, then correct the height to h. Now add it to your follow target's position to get your new camera position (you can either set it directly, or lerp the camera toward it for a softer camera feel)


This gives a camera that will be gradually pulled behind you anytime you move away from it. It's a conceptually-simple base, but it has some problems on its own so you'll need to layer additional behaviour on-top:




  • The speed with which the camera gets behind you is inversely proportionate to the follow distance - a close camera swings responsively (maybe even a bit twitchy) while a distant one barely moves. You can fix this by tracking a "fake" camera at a fixed distance from your player that feels like the right balance, then multiplying its offset by a scaling factor to get your real camera offset.




  • It needs some help getting around sharp corners. Normally it follows a curve of pursuit, which means it lazily cuts corners whenever it can. Adding a multiple of the player's "back" vector (negative forward) to the offset before you normalize it helps.





  • Play with the look direction - you'll probably want the camera to look at a point above the follow target, and a ways ahead of it (this pushes the target toward the bottom of the screen so you can see more of what's ahead). Biasing this anticipation vector according to velocity and steering can help the camera feel responsive, without it moving around too much.




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...