Game Development Community

Vector math for anti-grav with direction

by Chris Cain · in Torque Game Engine · 01/06/2009 (11:51 am) · 23 replies

I sure hope I don't fudge up with the explanation of my problem...

First of all, I'd like to say that I think this would probably be better placed in the Mathematics section, but I put it here in case I need to post C++ source to diagnose problems.

Alright, I'm making a booster that resists gravity, then propels a player into the direction they are pointing. The catch is that there is a maximum force that the booster can propel, and it won't exceed that force... so I'm trying to figure out how to do this.

I wouldn't mind being pointed in the right direction instead of having my hand held ;) ... just keep in mind, I don't have a great grasp on vectors just yet.

So, here's a couple of images to help illustrate what I'm trying to do (and how I've pictured it in my head on how I might be able to solve it.)

e.imagehost.org/0692/Pt1.jpg
In this picture, gravity is defined as -20, the force the booster can output is 90. The vector marked as "x" is the direction that the player is facing. I figured I could just use vector projection at this point...

But...

e.imagehost.org/0730/pt2.jpg
This is an image that shows when a player aims a bit up. Vector projection wouldn't provide the correct vector then. Also, this vector is overall shorter compared to the other one (which makes sense, if you're pointing up, it should provide less net-acceleration because you're fighting gravity). So, I figured if I found out the x and z values necessary, then that'd work. But, that wouldn't translate very well into 3d. So in the end, I really just need an algorithm to figure out the scale needed for a vector... then all I'd need to do is take the eye vector from the player and scale it appropriately.


I'm coding all of this into updateMove, just for your information.


Thanks for any help you can give me.
Page «Previous 1 2
#1
01/06/2009 (1:54 pm)
Let me see if i understand the problem.

you want to generate a thrust vector of maximum magnitude (90) which
A) exactly cancels gravity (-20) and B) moves the player along some vector.

i assume that you want the player's altitude to change for non-horizontal forward vector ?

G = gravity vector [Gx, Gy]
F = forward vector [Fx, Fy]
T = the final thrust vector; what we're trying to find.
t = magnitude of final thrust


let's construct T as:
T = -G + kF,
where k is a scalar we'll solve for:

Tx = -Gx + k*Fx
Ty = -Gy + k*Fy

now, you know that Tx^2 + Ty^2 = t^2, so:

(-Gx + k*Fx)^2 + (-Gy + k*Fy)^2 = t^2

expanding:

(Gx^2 - 2*k*Gx*Fx + k^2*Fx^2) + (Gy^2 - 2*k*Gy*Fy + k^2*Fy^2) = t^2

to solve for k, we collate terms according to k and bring the t^2 over.

k^2*(Fx^2 + Fy^2) + k*(-2*Gx*Fx - 2*Gy*Fy) + Gx^2 + Gy^2 - t^2 = 0.

perfect!
now the only unknown in the equation above is k,
and the equation is of the form a*k^2 + b*k + c = 0,
and you can use the quadratic equation: k = [-b +/- sqrt(b^2 - 4*a*c)] / 2a.

this will give you two answers for k, which thus gives you two answers for T = -G + kF.
probably one of the answers will be negative, and you naturally want the positive one.

hope that helps!
#2
01/06/2009 (2:58 pm)
I think that'll work. I'll just need to change it to 3 dimensions. If I have any trouble, I'll let you know!

Thank you very much for your help :)
#3
01/07/2009 (9:08 am)
This is probably an unhelpful suggestion. I would have taken the desired movement vector, x, subtracted the gravity vector (subtract -20 z, in this case), and normalized to 90 units in length.
#4
01/07/2009 (9:44 am)
That was my initial thought as well Daniel, but consider a simple case
where the desired movement vector is horizontal (ie perpendicular to gravity).

say gravity = [0, -20], desired movement direction = [1, 0].

-gravity + movement = [1, 20],
which when normalized to length 90 will be about [4.5, 89.9],
which has almost 90 units of force vertically, so you will go zooming up.

what you want is something which would look more like [, 20],
where ^2 + 20^2 = 90^2, so about [87.8, 20].

the above math is just a generalization of the situation for when gravity may not be perfectly vertical (eg perhaps there's some wind) and your desired move direction may not be perpendicular to gravity.
#5
01/08/2009 (8:08 am)
Okay, assuming the desired movement direction is a normal vector, then that is true. However, if desired movement is represented as a vector with the magnitude of the vehicle's maximum speed, this method would work more properly, no?

In the case above, if our desied movement direction was [1, 0] then we would normalize that to 90 units, assuming 90 is our movement speed.
Movement - gravity = [90, 20] which we normalize, and it becomes nearer horizontal.

Actually, I just realised the problem in this method is that the z component after normalisation will be less than 20. So if you're trying to move forwards, there will be less acceleration countering gravity, so you'll sink.

Yep, your method works better ;P
#6
01/08/2009 (9:08 am)
Right,
you know the final thrust vector has to have a vertical component of 20 or else the player will either rise or sink, and you also know it has to have magnitude 90, so it's a perfect setup for the pythagorean theorem.

someday i want to have a theorem. "the elenzillian theorem", nice ring !
"the buckmaster mechanism", "cain's generator", etc.

my favorite real one is "the sieve of eratosthenes".

.. wow, ot
#7
01/08/2009 (9:37 am)
Pythagorean theorem only works with 90 degrees, unfortunately :-p

I wish it was that easy :(
#9
01/08/2009 (10:43 am)
Orion, what's that mean exactly? :-p

I think I have the answer... but another problem arises... but first, the answer to my original question:

e.imagehost.org/0397/pt3.jpg(The increase in quality is brought to you by Inkscape. Thank goodness for free vector drawing software :-p)

Alright, we are given A, a, and b, and our goal is to find c. Thus, I present to you with great honor, Cain's Generator:

Find B:
Sin B = (b sinA)/a
thus B = Sin^-1( (b sinA)/a )

Find C:
if in degrees:
C = 180 - (A + B)
in radians:
C = PI - (A + B)

Find c:
c = (a sin C) / (sin A)

Congrats, we have it!

However, after doing all this work, digging out trig from the depths of my brain, I tried this out just to realize that the controls just aren't working for me. The problem is that I have to compensate too much for the player's speed, when all I want is to just point straight and go.

So, now, I have an additional smackdown to add to the problem (and, thus, invalidating most of the other work): Now we have to compensate for velocity! The problem has become a bit more complex. Before, it was absolutely sufficient to solve for just 2d and use the scale we found to simply scale a vector (very very easy in the end). But since Velocity is 3D, we have to work on the method in 3 dimensions. I think the problem can be broken down into 2 2D problems... but maybe there's a better way? You tell me if you have any ideas.

I'll post if I come up with anything.
#10
01/08/2009 (10:47 am)
I'm not sure i entirely follow,
but one approach would be to rotate the situation so that the velocity vector is in some convenient plane (like XZ or whatever), then do the 2D business, then unrotate back.
#11
01/08/2009 (11:28 am)
Basically, the problem is that when I'm flying the player around, and I make a turn, the player keeps going in the direction he was (inertia) ... so, as the controller of the player, I have to compensate (turning the character a bit harder than I initially want) in order to get the player to go where I want him to go. This leads to various difficult situations (such as, I'm going very fast, and I'm about to hit the ground, so I have to look straight up at the sky not to crash and burn, instead of looking where I want to go, for instance)...

so, basically, I want the thrust to direct the player to where he wants to go, instead of just thrusting in the direction he wants to go.

So...

Now I have a totally new problem. :-\ Now I get to confuse the heck out of you because I've changed my mind on how I want the system to work :-p

The vector that the thrust vector comes out of is velocity + gravity added.

Case 1: Player requests 100% of his total thrust (110 units of force) and can meet the requested direction with the amount of thrust his booster can output:

e.imagehost.org/0837/inertia_correction_1.jpg
Case 2: Player requests 100% of his total thrust (110 units of force) but can't meet the requested direction... so it does the best it can. (note, the thrust vector is perpendicular to the requested direction vector)

e.imagehost.org/0582/inertia_correction_2.jpg
Case 3: Player requests an arbitrary amount of his total thrust (such as 50%, 55 units of force) and can meet the requested direction with the amount of requested thrust:

e.imagehost.org/0489/inertia_correction_3.jpg
Case 4: Player requests a low amount of his total thrust (such as 10%, 11 units of force) but can't meet the requested direction with the requested thrust:

e.imagehost.org/0380/inertia_correction_4.jpg
#12
01/08/2009 (1:14 pm)
Whoah, now I'm lost :P. Nice catch in the Pythagorean rules only being for right-angled triangles :P. But can't you just assume the triangle is right-angled? Take your second original diagram - you're looking for the vector with length 90. It equals desired direction - gravity. However, you have a right-angled triangle made between the bottom-most point, the point [0, z] and the right-most point.

So now, I'm given to understand, you want to cancel current velocity as well as gravity. Now you have the problem that you know the acceleration due to gravity, but the velocity due to... velocity. Dare I suggest that you just say
Desired thrust = desired direction - gravity - current velocity?
I'm just taking that from the top of my head, here.

By the way, vectors should work equally well in 2 and 3 dimensions. There might be a little additional complexity added, but if you can come up with a good general solution involving dot and vector products, it should be equally applicable to 2D and 3D, right?
#13
01/08/2009 (1:33 pm)
Yeah, I had to think on that for a few... after I remembered that, I was like "aw, this isn't going to work :("

I'm not sure where you're going with your suggestion, though. I guess I don't see what you're describing. Sorry.


Yeah, I want to cancel current velocity and gravity... my hope is that it would make handling a flying player significantly easier (and therefore more fun, hopefully... that said, it was a blast flying around with the physic model described above :-p).

Vector subtraction could work, if I could work out where the direction vector should be and then I simply scale the thrust vector, I guess.

I'm thinking so. The solution for my previous problem actually doesn't need any tweaking to work in 3D. I solve for c via that 2D method and apply a simple scale to the normalized directional vector, and poof, it works.

Of course, that was mostly due to the fact that gravity is always downward... so that made it easy. Since velocity can go anywhere, in the end, you'll either have to solve 2 2D problems (such as XZ and XY, or some other combination) or just do 3D math (which I'm thinking is the best bet, in the end).

Right now, I'm playing around with various things on MathWorld's website to see if I see anything that could help me solve the problem. Sometimes things just click when you see it working :-p
#14
01/08/2009 (2:36 pm)
Chris,
you've come up against a fundamental issue here:
Quote:I want to cancel current velocity and gravity
you are applying a force, which is good for canceling gravity, because gravity is a force, but velocity is not a force, so you have to come up with some creative method of navigation control.

if it were me, my first approach might be something like:
* create a "compensating velocity" = desiredVelocity + K * (desiredVelocity - currentVelocity),
where K is some scalar. if K is 0 you have exactly the situation described in your post of 11:28, above.
* determine the thrust vector needed to cancel gravity and have the remaining thrust be along the compensated velocity vector via the method you're using in that same 11:28 post.

then tweak K until it feels right.
#15
01/08/2009 (3:17 pm)
I guess I'm messing up how to explain what I'm doing...

In player.cc, the current velocity is held in mVelocity, a vector.

So, basically, I'm trying to apply my thrust to align mVelocity with my desired direction. When mVelocity's direction = my desired direction, then the thrust is basically being applied 100% to my desired direction.

The pictures are to describe the various possible situations, so that you kind of see what I want the algorithm to do.

I guess I could impliment a "desired velocity" potentially... but right now, I want to see if I can make it so the player controls the thrust and a desired direction...
#16
01/08/2009 (4:02 pm)
Right,
mVelocity is the current velocity,
and you want to change it to be parallel with say desiredDirection.
you could just apply thrust in desiredDirection,
but as you've discovered, it takes a while for mVelocity to line up with desiredDirection.
i'm suggesting that you should apply thrust in a third direction, compensatedDirection,
which should bring mVelocity into alignment with desiredDirection somewhat faster.

there's certainly an art to making this sort of stuff "feel" right to the user.
fun!
#17
01/08/2009 (7:52 pm)
I think see what you mean. Basically, you use compensatedDirection as the vector to apply thrust along... and desiredDirection would be between compensatedDirection and Velocity... so, that would bring Velocity to desiredDirection faster. Correct? I think it sounds like a pretty good idea

How would I get that compensatedDirection?
#18
01/09/2009 (7:59 am)
If you want to be really simple, just make it the opposite of velocity times some factor. That will cancel velocity in that direction. However, you'll end up fighting yourself when thrust alters valocity to be the direction you want it. So I'd suggest getting normal vectors in the direction of thrust and current velocity, and using the dot product to find how parallel they are. If they're bang on, then you don't need to do anything. As they become less and less parallel, apply more and more force in the opposite direction to cancel velocity in that direction. Then you apply the thrust in the direction you want to go.
#19
01/09/2009 (8:16 am)
Sounds like a good idea to me.

Thanks :D


Now if only Torque had the player rotate with quats... the next part of my engine modification process could be so much simpler. Wouldn't you say? :-p
#20
01/09/2009 (8:26 am)
K * -Velocity is certainly an interesting idea to try,
assuming you add in some amount of desiredDirection or else you'll never approach it.

my suggestion would be

compendatedDirection = desiredDirection + K * (desiredDirection - currentDirection),
where K is somewhere between maybe .5 and 4 or something.
Page «Previous 1 2