0
101 Mar 17, 2009 at 15:59

I’m new here and I hope this is something that is easy to answer.

I have a sun and planets, the planets orbit the sun with gravity. the player can orbit both the sun or planets or depending on the trajectory a combination of many. but i will just use the sun, now the sun is set in some x,y,z place.

sun(x,y,z)
player(x,y,z)

the gravity from the sun to the player works on velocities that effect the x,y,z of the player and are calculated as xv,yv,zv

player(x-xv,y-yv,z-zv) and would update player(x,y,z) with the new coordinates

this part works.

i also have the player velocities: player(pxv,pyv,pzv)
and there are player angles: Player(pitch,yaw,roll)
and the player moves by combining them. This works as well.

Now my problem, I cannot figure out how to alter the xv,yv,zv and the player(pxv,pyv,pzv):Player(pitch,yaw,roll) into a harmonious act.

example experienced: say the player is gravitating to the sun,and the player moves to the sun as well, when then i stop the velocity increase of the player the gravitating velocity does not change with the player’s velocity increase.

and it’s not just to the gravitating body, its in any direction. Any help would be great. Thank you.

#### 22 Replies

0
102 Mar 17, 2009 at 17:15

Try integrating accelerations (or better yet forces) to get velocities instead.

0
101 Mar 18, 2009 at 14:17

I suppose i should show the gravity code. basic/sudo code

;---------------------------CREATE GRAVITY---------------------------
;gravityforce                   - is a constant gravity value
;gravity_x#         - x axis point of source of gravity
;gravity_y#         - y axis point of source of gravity
;gravity_z#         - z axis point of source of gravity
;mass#              - combined mass of the objects
;surface_radius#    - radius of the source of gravity
;atmospheric_radius - radius of atmosphere , introducing drag
;effect_radius#     - radius of the gravitational effect
;MovingBody_x#      - x axis point of the effected object
;MovingBody_y#      - y axis point of the effected object
;MovingBody_z#      - z axis point of the effected object
;MovingVx#          - x axis velocity of the effected object
;MovingVy#          - y axis velocity of the effected object
;MovingVz#          - z axis velocity of the effected object
;NOTE: MovingVx#, MovingVy#,MovingVz# must be global and assigned outside of the function
;                          -----EXAMPLE-----
;MovingVx# = players_x_velocity#
;MovingVy# = players_y_velocity#
;MovingVz# = players_z_velocity#
;players_x_velocity# = MovingVx#
;players_y_velocity# = MovingVy#
;players_z_velocity# = MovingVz#
;                          ---END EXAMPLE---
;Or simply use MovingVx# And MovingVy# as your main x,y velocity variables for 2d gravity. (not tested)

sd# = Abs(Distance#(MovingBody_x#,MovingBody_y#,MovingBody_z#,gravity_x#,gravity_y#,Gravity_z#))

drag# = 1
If sd# <= Atmospheric_radius# Then drag# = .98
If sd# <= surface_radius# Then
MovingVx# =0
MovingVy# =0
MovingVz# =0
Return
EndIf
If sd# <= effect_radius# Then

XYa# = Angle#(gravity_x#,gravity_y#,MovingBody_x#,MovingBody_y#)
YZa# = Angle#(gravity_y#,Gravity_z#,MovingBody_y#,MovingBody_z#)
ZXa# = Angle#(Gravity_z#,gravity_x#,MovingBody_z#,MovingBody_x#)
MovingVx# = ((MovingVx#+(((Sin(XYa#)+Cos(ZXa#))* gravityforce*mass#))/sd#)*drag#)
MovingVy# = ((MovingVy#+(((Sin(YZa#)+Cos(XYa#))* gravityforce*mass#))/sd#)*drag#)
MovingVz# = ((MovingVz#+(((Sin(ZXa#)+Cos(YZa#))* gravityforce*mass#))/sd#)*drag#)
EndIf
End Function


so as the player gets closer to the source of gravity it accelerates and moves around the object (unless the player is headed basically straight at it). I thought i was using acceleration or forces but I’m probably wrong.

I guess another way of stating my issue is, I cannot coordinate independent angular accelerations/movements (player) with independent positioning accelerations/movements (gravity). I hope this helps define my problem a bit more. Thank you for helping.

0
101 Mar 18, 2009 at 15:22

ooh just noticed my gravity is a bit funked. hmm. maybe i just need help with that?
nvm I think i just fixed it. I still have my original problem though.

0
167 Mar 18, 2009 at 16:07

Please use …[/code[b][/b]] tags to post code; it keeps the formatting. [code]…[/code**] tags to post code; it keeps the formatting.

0
101 Mar 18, 2009 at 16:18

sorry, I forgot how to do that. Thank you.

0
101 Mar 19, 2009 at 14:15

I will be more descriptive. I have been working on this issue for many days now and cant get it right. So.. here it goes.

basic/sudo code:

;returns the angle of 2 points.
Function Angle#(x1#,y1#,x2#,y2#)
Return ((ATan2(x2# - x1#,y2# - y1#)+180) Mod 360)
End Function


I am using this to find the angle between the players(x,y,z) location and an invisible point in space that is always 5 steps in front of the player, no matter what angle/direction the player is facing. (if the point were visible, the player would always see it directly in front if them)

;Calculate gravity
MovingVx# = xv#
MovingVy# = yv#
MovingVz# = zv#
xv# = MovingVx#
yv# = MovingVy#
zv# = MovingVz#

;Set thrust, moving force.
thrust# = 0
if leftmouseclick = true then thrust# = .5

;Get angles
XYa# = Angle2#(player(x),player(y),invisiblepoint(x),invisiblepoint(y))
YZa# = Angle2#(player(y),player(z),invisiblepoint(y),invisiblepoint(z))
ZXa# = Angle2#(player(z),player(x),invisiblepoint(z),invisiblepoint(x))

;Get players velocity on above angle
player(pxv#) = ((Sin(XYa#)-Cos(ZXa#))* (thrust#))
player(pyv#) = ((Sin(YZa#)-Cos(XYa#))* (thrust#))
player(czv#) = ((Sin(ZXa#)-Cos(YZa#))* (thrust#))

;Add players velocity to gravitational velocity
xv# = xv#+player(pxv#)
yv# = yv#+player(pyv#)
zv# = zv#+player(pzv#)

;Update the players position
mx# = player(x)+xv#*timestep#
my# = player(y)+yv#*timestep#
mz# = player(z)+zv#*timestep#
Position player,mx#,my#,mz#


In theory the above should work(i think). But I’ve narrowed the problem down to getting my angles for the player incorrectly or used improperly for determining the velocity in the right direction. I said before that the player movement was working, it’s not. sorry about that.

0
101 Mar 19, 2009 at 15:50

I figured it out.. my problem was with my angle# function

;returns the angle of 2 points.
Function Angle#(x1#,y1#,x2#,y2#)
Return ((ATan2(x2# - x1#,y2# - y1#)+180) Mod 360)
End Function


should have been

;returns the angle of 2 points.
Function Angle2#(x1#,y1#,x2#,y2#)
Return ATan2(x2# - x1#,y2# - y1#)
End Function


Its weird though.. cause the first angle works for the gravity but not for player movement?? I am using both versions of the angle function now.
everything works how I envisioned it.
thank you

0
101 Mar 25, 2009 at 15:29

I’m still having problems. What i have above tends to jump around a lot and in some directions it will gravitate toward the sun but not directly to it until a certain angle is reached then it will. Basically it’s not accurately fallowing a gravitational path. I have some new code that gets better accuracy but it still just isn’t right. I am changing from the previous description of the problem to better fit the issue at hand. For this description I shall use player(x,y,z), an invisible point invP(x,y,z) that is 10 steps in front of the player(x,y,z) point ,and shot(xv,yv,zv) . I will reference the angle# function from above in the code.

In this description the player is firing a weapon. the player will always be at player(0,0,0) for this example. when the player fires the weapon the shot should appear directly in front of them (center of the screen) no matter what direction the player is facing. With the code below, pitch works fine, yaw is inverted (and i cant just swap key’s around cause i’m using a mouse for the player’s control) .

here’s what i got so far:

x#=Angle#(invP(y),invP(z),player(y),player(z)) //pitch
y#=Angle#(invP(x),invP(z),player(x),player(z)) //yaw
z#=Angle#(invP(x),invP(Y),player(x),player(y)) //roll

xv = 0     // x axis velocity
yv = 0     // y axis velocity
zv = 2     // z axis velocity

//roll
tx = ((Cos(z#) * xv) - (Sin(z#) * yv))
ty = ((Sin(z#) * xv) + (Cos(Z#) * yv))

//yaw
tx = ((Cos(y#) * xv) - (Sin(y#) * zv))
tz = ((Sin(y#) * xv) + (Cos(y#) * zv))

//pitch
tz = ((Cos(X#) * zv) - (Sin(x#) * yv))
ty = ((Sin(X#) * zv) + (Cos(x#) * yv))

shot(xv) = tx
shot(yv) = ty
shot(zv) = tz


I have looked everywhere online for tutorials and forums but none have anything that works completely. The above works for pitch and the ones from tutorials work for yaw, but not both. If you can please, please help.
Thank you.

0
167 Mar 25, 2009 at 17:09

If the yaw is inverted, can’t you just negate the angle to fix it?

0
101 Mar 25, 2009 at 17:53

Thats what i thought as well, but if i invert the yaw then both the pitch and yaw have a peek or dip at 90 and -90 degree’s.
if the player rotates on the yaw axis it looks like

v—-
where — is the rotation and v is the dip.

0
102 Mar 25, 2009 at 19:20

This code would be a lot easier to read and write if you incorporated vector and matrix math routines.

PLEASE ask the math question instead of pasting a bunch of code in some obscure language.

If all you want is where to put the shot then the answer is trivial. Subtract the player position from the imaginary point “10 steps in front of the player” and divide by 10 to get a normalized direction vector for the player. The location of the shot is then the distance in front of the player you want the shot to appear multiplied by the unit direction vector plus the player position – no trig functions required.

0
102 Mar 25, 2009 at 19:28

Also, you have a typo:

xv = 0     // x axis velocity
yv = 0     // y axis velocity <-- shouldn't that be a 1?
zv = 2     // z axis velocity

0
167 Mar 25, 2009 at 20:06

@paul0n0n

Thats what i thought as well, but if i invert the yaw then both the pitch and yaw have a peek or dip at 90 and -90 degree’s.
if the player rotates on the yaw axis it looks like

v—-
where — is the rotation and v is the dip.

Sounds like you’re having trouble with angles wrapping around and making the trig functions do unintended things. It’s not totally clear to me how your control scheme works, but if you’re having the player rotate the camera with the mouse, you should just let the mouse movement change the yaw and pitch variables directly, then calculate the vector you need using spherical coordinates. Look at the spherical->Cartesian conversion on that page - it’s a standard formula that’s known to work right for all values of the angles.

0
101 Mar 26, 2009 at 14:08

@Reedbeta

calculate the vector you need using spherical coordinates

omg thank you this works perfectly. Talk about over thinking the problem!

now how do i get it to work if the player moves away from 0,0,0 ? That was easy enough.
but then the farther away i get from 0,0,0 the shot starts jumping around.. is there a fix for this?
so far this is what I am doing. shot has x,y,z as well, shot(x,y,z)

//start Cartesian coordinate system always at 0,0,0
// this works since the invP(x,y,z) is always 10 steps in front of the player (x,y,z) directional facing.
shot(x) = player(x)
shot(y) = player(y)
shot(z) = player(z)
tx = player(x)-invP(x)
ty = player(y)-invP(y)
tz = player(z)-invp(z)

//set up the initial velocity on each axis for use as a radial distance
xv = 0
yv = 0
zv = 2

// Cartesian coordinates to spherical coordinates
radialDistance = (xv^2+yv^2+zv^2)    //uses the velocity's
azimuth = ATan2(ty,tx)                      //uses the invP
zenith =  ATan2(SquareRoot(tx^2+ty^2),tz) //uses the invP

//convert spherical coordinates into Cartesian coordinates
shot(xv) = radialDistance * sin(zenith) * cos(azimuth)
shot(yv) = radialDistance * sin(zenith) * sin(azimuth)
shot(zv) = radialDistance * cos(zenith)

0
167 Mar 26, 2009 at 16:50

That code looks like it should work. However, you don’t need to convert to spherical coordinates and back again - all you’re doing there is scaling the tx, ty, tv vector to match the desired speed for the shot. You could do that just as well in Cartesian coordinates.

I wonder if the problem you’re seeing is with how the invP point is being calculated. I don’t see the need for invP at all. You can just keep track of (and/or let the user control) the desired azimuth and zenith, then convert those to Cartesian coordinates whenever needed.

0
101 Mar 26, 2009 at 23:26

@Reedbeta

That code looks like it should work. However, you don’t need to convert to spherical coordinates and back again - all you’re doing there is scaling the tx, ty, tv vector to match the desired speed for the shot. You could do that just as well in Cartesian coordinates.

I was trying to do that I think, but it wasn’t working or I was doing it wrong. I’m still not sure how to do it, a wiki page?

0
167 Mar 27, 2009 at 02:34

To scale a vector in Cartesian coordinates, all you have to do is multiply each component by the scaling factor. So if the vector is (tx, ty, tz), then (2*tx, 2*ty, 2*tz) is a vector in the same direction but twice as long.

Now if you want a vector to have a particular length, say 5, you first have to normalize it, which means scaling it to have length 1. Then you can scale it by 5, and it will have length 5. To normalize it, you just divide each component by the vector’s length, which is sqrt(tx*tx + ty*ty + tz*tz).

0
101 Mar 27, 2009 at 16:18

@Reedbeta

To scale a vector in Cartesian coordinates, all you have to do is multiply each component by the scaling factor. So if the vector is (tx, ty, tz), then (2*tx, 2*ty, 2*tz) is a vector in the same direction but twice as long. Now if you want a vector to have a particular length, say 5, you first have to normalize it, which means scaling it to have length 1. Then you can scale it by 5, and it will have length 5. To normalize it, you just divide each component by the vector’s length, which is sqrt(tx*tx + ty*ty + tz*tz).

I’m not sure but isn’t scaling relative to the position of the object and not to the direction of the object is facing? anyway I also figured out how to use Cartesian coordinates to rotate in the same way spherical coordinates do. it’s pretty easy actually, I was close yet so far away. it is done like so:

xv =0:yv=0:zv=2

sx = Sin(player(pitch))
cx = Cos(player(pitch))
sy = Sin(player(yaw))
cy = Cos(player(yaw))
sz = Sin(player(roll))
cz = Cos(player(roll))

// rotation around x
xy = cx*yv - sx*zv
xz = sx*yv + cx*zv
// rotation around y
yz = cy*xz - sy*xv
yx = sy*xz + cy*xv
// rotation around z
zx = cz*yx - sz*xy
zy = sz*yx + cz*xy

tx = zx
ty = zy
tz = yz

shot(xv) = tx
shot(yv) = ty
shot(zv) = tz


Your absolutely right about not needing invP. Though i still get the jumping around of the shot after player moves farther then about 1,000,000 steps in any direction. Strange there are no tutorials for this or anything in the wiki as well.

0
167 Mar 27, 2009 at 16:42

In this case the vector you’re scaling is the view direction, which has nothing to do with where the player is. A vector is just an arrow and scaling just lengthens or shortens it.

0
101 Mar 27, 2009 at 17:01

oh yea, sorry, I should have but didn’t make that connection. So the above code is how to scale a vector in Cartesian. Sweet, this has defiantly been a learning experience thank you Reedbeta for all the help.

0
102 Mar 27, 2009 at 19:47

The “jumping” about at coordinates beyond 1,000,000 is likely due to floating point errors. This article addresses the issue in the context of a space simulation.

0
101 Mar 30, 2009 at 14:33

@monjardin

The “jumping” about at coordinates beyond 1,000,000 is likely due to floating point errors. This article addresses the issue in the context of a space simulation.

Thank you monjardin. That helped out immensely. Doubles isn’t an option for me so I have figured out another way to overcome the floating point errors. instead of the player going to the systems, I bring the systems to the player. so the player is always at 0,0,0.