Switching To Third Person

Sage
Posts: 1,066
Joined: 2004.07
Post: #1
I'm trying to figure out how to properly make a third person camera out of my current camera. It already has the capabilities (i.e. a function that rotates it around a point) but I can't figure out how to get the "look" right. It's going to be a third person shooter in similar fashion to Grand Theft Auto or Mafia or Driver 3.

I'm not sure if the code is necessary so I'll refrain. Let me know if I should post it. I'm mainly concerned with where the camera should be positioned, how it's position relates to the player, and where it points. Thanks for any help.
Quote this message in a reply
Member
Posts: 338
Joined: 2004.07
Post: #2
Threw some keywords into google (it's your friend, abuse it) and came up with this quick writeup.

It's the bare basics (doesn't account for obstructions or anything) but it should get you started. In a nutshell, take the camera you have now, and move it up & back (relative to player position and heading), and aim it at the player.

Justin Ficarrotta
http://www.justinfic.com
"It is better to be The Man than to work for The Man." - Alexander Seropian
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #3
I've been trying things out and just can't get it even working right. The idea: I want a third person view that switches to first person when the player zooms in with a gun.

If anyone can help, IM or email me and I can send my Camera and Player class files to you. I just need some help making this all happen.
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #4
In a previous project, where I used Shockwave 3D exclusively, I had a smilar problem. What I did was create 2 camera objects, and when I had to switch from one to the other I just transposed the movement and made a camera the current one.

I don't know if this is possible in OpenGL. If it isn't, then what you could do is have 2 invisible points that you could use as targets for your camera position.

Ofcourse this is pure theoretical, I'm really the last person to ask for help when it comes to 3D programming Rasp

"When you dream, there are no rules..."
Quote this message in a reply
Moderator
Posts: 508
Joined: 2002.09
Post: #5
Hmm, rereading your post, the text I wrote above didn't quite answer your question. My apologies.

I would edit it, but I can't find the edit button. Oh well...

"When you dream, there are no rules..."
Quote this message in a reply
Member
Posts: 153
Joined: 2004.12
Post: #6
I would create two camera classes and switch between them. There are about a million camera class tutorials out there so i wont go into the details.

to answer the second part of your question: I read somewhere that the key to doing 'zoom' is to change the FOV, im not exactly sure what the right values are but im sure a little experimentation will answer that quickly.

There was a long silence...
'I claim them all,' said the Savage at last.
Quote this message in a reply
Sage
Posts: 1,199
Joined: 2004.10
Post: #7
I agree with Taxxodium here

In my situation I'm writing a 3rd person driving game, where you can switch from a driving view ( 3rd person ) to a gunnery/turret view ( I guess 1st person ). I maintain one camera, but I have different positioning rules, using object-relative transformations.

E.g., for the driving view I have the camera positioned backwards by about 5 meters and up a couple, looking towards a point about 100 meters in front of the car.

When you switch to first person, the camera is positioned to the left of the barrel by one meter, and looks in the same direction as the gun.

When you switch between the views I "tween" between the positioning for one view to the next, to give a smooth "swooping" effect, which is cool.
Quote this message in a reply
tigakub
Unregistered
 
Post: #8
Are you using gluLookAt. If not use it. I assume you have some kind of transform hierarchy. To use gluLookAt, you need the global position of your view point, the global position of the point you're looking at, and the up vector, which can be obtained by subtracting the view point from a point 1 unit directly above it. Let's say you have a view hierarchy as follows.

Code:
MainNode
  |
  |- NodeA // Your player
     |
     |- NodeB // Your player's head
        |
        |- NodeC // A point somewhere behind the player's head
           |
           |- NodeD // A point directly above it -- i.e. ( 0, 1, 0 ) relative to NodeC

To find the global position of NodeC and NodeD (which correspond to the camera's position and the up point of the camera).

Code:
GLenum tOldMode;
glGetIntegerv(GL_MATRIX_MODE, &tOldMode); // Save this to restore the mode when
  // you're done. This is so that you can basically call this code from anywhere
  // without messing up your scene.

glMatrixMode(GL_MODELVIEW);
glPushMatrix(); // To save the current model view matrix so you don't screw up your scene
glLoadIdentity(); // Load the identity matrix -- i.e. a fresh model view transformation matrix

// You've probably got these transforms in some kind of class structure which you
// iterate through or recurse through.

glTranslate(NodeA's position); // Apply NodeA's transformations
glRotate(NodeA's rotation);
glScale(NodeA's scaling);

glTranslate(NodeB's position); // Apply NodeB's transformations
glRotate(NodeB's rotation);
glScale(NodeB's scaling);

glTranslate(NodeC's position); // Apply NodeC's transformations
glRotate(NodeC's rotation);
glScale(NodeC's scaling);

// The global position of NodeC is now in positions 12 through 14 of the model view matrix.
// And we can retrieve that like this:
GLfloat tMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, tMatrix);
GLfloat tCameraPosition[3];
tCameraPosition[0] = tMatrix[12];
tCameraPosition[1] = tMatrix[13];
tCameraPosition[2] = tMatrix[14];

// The model view matrix has not changed and can be the basis to find the global
// position of NodeD.
glTranslate(NodeD's position); // Apply NodeD's transformations
glRotate(NodeD's rotation);
glScale(NodeD's scaling);

glGetFloatv(GL_MODELVIEW_MATRIX, tMatrix);
GLfloat tCameraUpVector[3];
tCameraUpVector[0] = tMatrix[12] - tCameraPosition[0];
tCameraUpVector[1] = tMatrix[13] - tCameraPosition[1];
tCameraUpVector[2] = tMatrix[14] - tCameraPosition[2];

glPopMatrix(); // Restore your scene's model view matrix

glMatrixMode(tOldMode); // Restore the current matrix mode

You can use a similar method to get the global position of the camera's target point.

So you can then use gluLookAt:

Code:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(tFOV, tAspect, tNear, tFar);
gluLookAt(tCameraPosition[0],tCameraPosition[1],tCameraPosition[2]
  tTargetPosition[0],tTargetPosition[1],tTargetPosition[2],
  tCameraUpVector[0],tCameraUpVector[1],tCameraUpVector[2]);
glMatrixMode(GL_MODELVIEW);
.
.
.

I typically put this code in my camera class and have three pointers in my camera class, one that points to the position node, one to an up node, and one to the target node. This way I can simply swap pointers to attach the camera to different objects.
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #9
Thanks for all the help. My camera is working fine now. I'm going to add some 'effects' to it later but the basics all work. Now I get to figure out how to get the character to rotate based on the mouse movement.
Quote this message in a reply
lpetrich
Unregistered
 
Post: #10
The trick I used in Aleph One, http://source.bungie.org was to calculate the position in three steps.

The first step was to find a target position -- a camera position offset from the player character's position. This I will call xt.

The next step was to give the camera some inertia, so it does not seem fixed on a pole. In Aleph One, I did that by doing a crude ordinary-differential-equation solution. The current value, x, I found from its two most recent values, x1 and x2 with:

x = (1 + c1 + c2)*xt - 2*c1*x1 - c2*x2

where c1 and c2 are constants that express the camera's inertia. Be careful about choices of c1 and c2, because the camera's position can become unstable with incorrect values. I'll defer discussion of that to the end of this message, because it is a bit long and technical.

The final step was to ensure that the camera will not go through walls. This was done by using the Marathon engine's projectile-motion code, moving the camera from the player-character position to x, and stopping if the camera hit a wall. This step also ensured that the camera would be in the proper map polygon to get the visibility calculations right.

How the camera behaves can be calculated by plugging in an ansatz or guessed partial solution for the camera's free motion:

x = w^2*x0
x1 = w*x0
x2 = x0

where x0 is an integration constant and the size of w determines the camera's behavior. If its absolute value is less than 1, it is stable, and the closer it gets to 1, the more borderline its stability becomes. An absolute value greater than 1 means instability. We can find w by plugging the x's into the above equation and ignoring xt:

w^2 +2*c1*w + c2 = 0

yielding w = - c1 +/- sqrt(c1^2 - c2)

If c2 < c1^2, then the camera will be overdamped. The stability condition becomes sqrt(c1^2 - c2) < 1 - |c1|, or c2 > 2*|c1| - 1.

But if c2 > c1^2, then the camera will oscillate. since the square root becomes imaginary: w = - c1 +/- i*sqrt(c2 - c1^2). In that case, c2 < 1 for stability.

If the camera is to have relatively noticeable inertia, then you will want it to have values of w close to 1. This means that c1 must be close to -1 and c2 close to 1. It might take some experimentation to find values of c1 and c2 that give nice-looking camera behavior, however.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  First Person Shooter Nick 14 6,772 Mar 19, 2005 04:26 PM
Last Post: Frank C.
  Camera Following Object (3rd Person Perspective) squidgee 1 2,874 Nov 30, 2003 11:58 AM
Last Post: ERaZer