3rd person camera in DirectX

Started by
6 comments, last by Aaron1178 12 years, 8 months ago
Hello all,
The names Aaron1178, I'm a student and a professional web developer (php), I recently decided (start of the year) that I was going to learn the ins and outs of Game Programming. It is going good so far. I am able to load .X meshes (character mesh, npc meshes and object meshes(buildings ect)) . Now when it comes to the bone, I am a persistent SOB that will work endlessly to try and fix the solution. But this one, I cannot fix.

The problem:
I am trying to create a 3rd person camera that will rotate around the character at X,Y,Z coordinates. But I am uncertain of how to accomplish this. Some have suggested a Matrix.Transformation to rotate the camera around the indicated mesh coordinates. But it is not working, Here is my code so far.

Also it is in C# :) I know... I should be using C++

device.Transform.View = Matrix.Translation(cameraMove.X, cameraMove.Y, cameraMove.Z) * Matrix.RotationAxis(new Vector3(0, 1, 0), camera.Y) * Matrix.RotationAxis(new Vector3(1, 0, 0), camera.X);


That is just a translation but the transformation (did not work)


device.Transform.View = Matrix.Translation(cameraMove.X, cameraMove.Y, cameraMove.Z) * Matrix.Transformation(new Vector3(0,0,0), Quaternion.Identity, new Vector3(0,0,0), new Vector3(0, 0, 0), new Quaternion(0,0,0,0), Vector3.Empty);


All help is much appreciated.

Thanks,
Advertisement
According Cam3Person theory you must have a model and camera (camera move around and follow a model). You need create class model and class camera. Class model Update func (update model move according movement keys left, right, up, down and mouse input):

[source lang="cpp"]
void CModel::FrameMove(float fTime)
{
//mouse move
POINT mousePos;
GetCursorPos(&mousePos);

//return mouse in center screen
SetCursorPos(nScreenWidth/2, nScreenHeight/2);

//how many pix mouse move
int nDeltaX=nScreenWidth/2-mousePos.x;
int nDeltaY=nScreenHeight/2-mousePos.y;

D3DXVECTOR2 m_vRotVelocity = m_vMouseDelta * m_fRotationScaler;

if(nDeltaX<0)
{

//move right
D3DXMATRIX matRot;
D3DXVECTOR3 vUpTemp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
D3DXMatrixRotationAxis(&matRot,&vUpTemp,D3DXToRadian(m_vRotVelocity.x));

D3DXVec3TransformNormal(&vRight,&vRight,&matRot);
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);
//D3DXVec3TransformCoord( &vPos, &vPos, &matRot );


}
if(nDeltaX>0)
{

//move left
D3DXMATRIX matRot;
D3DXVECTOR3 vUpTemp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
D3DXMatrixRotationAxis(&matRot,&vUpTemp,D3DXToRadian(-m_vRotVelocity.x));
D3DXVec3TransformNormal(&vRight,&vRight,&matRot);
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);
}

if(nDeltaY<0)
{
//move down
D3DXMATRIX matRot;
D3DXMatrixRotationAxis(&matRot,&vRight,D3DXToRadian(m_vRotVelocity.y));
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);

}
if(nDeltaY>0)
{
//move up
D3DXMATRIX matRot;
D3DXMatrixRotationAxis(&matRot,&vRight,D3DXToRadian(-m_vRotVelocity.y));
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);

}

//keyboard move

if(GetAsyncKeyState('D')& 0xFF00)
{

//move right
D3DXMATRIX matRot;
D3DXVECTOR3 vUpTemp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
D3DXMatrixRotationAxis(&matRot,&vUpTemp,D3DXToRadian(m_vRotVelocity.x/15));
D3DXVec3TransformNormal(&vRight,&vRight,&matRot);
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);

}
if(GetAsyncKeyState('A')& 0xFF00)
{
//move left
D3DXMATRIX matRot;
D3DXVECTOR3 vUpTemp = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
D3DXMatrixRotationAxis(&matRot,&vUpTemp,D3DXToRadian(-m_vRotVelocity.x/15));
D3DXVec3TransformNormal(&vRight,&vRight,&matRot);
D3DXVec3TransformNormal(&vUp,&vUp,&matRot);
D3DXVec3TransformNormal(&vLook,&vLook,&matRot);




}

float ratioMove = 50;
D3DXVECTOR3 vAccel = D3DXVECTOR3(0,0,0);


if(GetAsyncKeyState('W')& 0xFF00)
{
vAccel = D3DXVECTOR3(vLook.x, 0.0f, vLook.z) * ratioMove * fTime;
}
if(GetAsyncKeyState('S')& 0xFF00)
{
vAccel = D3DXVECTOR3(vLook.x, 0.0f, vLook.z) * -ratioMove * fTime;
}


//change position
vPos+=vAccel;

//makes all vectors of camera perpendicular each other
D3DXVec3Normalize( &vLook, &vLook );
D3DXVec3Cross( &vRight, &vUp, &vLook );
D3DXVec3Normalize( &vRight, &vRight );
D3DXVec3Cross( &vUp, &vLook, &vRight );
D3DXVec3Normalize( &vUp, &vUp );

}

void CFirstPersonCamera::Update(float TimeScale)
{
//move camera follow and around model
D3DXMATRIX mtxRotate;
D3DXMatrixIdentity( &mtxRotate );
D3DXVECTOR3 vecRight = m_pModel->GetRight(), vecUp = m_pModel->GetUp(), vecLook = m_pModel->GetLook();
mtxRotate._11 = vecRight.x; mtxRotate._21 = vecUp.x; mtxRotate._31 = vecLook.x;
mtxRotate._12 = vecRight.y; mtxRotate._22 = vecUp.y; mtxRotate._32 = vecLook.y;
mtxRotate._13 = vecRight.z; mtxRotate._23 = vecUp.z; mtxRotate._33 = vecLook.z;

//camera is 15 unit up model, and -50 unit from back of model
D3DXVECTOR3 vOffset(0,15,-50);

D3DXVECTOR3 vecOffset(0,0,0);

// Calculate our rotated offset vector
D3DXVec3TransformCoord( &vecOffset, &vOffset, &mtxRotate );

// vecOffset now contains information to calculate where our camera position SHOULD be.
D3DXVECTOR3 vecPosition = m_pModel->GetPosition() + vecOffset;


if(vPos.y<0.0f) vPos.y = 0.0f;

//calculate view matrix
matView._11 = vecRight.x;
matView._21 = vecRight.y;
matView._31 = vecRight.z;

matView._12 = vecUp.x;
matView._22 = vecUp.y;
matView._32 = vecUp.z;

matView._13 = vecLook.x;
matView._23 = vecLook.y;
matView._33 = vecLook.z;

matView._41 =- D3DXVec3Dot( &vecPosition , &vecRight );
matView._42 =- D3DXVec3Dot( &vecPosition , &vecUp );
matView._43 =- D3DXVec3Dot( &vecPosition , &vecLook );


}

class CModel{
D3DXVECTOR3 GetRight(){return vRight;};
D3DXVECTOR3 GetUp(){return vUp;};
D3DXVECTOR3 GetLook() {return vLook;};
D3DXVECTOR3 GetPosition(){return vPos;};

};
[/source]

My source code you can download http://www.rapidshare.ru/2665660
Windows programming is like going to the dentist: You know it’s good for you, but no one likes doing it.- Andre LaMothe.
You must to use the [font="Consolas"][font="Consolas"]

[/font][/font][font="Consolas"][font="Consolas"] [/font][/font][font="Consolas"][color="#2b91af"][font="Consolas"][color="#2b91af"][font="Consolas"][color="#2b91af"]Matrix[/font][/font][/font][font="Consolas"][font="Consolas"].CreateLookAt(where I am , where I want to look , My vector up );
Simply in your "where I am" vector3 put the offset respect to the player.
In your "where I want to look" vector 3 put the target.
In your "My Vector up" put Vector3.Up value(it is not truth but you can use it by now).

With this you are attaching a camera to a player.You have to apply the matrix to a object view matrix(don´t forget it).This is not a good camerafor games,is a rigid camera,for fix it you must interpolate your position with a desired position and you have to interpolate the rotation also.Get examples from xna page,look for chase camera sample.This is the best sample in internet to xna cameras but it not interpolate his rotation,if you interpolate the rotation then the camera be a good camera.
Is a physic camera with a spring.Set correctly the damping and stiffness values for you world dimensions and displacement units.
Not is the same a world in a squared meter that a world in a squared km.This is the link for the sample:
http://create.msdn.com/en-US/education/catalog/sample/chasecamera

I hope to be helful.
Bye!!!

[/font][/font]


The problem:
I am trying to create a 3rd person camera that will rotate around the character at X,Y,Z coordinates. But I am uncertain of how to accomplish this.

Thanks,


just set the Target vector as the X Y Z position you want the camera to face :)


Also it is in C# :) I know... I should be using C++


there is nothing wrong with using C#
the automatice garbage collector can be a bit of a pain for you, but there is a way to suppress automatice garbage collection on a object, coincidentally i cant remember how to do that at this time and moment.

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

Hi Aaron,

Basically what you need to do is the same for ANY object you need to rotate around a point. This is accomplished by moving your object in such a way that the pivot point (in your case the character) is at the origin when you are rotating. Basically you do this:

  1. Translate object with object.position - pivot
  2. Rotate object with your rotation (position transformation can be included in this operation)
  3. Tranlate object back with object.position - pivot

As others here have suggested you might also want to do other fancy things as making camera bobbing/smooth movement, but as long as you rotate the camera in its local coordinate system, with the steps I posted it will at least be focused on your pivot point.

Also, there is no problem at all in using C#. It is merely different from C++, but it is not inherintly worse. Fyi ryan, I think you might be talking about GC.SuppressFinalize.
G,day all,
I know that this is sort of an old topic, but I have been very busy at school with exams and my computer crashed. I have lost a lot of knowledge about all of this and have just started construction of my DirectX adventures again. Now I have it to the point were I have the character loaded (.X file) and have the camera positioned so that the Camera is looking behind and down on the mesh. Now I just need to clarify some things with you. In order to get a simple 3rd person camera operating, I need to move the character to the origin {0,0,0} and rotate the camera around it to X amount and then send it back to the old position? But wont this make the scene objects (buildings ect) move as well, I mean say the character was at {100,0,200} and then I move him to {0,0,0} wont this make me watch it as he travels to the origin?

Hi Aaron,

Basically what you need to do is the same for ANY object you need to rotate around a point. This is accomplished by moving your object in such a way that the pivot point (in your case the character) is at the origin when you are rotating. Basically you do this:

  1. Translate object with object.position - pivot
  2. Rotate object with your rotation (position transformation can be included in this operation)
  3. Tranlate object back with object.position - pivot

As others here have suggested you might also want to do other fancy things as making camera bobbing/smooth movement, but as long as you rotate the camera in its local coordinate system, with the steps I posted it will at least be focused on your pivot point.

Also, there is no problem at all in using C#. It is merely different from C++, but it is not inherintly worse. Fyi ryan, I think you might be talking about GC.SuppressFinalize.


I am trying your way and this is what I've got for when I press < arrow.


public void mRotateCamera(float angle,float speed, dev.Device d)
{
Vector3 old = cha.position;
cha.position = new Vector3(0, 0, 0);
d.Transform.World = Matrix.RotationY(10);
cha.position = old;
}


This will not work, It wont rotate the camera around the Y axe.

It just stays at {old}
Anyone?

This topic is closed to new replies.

Advertisement