PDA

View Full Version : Problems with (newtonian) movement



Skalli
03-03-2013, 06:17 AM
Hallo all,

I'm new to OpenGL and I'm experimenting around a bit. So far everything went nice but now I'm stuck with a problem that's probably easy to solve but I'm just not getting it.
Currently I'm having a little object that can be steered with keyboard keys. When the up or down key is pressed the object accelerates and when left and right arrow keys are pressed the object gets rotated. So far so good but I wanted to change the movement behaviour in a more newtonian direction. When the object gets accelerated it contains it's movement speed and direction. I'm having projection, view and model matrices in my project. When I use translate and rotate my object this also changes the movement direction. To move the object I translate my model matrix with the movement vector, containing the movement speed in the y-axis. In the vertex shader the projection, view and model matrices get multiplied.
What would be the best way to implement a movement like this? I just can't figure it out.

Greetings
Skalli

trinitrotoluene
03-03-2013, 10:11 AM
A good introduction for particles and rigid body simulation is the lecture note of David Baraff and Andrew Witkin (http://www.cs.cmu.edu/~baraff/sigcourse/index.html) . For a newtonian simulation, mathematical knowledge to solve basic differential equation of the form mf''(t) + cf'(t) + kf(t) = F numerically is a must (Second order linear differential equation with constant coefficients) . The easiest but less accurate method to solve this equation numerically is the Euler method. My advice is to start learning physic simulation with particles because rigid body simulation are more complicated (inertia tensor,angular momentum). With particle you only need to store the position(x,y,z), the velocity (x,y,z), the sum of all forces F (x,y,z) acting on the particle and the mass (scalar).


So for each time step you compute with Euler method




struct Particle
{
glm::vec3 position,velocity;
float mass;
};
//Set initial position and velocity of the particle
...
delta_t = 1.0f/60.0f;
...

glm::vec3 force = compute_all_force_on_particle(); // thrust, gravity, damping etc.
glm::vec3 acceleration = force/particle.mass;
particle.velocity = particle.velocity + acceleration * delta_t;
particle.position = particle.position + particle.velocity * delta_t;
...

Skalli
03-03-2013, 11:04 AM
That's quite helpful! Thanks.
My first approach doesn't seem to be so bad then. I'm currently working with acceleration and position only. There seems to be a little problem somewhere to. It works almost as I'd expect, but my object is making small jumps back and forth.
This is the first step in my approach. When the user presses the up arrow, the object gets accelerated:
velocity and position are of type glm::vec3.
modelMatrix is a glm::mat4 and frametime and orientation are floats.


velocity.x -= sin(orientation * 3.14159 / 180) * 2.5f * frametime;
velocity.y += cos(orientation * 3.14159 / 180) * 2.5f * frametime;
With left/right arrow the object gets rotated:

orientation += 90.0 * frametime;
And then I add the position and velocity and translate:

position += velocity;

But is it wrong to set the objects position by using the identity matrix and translate it with the position like this?

modelMatrix = glm::translate(glm::mat4(1.f), position * frametime);
The movement in general seems correct, but the object makes small jumps back and forth. This is what it looks like, when I move straight up:

Position: 0, 615.726
ModelMatrix: 1,0,0,0
ModelMatrix: 0,1,0,0
ModelMatrix: 0,0,1,0
ModelMatrix: 0,0.90758,0,1

Position: 0, 637.105
ModelMatrix: 1,0,0,0
ModelMatrix: 0,1,0,0
ModelMatrix: 0,0,1,0
ModelMatrix: 0,0.858818,0,1

Position: 0, 658.165
ModelMatrix: 1,0,0,0
ModelMatrix: 0,1,0,0
ModelMatrix: 0,0,1,0
ModelMatrix: 0,1.78297,0,1 << Uh? oO

Position: 0, 679.864
ModelMatrix: 1,0,0,0
ModelMatrix: 0,1,0,0
ModelMatrix: 0,0,1,0
ModelMatrix: 0,0.940931,0,1

The format of the last row in the matrix is x, y, z, w. It should only increase on the y.axis. What am I missing?

trinitrotoluene
03-03-2013, 12:09 PM
But is it wrong to set the objects position by using the identity matrix and translate it with the position like this?



modelMatrix = glm::translate(glm::mat4(1.f), position * frametime);

I think that your position should not be multiplied by frame time. The code should be like this:




modelMatrix = glm::translate(glm::mat4(1.f),position);

The unit of acceleration is m/s^2 . When acceleration is multiplied by time, we get (m/s^2) *s = (m/s) unit of velocity. Then velocity multiplied by time give position (m).

Skalli
03-03-2013, 12:28 PM
Whops! Sometimes you miss the obvious! Of course you're right. I still need the frametime, but at "position += velocity * frametime;".
Thanks alot for your help and clarification.
I'm going to use a particle like system first, especially I'm not that good at math. ;) The Euler method is exactly what I'm looking for at the moment.
For a more complex physics system I'm going to switch to a library like bullet or similar.