Jump to content

Home

Rotating player view


Fardreamer

Recommended Posts

How would I set about changing the player's view angle (to face a certain point) using existing functions in q_math.c? I'm having a little trouble understanding the angle/vector relationship used in q_math. The basic idea I'm after is rotating the forward vector of the player around the Z axis (the one pointing away from the ground) by the angle between the player's forward vector and the vector connecting the player's origin to the point in question. Simple math, but what functions do I use for that?

 

Any help here would be hot :)

 

-Fard

Link to comment
Share on other sites

First of all, you can take out the _ from VectorSubtract, it works fine without it.

 

Second of all, are you sure that those are the only arguments for vectoangles? I think there are more arguments... I could be wrong though.

 

Other than that, it should work - you're trying to get the player to face the person he is dueling?

Link to comment
Share on other sites

Yes, Commodus, that's what I'm trying to do... but those lines don't work, even though I double checked their parameters and usage. Concerning what wudan said, I guess it depends on whether entity->client->ps.viewangles is set for reference only after the view is calculated in cg_view.c, or whether it's the angle cg_view.c uses to update the view... if it's the former, then obviously these lines won't work, but otherwise they should do fine... ?

Link to comment
Share on other sites

As I thought the ps.viewangles is not used by the view updating method, but rather is set after the view is updated... meaning that my code sets the correct angle to ps.viewangles, but doesn't do anything else. I'll have to try a different approach.

 

Changing cgThirdPersonAngle isn't what I want... I want the player to actually point to the direction, not only the camera... although the effect might be interesting.

Link to comment
Share on other sites

Well, apperently the only way to do it would be to run something in Pmove() (modifying playerState_t outside of Pmove causes prediction errors and simply doesn't work), but since there is no access to gentity_t or gclient_t in files that work for both client and server games (such as bg_pmove) there is no way for me to access anyh of the client and entity members I need for retrieving vectors. Phooey.

 

The only struct that exists in g_ and bg_ is playerState_t but I can't modify it (that's what it says in q_shared.h).

 

 

Ideas, for the love of the Force!

Link to comment
Share on other sites

[yoda]Hard to do, this is.[/yoda]

 

It'll be tough - so you want the client to lose his ability to rotate himself, and have his rotation be relative to his oponent? (basically, if 2 clients are duelling, and one stands still, and the other strafes, the strafe-client should, in essence, be revolving around the stationary-client? Like the earth around the sund?

Link to comment
Share on other sites

Look up polar coordinates on google for a background on this.

 

For a circle traced on the XY plane,

x = r * cos( theta )

and

y = r * sin( theta )

 

where r is the radius of the circle, and, theta is the angle between 1) the vector starting at the origin of the circle pointing to the current point on the circles edge and 2) the vector starting at the origin and pointing along the positive X axis (x = r * 1, y = 0).

 

Using this, whenever you are locked onto an opponent, his origin is going to be the origin of the circle you want to be moving on the outer edge of. The distance between your origin and his origin is the radius of this circle. To find theta (which you need to do when you first lock onto the opponent), use the definition of the dot product.

 

V and U are vectors.

 

v . u = ||v|| * ||u|| * cos(theta)

thus,

theta = acos( (v . u) / (||v|| * ||u||) ).

 

Now you have the equation that will trace out the circle.

 

To make sure you actually move in this circle, you need to modify the way the strafeleft and straferight keys work. Using the equations for X and Y above, if I increase theta, I start moving around the circle in the counterclockwise direction. Then, obviously, if I decrease theta I will move in the clockwise direction. So your strafeleft and straferight keys will just modify theta.

 

You also want to be able to move closer to your opponent. So, you need a way to change the radius of the circle. There are two ways to do this. You can create "movecloser" and "movefurther" commands, which will just decrease or increase r in the equations above. Or, you can do it another, perhaps, cleaner way.

 

Logic dictates that if youre facing the opponent, by pressing forward, you will move closer to him, thus effectively decreasing your radius. So, since this is easy and doesnt require you to change anything in the +forward or +backwards commands, you probably want to do this. But, to do this, you need to be facing your opponent. This is pretty easy. What you want is a vector pointing in the direction of your opponents origin from your origin.

 

If your opponents origin was vector A, and your origin was vector B, you want to find a vector C such that

 

C = A - B.

 

Then you can normalize vector C and use vectoangles to set it to your viewangles. This should probably be done every frame while youre locked onto your opponent.

 

I hope this clears some things up for you. It is not a literal solution to your problems though (because while moving around the circle, you might pass through a wall or be floating on top of a gorge), so you might have to add additional checks to make sure it works properly. But this should be a sufficient step in the right direction.

 

Keep us posted on your progress.

 

EDIT: I made a mistake.

 

Lets say the x coordinate of your locked opponent is X0 and the y coordinate is Y0. Then the new equations for the circle are:

 

X = X0 + r*cos(theta)

and

Y = Y0 + r*sin(theta).

Link to comment
Share on other sites

It just occurred to me how much I was overcomplicating the implementation for this. Blame me for being a math head :).

 

All you really need to do is make the players face each other every frame. Then, if you strafe, since youre always changing the direction youre facing to face your opponent, youre automagcally going to be tracing out a circle. It cant be any easier than that.

 

So, yeah, just like before... B is your origin, A is your opponents, and C is the direction facing your opponent.

 

C = A - B.

 

Normalize C and use vectoangles to find the angles that will face you towards your opponent. Then just use those to orient your player. Its been a while since I've worked with q3 or jedi knight ii, but I'm sure you have to do this in bg_pmove somewhere.

 

Sorry I couldnt be more specific with the bg_pmove stuff, but its been a while (and I'm on vacation right now so dont expect me to go look it up :) ). Im sure one of the regulars here will be able to help you out.

Link to comment
Share on other sites

[yoda]Learned in the ways of Vector Math, he is.[/yoda]

 

I too have been looking for a way to do this, and have a few ideas. He is correct on the viewangles thing, that's kind of what I came here to say. I've also begun documenting some of the q_math.c functions, mostly so that I know what the hell I'm doing, I've read them before, but documenting them has taught me more.

 

http://users.sisna.com/tokyopop/vectors.html

 

I still haven't documented vector angles, or thought up a way to make the player 'lock-on' to another player, but I plan on it ;)

Link to comment
Share on other sites

Wow, thanks for that detailed first post skew, though it's more complex than needed :D Since every frame I'll be reorienting my clients their strafe keys will in fact automatically move them in a circle. So as you said in your second post, all I need to do is calculate the new forward vector the client will be using - a simple vector substitution (and I don't really have to normalize it because I'm not using it's magnitude) -and then just convert this vector to angles (angles being the way orientation is implemented in Q3).

 

The two lines of code I put in my second post do the job fine - I checked their results. I actually understood the q_math functions after my first post, so the question here has changed :o (silly me). Where I really need help is in applying this new angle, something I'm not succeeding in doing because I'm not quite sure where in bg_pmove the client's new angle is being calculated and set to ps->viewangles. The closest I got was the function PM_UpdateViewAngles, but I think it only calculates the camera angle and not the physical orientation of the client model; although maybe the physical orientation is simply taken from the camera orientation?... I have no clue :confused: I gotta do somemore research.

 

If you feel like putting your vector skills at work you could help me out on a different problem which I forgot the solution to... I want to know whether a given point in space is to the left of the client or to his right. For example (using a left-handed co-ordinate system), if my client is positioned at (0 0 0) and his forward vector (direction he's pointing to) is (0 1 0) (along the y axis) then all points that have a positive x value are to the right, negative x to the left. I seem to remember I have to use the cross product of the normalized vector with another vector but I forgot what that other vector is... any help?

Link to comment
Share on other sites

Physical orientation isn't taken from camera angles, it's the other way around. If it were me, I'd rather the camera angle be the one that get's fixed on the other player, rather than it be the other way around.

 

Are you planning this for duel only, or will the player be able to point and lock their camera?

Link to comment
Share on other sites

I haven't really decided on that yet... but the idea is similar to Z-targetting from Zelda64, target locking in Rune, etc.: Constantly face your target so that you don't have to worry about aiming, just striking/blocking at the right time. I want both the camera AND the player model to face the target, just as though the client actually moved the mouse. I never thought it would be so complicated... :(

Link to comment
Share on other sites

Fardreamer,

 

The left / right checking is pretty simple. Its using component projection (or scalar projection, depending on what nomenclature you were taught). Instead of using the forward vector, we'll use the right vector, for simplicity's sake.

 

Lets say your right vector is R. Now, to demonstrate how this works, lets deliberately pick a point thats on your right. We'll call the vector from your origin to this point vector A. Now pick a point on your left side. The vector from your origin to this point is vector B. Now you want to mathematically prove whether or not these points are on your left or right (in relation to your right vector). Use the component projection.

 

The component projection of A onto R is:

 

comp_R_A = (R . A) / ||R||.

 

What this is going to show you is the component of A in the direction of R. Since A points towards your right (and somewhat in the direction of your R vector), the component projection of A onto R will be positive. Thus, the endpoint of vector A is on your right.

 

Now, if you tried doing the component projection of vector B onto R, logically you'd assume that since B is going in the opposite direction of R, your component projection would be negative. And that indeed is the case. Thus, the endpoint of vector B is on your left.

 

Thats all there is to it.

 

To recap,

1) get a vector R

2) get a vector from your origin to the arbitrary point and call it something (vector V)

3) project V onto R

4) if positive, point is on your right. if negative, point is on your left.

 

One thing you might want to keep in mind is discarding the Z coordinate of these vectors when doing this. If your R vector pointed upwards slightly and the point youre checking is below you AND to your right, you will probably still get a negative component projection. And thats not what you want :).

 

I hope this helps. If you need anythign else, I'll be around checking this thread. Good luck.

 

EDIT: I accidentally made a typo in the equation for the component projection in my first post.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...