Jump to content
  • Advertisement
Sign in to follow this  
TimmerCA

Unrestrained 3D Motion

This topic is 2383 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

I'm working on something like a space flight simulator. There is no gravity and no collisions in this simulator (for now). I've got the player's location_x, location_y, and location_z as well as the player's speed, yaw and pitch (I am currently not enabling any sort of roll, but I don't think roll would have any bearing on position calculations anyhow).

I'm having some problem calculating the player's new location based on the current speed, yaw and pitch. For a player that's only moving in two directions - for example, walking across a plane, I know the equation goes something like this:

location_x += ((float)Math.cos(Math.toRadians(yaw)) * speed);
location_y += ((float)Math.sin(Math.toRadians(yaw)) * speed);

But what is the proper set of equations for calculating location_z, and how do I take pitch into account?

Share this post


Link to post
Share on other sites
Advertisement
In space, you don't necessarily advance in the direction that your spaceship is pointing, so yaw and pitch don't matter. Other than the position, you need a vector called "velocity", whose size is the speed.

Then you just update the position by adding the velocity times the time increment (i.e., the time duration of a frame).

Share this post


Link to post
Share on other sites

In space, you don't necessarily advance in the direction that your spaceship is pointing, so yaw and pitch don't matter. Other than the position, you need a vector called "velocity", whose size is the speed.

Then you just update the position by adding the velocity times the time increment (i.e., the time duration of a frame).


Ok, that makes sense. I've created a velocity_x, velocity_y and velocity_z and those get added to the location_x, location_y and location_z each iteration through the game loop, which works very well. But, my original problem still stands, more or less.

How do I adjust velocity_x, velocity_y and velocity_z based on the current rotation_x, rotation_y and rotation_z of the player?

Basically, if the player is holding down the left mouse button, I want to accellerate the craft in the direction that the player is currently looking.

Share this post


Link to post
Share on other sites
As alvaro said, you cannot presume that the ship is flying in the direction where it's currently pointing. Of course you could do it this way, after all you're creating a game and in games everything is possible (hell, most spaceship simulators have sound effects, which isn't possible in vacuum).

Anyway, I personaly would try something like this:

You have 4 vectors:
- position (where the ship is in the space)
- direction (given by yaw and pitch, tells you how to render the ship and is handy later, read on...)
- velocity (direction in which the ship is currently flying, in general case have absolutely no relation to the direction vector)
- acceleration created by thrust (explained later)

Position and velocity are quite simple, each frame you simply modify your position by velocity:
position += velocity * dt;
(Those are vectors and vector operations, dt is delta time - time between two frames.)

Direction can be changed by the player when he wants to rotate the ship. This wouldn't be so trivial if you wanted an accurate simulation, because a real ship would probably rotate by some small jets placed on the ship for this purpose and you would have to work with forces, rotational inertia of the ship etc. But I think you can just simplify it somehow and just rotate the ship in the corresponding direction when the player holds a key (or analog stick).

Acceleration is caused by the main engine (jet) of the ship. The magnitude of this vector is given by the actual power of the engine (controlled by the player) and the orientation of the vector is equal to direction. Simply, the engine is pushing the ship in the direction where the ship is pointing.
You apply the acceleration very easily (direction must be a unit vector):
acceleration = direction * power;
velocity += acceleration * dt;

Which should be before the previous line, so in fact:

acceleration = direction * power;
velocity += acceleration * dt;
position += velocity * dt;

That's quite it. Of course you have to add the code that computes direction based on the player's input.

Now think about it - you hold the power button for a while, so the ship flies in one direction. Then you stop power - the ship will go in straight line with a constant speed (nothing is slowing it down in space). Now the player can rotate the ship however he wants, but the ship will still go in the original direction, you can for example rotate the ship 180 degrees and it will be going "backwards". Now if you again apply power, the ship will accelerate in the actual direction (towards the "spike" of the ship, not towards the actual movement vector), so as a result it may start slowing down (if it really was 180 degrees) or just generally changing direction.

Share this post


Link to post
Share on other sites
Slight modification of what Tom KQT said: I would describe the state of the spaceship as

  • Position
  • Velocity
  • Attitude (a.k.a. orientation)
  • Angular velocity

    Position is a point (but you can use a vector instead, if it's not clear to you what the difference is), velocity and angular velocity are vectors and attitude is a rotation, which can be represented using three angles (e.g., roll, pitch and yaw) or a 3x3 orthogonal matrix or a quaternion. I strongly recommend using the quaternion.

    Then at each frame I would compute two more vectors:

    • Acceleration
    • Angular acceleration

      Updating the state (the four things in the first list) based on these two accelerations can be done in many different ways, but you should probably start with Euler integration and go from there.

      Of course, you can throw any part of classical mechanics away and impose your own rules: It's your game. So you could just have position, speed and attitude, and compute your velocity as speed*attitude_applied_to(1,0,0) (attitude is a rotation, so you can apply it to a vector in model coordinates to get the direction in which it points after the rotation), which is the answer to your original question.

Share this post


Link to post
Share on other sites
If I'm understanding you correctly, you're having trouble finding the x, y, and z components of a vector given its roll, pitch, and yaw?

You are actually a lot of the way there. If the vector is pitched by angle theta above the x-y plane, then no matter what its yaw is its x and y components are lower by a factor of cos(theta). You can see that by drawing a triangle with the the x and y parts of the forward vector as the base and the total forward vector as the hypotenuse.

The z component is unaffected by yaw; with similar trigonometric arguments you can see that it is just sin(theta) times the magnitude of the vector.

To sum up:

vector.x = vectorMagnitude*cos(yaw)*cos(pitch);
vector.y = vectorMagnitude*sin(yaw)*cos(pitch);
vector.z = vectorMagnitude*sin(pitch);

I hope that helps!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!