This is what I do for my 3rd-Person Camera:
Code: Select all
else if (m_CamType == CAMTYPE_3RDPERSON)
{
assert(!(m_SnapTarget == nullptr));
const D3DXVECTOR3 SnapDir = *m_SnapTarget->GetDirection();
const D3DXVECTOR3 SnapUp = *m_SnapTarget->GetUp();;
const D3DXVECTOR3 SnapRight = *m_SnapTarget->GetRight();
const D3DXVECTOR3 SnapPos = *m_SnapTarget->GetPos();
D3DXVECTOR3 CamVecDir = *m_SnapTarget->GetDirection();
D3DXVECTOR3 CamVecUp = *m_SnapTarget->GetUp();
D3DXVECTOR3 CamVecRight = *m_SnapTarget->GetRight();
// 1st: Rotate the CameraVector
// 1.1. Rotate Local Up/Down
D3DXMATRIX Temp;
//D3DXMatrixRotationAxis(&Temp, &CamVecRight, D3DXToRadian(m_OffsetRot.x));
D3DXMatrixRotationAxis(&Temp, &SnapRight, D3DXToRadian(m_OffsetRot.x));
D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
D3DXVec3Normalize(&CamVecDir, &CamVecDir);
D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
D3DXVec3Normalize(&CamVecUp, &CamVecUp);
D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
D3DXVec3Normalize(&CamVecRight, &CamVecRight);
// 1.2. Rotate Global Left/Right
//D3DXMatrixRotationAxis(&Temp, &CamVecUp, D3DXToRadian(m_OffsetRot.y));
D3DXMatrixRotationAxis(&Temp, &SnapUp, D3DXToRadian(m_OffsetRot.y));
D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
D3DXVec3Normalize(&CamVecDir, &CamVecDir);
D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
D3DXVec3Normalize(&CamVecUp, &CamVecUp);
D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
D3DXVec3Normalize(&CamVecRight, &CamVecRight);
// 1.3 Rotate Local Tilt
D3DXMatrixRotationAxis(&Temp, &CamVecDir, D3DXToRadian(m_OffsetRot.z));
//D3DXMatrixRotationAxis(&Temp, &SnapDir, D3DXToRadian(m_OffsetRot.z));
D3DXVec3TransformCoord(&CamVecDir, &CamVecDir, &Temp);
D3DXVec3Normalize(&CamVecDir, &CamVecDir);
D3DXVec3TransformCoord(&CamVecUp, &CamVecUp, &Temp);
D3DXVec3Normalize(&CamVecUp, &CamVecUp);
D3DXVec3TransformCoord(&CamVecRight, &CamVecRight, &Temp);
D3DXVec3Normalize(&CamVecRight, &CamVecRight);
// 2nd: Calculate New Camera Pos
m_Pos = SnapPos - (m_OffsetDist * CamVecDir);
// 3rd: Calculate new Camera Local Vectors
m_Target = CamVecDir;
m_Up = CamVecUp;
m_Right = CamVecRight;
// 4th: Do Vector regeneration
D3DXVec3Normalize(&m_Target, &m_Target);
D3DXVec3Cross(&m_Right, &m_Up, &m_Target);
D3DXVec3Normalize(&m_Right, &m_Right);
D3DXVec3Cross(&m_Up, &m_Target, &m_Right);
D3DXVec3Normalize(&m_Up, &m_Up);
// 5th: update viewmatrix
m_ViewMatrix._11 = m_Right.x;
m_ViewMatrix._12 = m_Up.x;
m_ViewMatrix._13 = m_Target.x;
m_ViewMatrix._21 = m_Right.y;
m_ViewMatrix._22 = m_Up.y;
m_ViewMatrix._23 = m_Target.y;
m_ViewMatrix._31 = m_Right.z;
m_ViewMatrix._32 = m_Up.z;
m_ViewMatrix._33 = m_Target.z;
m_ViewMatrix._41 = -D3DXVec3Dot(&m_Pos, &m_Right);
m_ViewMatrix._42 = -D3DXVec3Dot(&m_Pos, &m_Up);
m_ViewMatrix._43 = -D3DXVec3Dot(&m_Pos, &m_Target);
// 6th: set transform
m_pDirect3DDevice->SetTransform(D3DTS_VIEW, &m_ViewMatrix);
}
It's not that complicated.
First I make const copys of the local-vectors of the snaptarget (in your case it would be the car).
http://puu.sh/9yR9j/0ad170ed2d.jpg
The Up-Vector always points upwards the car (e.g. when you jump you would technically move along the local Up-Vector).
The Direction Vector always points in the direction your car is facing.
The RightVector always points to the right (if you strafe in an ego-shooter you would always move along the local RightVector of the Character). You Need local Vectors of the Car to work. It is important, that you rotate these vectors with your car.
You may have seen those local vectors in 3D Programms:
http://puu.sh/9yS29/8125da5d33.png
Those "Gizmos" used in those programm are the same as the three local Vectors (Up, Right, Direction).
The 3 CamVec Vectors will be the endresult I will use in the end to calculate the new viewmatrix.
1st I rotate the CamVec vectors in three different directions. What I do is rotating around the three Vectors of the Car (the const copys!). If you change the m_OffsetRot Vector you can freely rotate the Camera around the Target.
http://puu.sh/9yRyH/3af46614a4.jpg
It may look like this, after all rotation stuff.
In your racing game, you may want to set the OffsetRot Vector once (normally you can't rotate the cam freely around the car).
2nd part:
ONE IMPORTANT THING!: Those Local Vectors are "Unitlength Vectors". That means they ALWAYS should have a length of 1 (chili called them x^(x-hat) and y^(y-hat) in the 2D world). Then If I multiply the vector with a scalar (normal number), the Vector will always have the length of the scalar! (like multiplying with 1).
To Calculate the CamPos I stretch the Camera Direction Vector by a certain Length (called OffsetDist(ance)) and subtract it from the Snappos (in your case Car). This means the resulting Cameraposition will be perfectly behind the Camera Direction Vector. And because we rotatet these Vectors freely it could be anything around the car.
http://puu.sh/9yRJl/4db4c19a14.jpg
In the 3rd Part I Use The CamVec Vectors and set them as the three Camera Vectors (which you use to create the Viewmatrix). This way the Camera will always look at the Car.
4th is very important. When rotate the camera you will get little rounding errors. They are small, but the more you have moved the camera the bigger those errors will become. And in the End the Camera might not work probably after some time. You ALWAYS need to do this when you rotate any object, that has local-vectors (so basically every object).
5th is another possibility to create a new viewmatrix (if you want you can use the D3DX-Helper functions to create one, my version is not necessary).
6th: Set the new Viewmatrix.
You have to do this every frame (or even better everytime, the 3rd-Person Target has moved!)
Hopefully this could help a little bit