Looking for help with settings and code to get my physics game correct

Post Reply
dataexcess
Posts: 4
Joined: Wed Jan 11, 2023 7:40 pm

Looking for help with settings and code to get my physics game correct

Post by dataexcess »

Hi there!

I would love for someone to help me with getting the correct settings of my game right, because I am really lost.
I have a terrain with hills and abstract shapes and my player is a sphere that I want to be able to roll over the landscape.

You can visit the website here: https://staging.subneu.live/
You need to toggle gravity by clicking the G key in order for the physics to be enabled!

I am using ammo.js which is a javascript port of Bullet. https://github.com/kripken/ammo.js/

first off, in order to move the player I am currently using the setLinearVelocity() method which is triggered while holding the arrow keys every update. This works, but I believe it is not the best way since by setting the velocity the gravity of the world is circumvented/ignored? So I probably need to use setForce or setImpulse, but I am not getting it correctly.

some code:

Code: Select all

const moveRigidBodyWithVector = (body:any, vector:any, scaleFactor:number) => {
    const resultantImpulse = new Ammo.btVector3(vector.x, vector.y, vector.z) // eslint-disable-line
    resultantImpulse.op_mul(scaleFactor)
    physicsBody.setLinearVelocity(resultantImpulse)
}
Secondly I want my sphere to stick to the terrain at all times, I do not want it to jump in the air after going up a slope. The sphere should stick like velcro on to the terrain at all times, but at the same time it should be relatively light-weight. I am a bit lost as to which settings are appropriate:

- world gravity : Ammo.btVector3(0, -100, 0)
- mass of sphere : 800
- friction of sphere. : 4
- rolling friction of sphere. : 10

I just want my game to have normal earth-like physics + the sticky but easy-to-roll sphere on the terrain moving around with controls.

Any help so much appreciated!!!
Thank you.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Looking for help with settings and code to get my physics game correct

Post by drleviathan »

My advice is to avoid applying force/torque because it is complicated and difficult to tune. This because the amount of force depends on the mass and angular inertia of your object. Setting the velocities is the right way to go: it is much easier to implement because it works independently of mass and substep duration. However you shouldn't just slam it to its exact intended motion. Instead you need to measure its real velocity (which could be influenced by gravity but also by collisions with other objects in the world) and slam the new velocity to be a linear interpolation between that and the object's intended velocity. I've outlined how to do this several times on the forums. Here are some, but not all, of the old threads:

viewtopic.php?p=35325
viewtopic.php?p=40055
viewtopic.php?p=41288
viewtopic.php?p=42205

I have worked on very similar dynamic character controllers that needed to stay tight to the ground but also needed to be able to climb slopes. At upward slopes the character would go very slow if I used a horizontal target velocity, consequently I would have to adjust the target velocity upwards according to the slope (or step height if the character should be able to climb small steps). The solutions were usually a bit complex with a bunch of special checks and branches of behavior logic. In your case, if you allow the ball to roll then you have an opportunity to simplify your logic by adjusting the angular velocity only and ignoring the current linear velocity, except to maybe attenuate its vertical component in order to keep it tight to the ground. In other words, your target velocity may be linear but the way to achieve it would be to compute the corresponding angular velocity and to slam the sphere toward it over time, such that the character rolls in the right direction.

Set the friction high (yes 4 is plenty high) and restitution (bounciness) to zero.
dataexcess
Posts: 4
Joined: Wed Jan 11, 2023 7:40 pm

Re: Looking for help with settings and code to get my physics game correct

Post by dataexcess »

Interesting!
Thank you very much for the quick reply.

Can you explain me how I can set the restitution? I cannot find it in the API of rigidBody?

I will try to analyse the other threads and find out how to calculate the correct linearVelocity (although I must say I'm a bit overwhelmed at first haha).
Thank you!
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Looking for help with settings and code to get my physics game correct

Post by drleviathan »

I don't use ammo.js however after downloading the repository and scanning the codebase I learned: it appears to support set/getResitution().
dataexcess
Posts: 4
Joined: Wed Jan 11, 2023 7:40 pm

Re: Looking for help with settings and code to get my physics game correct

Post by dataexcess »

I think I'm a bit confused about the difference between setLinearVelocity and setAngularVelocity. Could you explain the difference? It seems using these interchangeably does not result in any different behaviour.

Also I cannot make my ball stick to my terrain. When I'm not pressing my keys (hence not applying setLinearVelocity) my ball just rolls of the hill. Is there a way to make the ball only apply physics when it is told to?

Sorry if I am misunderstanding some fundamental concepts.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Looking for help with settings and code to get my physics game correct

Post by drleviathan »

After thinking about it some more I realized: if I just wanted a very simple rolling controller that pretty much always moved in the direction I wanted then I would blend toward a target linear velocity and then slam the angular velocity to always agree. In C++ it might look something like the code below. Porting to Java is left as an exercise for the reader:

Code: Select all

// get character's desired linear velocity 
// Note: desired velocity might be zero when character is trying to stop
btVector3 target_linear_velocity = character->getTargetLinearVelocity();

// get character's movement timescale
// short-timescale means character is strong and can quickly change its velocity
// long-timescale means character is weak and takes a while to change its velocity
btScalar timescale = character->getMovementTimescale();

// compute a new velocity that is a blend toward target_velociity
// Note: dt must be provided by outside context
btScalar del = dt / timescale;
if (del > 1.0) {
    // avoid instability by capping del to 1.0
    del = 1.0;
}
btVector3 linear_velocity = body->getLinearVelocity();
btVector3 new_linear_velocity = (1.0 - del) * linear_velocity + del * target_linear_velocity;

// slam the body's linear velocity
body->setLinearVelocity(new_linear_velocity);

// since the character is a rolling sphere
// we calculate an angular velocity to agree with with its the linear velocity component
// tangential to surface normal
 btVector3 ground_normal = character->getSurfaceNormal();
 btVector3 tangential_velocity = new_linear_velocity - (new_linear_velocity.dot(ground_normal)) * new_linear_velocity;
 btScalar tangential_speed = tangential_velocity.length();
constexpr btScalar MIN_ROLLING_LINEAR_SPEED = 0.01;
btVector3 new_angular_velocity;
if (tangential_speed > MIN_ROLLING_LINEAR_SPEED) {
    btVector3 roll_axis = ground_normal.cross(tangential_velocity).normalize();
    // DANGER: Bad Things happen if rolling radius is zero or very very small!
    btScalar angular_speed = tangential_speed / character->getRollingRadius();
    new_angular_velocity = angular_speed * roll_axis;
} else {
    // character is not moving tangentially to surface
    // so it is not "rolling"
    new_angular_velocity.setZero();
}

// slam the object's angular velocity
body->setAngularVelocity(new_angular_velocity);
I didn't actually test the code but wrote it from scratch. It may well have bugs.

This logic doesn't care about gravity. If the character aims to move up a very steep hill or climb a vertical wall then this logic will happily scoot it right up.

It assumes the existence of the following methods:

Code: Select all

btVector3 Character::getTargetLinearVelocity(); // returns the velocity the character wants to achieve
btScalar Charcater::getMovementTimescale(); // returns the exponential timescale of the character's change of velocity
btVector3 Character::getSurfaceNormal(); // returns the normal of the surface on which the character is rolling
btScalar Character::getRollingRadius(); // returns radius of rolling sphere
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Looking for help with settings and code to get my physics game correct

Post by drleviathan »

I should probably mention: one problem with slamming the linear velocity is it can override collision rebound effects and if the velocity blend is too strong it might lead to pushing the character through obstacle geometry (e.g. tunnel through a btBvhTriangleMeshShape terrain). To avoid this problem you should make the movement_timescale long relative to the simulation substep. In other words, keep the movement_timescale at least 3X substep duration, but even better would be no less than 10x substep.

One way to tune the timescale is to think about it this way: absent any obstacles your character will achieve 80% of its target velocity within only three timescales. So if you want the character to ramp up to full speed in about 1 second then set the movement_timescale to be 1/3 of a second.
Post Reply