Get local direction

Hello!

I tried everything that I could to get the exact direction in local space for a vehicle.
Because I want to see how fast the vehicle is going in a specific direction.

The problem is, I tried local space, world space, calculating distance, and still, sometimes as I rotate the vehicle, the local vector becomes negative, or positive, and the code says that the vehicle goes backwards, even though its still heading forwards… just in a different rotation.

What’s the best method to know if a mesh goes forward, backward, right or left?
Thanks in advance!

Hello! thank you for your answer, but sadly i tried this too.
I have a direction vector with physicsImpostor.getLinearVelocity()
this tells me in world space that where does the vehicle heading, then i convert it into local space, in theory I could just check direction.z and if its negative then it goes backwards… but its all over the place… am i dumb? because i feel like this should be easy lol

I think you need both. @Necips 's code gives the orientation of your mesh. The direction your vehicle is facing.

var forward = new BABYLON.Vector3(0, 0, 1);
var direction = mesh.getDirection(forward);
direction.normalize();

Then you have the moving direction given by:

physicsImpostor.getLinearVelocity()

These two vectors are not the same. Use these two vectors together should give you the solution.

If these two vectors are 180 degree: you are moving backward.
If 90 degree: you are moving left or right.
If 0 degree: you are moving forward.

1 Like

Im using both in my code, but… what do you mean by degrees? how do i get that? i feel dumb.

If you have both vectors already, you can calculate the angle between these two vectors.

E.g. your vehicle is facing north and moving south. The angle between these two vectors should be 180.

Of course, for left and right moves, you cannot use the function above. You need to check if velocity vector is rotating 90 or -90 degrees from orientation vector?

Still not working, as soon as i rotate more than 90 degrees, the forward direction becomes negative number.

Can you try to get the orientation vector by using something like this? It will give you the rotation information (orientation) of your mesh.

            var invertWorldMatrix = new BABYLON.Matrix();
            dude.getWorldMatrix().invertToRef(invertWorldMatrix);
            var quaternion = new BABYLON.Quaternion();
            invertWorldMatrix.decompose(undefined, quaternion);
            console.log(quaternion.toEulerAngles());

@Matthias22 I will be afk and didn’t have time to put a complete PG. I can finish the PG a bit later.

yes i can, it goes from 0 to 3.14, then -3.14 to -0 im thinking about checking if its negative number, then make the forward direction positive, but i think that would be “hacky”.

Hi @Matthias22

The model is facing west, but moving north. You need both orientation and velocity.

Orientation can be calculated as either

Model originally has facing direction (0,0,1). Extract RotaionMatrix from model’s world matrix and apply it to the original facing direction:

            const originalFacing = new BABYLON.Vector3(0, 0, 1);
            const facing = BABYLON.Vector3.TransformCoordinates(originalFacing, dude.getWorldMatrix().getRotationMatrix());
            facing.normalize();
            console.log(facing);

Or using @Necips 's code.

            var originalOrientation = new BABYLON.Vector3(0, 0, 1);
            var orientation = dude.getDirection(originalOrientation);
            orientation.normalize();
            console.log(orientation);

Both should give the same result.

You also need the velocity vector, which is the moving direction of your model. Because the PG moves the model towards north (dude.position.z-= 0.005;), so the velocity is hardcoded to the following in the PG.

            const velocity = new BABYLON.Vector3(0, 0, -1);
            velocity.normalize();

If you can obtain velocity from physicsImpostor.getLinearVelocity(). Use it instead.

You can then calculate the angle between the orientation and velocity.

            const angleRadian = BABYLON.Vector3.GetAngleBetweenVectors(orientation, velocity, new BABYLON.Vector3(0, 1, 0));
            const angleDegree = BABYLON.Angle.FromRadians(angleRadian).degrees();
            console.log(angleDegree);

It will give angle in degree = 270. Which means your model is moving right.

I tried it, it tells me how much the vehicle rotated, but i dont think this will tell me if im going forward or sideways or whatnot, what i exactly want, is to able to see if the vehicle is moving forwards EVEN when the vehicle is rotated anywhere in 3D space.

why not just if angle < 0 then angle += Math.PI?

@Pryme8 and how is it going to help to get the direction of the mesh? :smiley:

I’m assuming you are doing a dot product of the mesh.forward and your chosen global forward.

Not really sure what you are trying to accomplish because technically the velocity or the meshes lastFramePosition - currentPosition is the direction of the mesh. So Im just confused what your end goal is maybe?

Whenever I need a localForward, I just use mesh.forward if thats not available or correct then I transform a Vector3.Forward() by the meshes rotation Matrix

1 Like

i have a vehicle, which has physics on it, i want to drive it, with applyImpulse, and slow it down as well with the same function… but… i dont want the vehicle to go 800000km/h or even more… so i want to limit it to only 25km/h…

so i have to able to check where is the vehicle is going, and how fast.
because if im going 25km/h forwards, and i want to go backwards, then it doesnt let me go backwards because Im already going 25km/h… so i have to check somehow if the vehicle is going 25km/h forwards or backwards.

const vel = physicsImpostor.getLinearVelocity()
if(vel.length() > maxSpeed){
physicsImpostor.setLinearVelocity(vel.normalize().scale(maxSpeed))
}

?

1 Like

i dont want to limit the speed of gravity:/

If you convert to a Vector2 and back to preserve the y velocity then it should work I think

const vel = physicsImpostor.getLinearVelocity()
const vel2D = new BABYLON.Vector2(vel.x, vel.z)
if(vel2D.length() > maxSpeed){
    vel2D.normalize().scaleInPlace(maxSpeed)
    vel.x = vel2D.x;
    vel.z = vel2D.y;
    physicsImpostor.setLinearVelocity(vel)
}

My site is crashing so something is wrong xd

Nevermind, i was dumb, but… this is not going to work… if i try to climb a wall, then it will yeet up the vehicle, and if i try to go up a ramp, slowly but surely the vehicle starts floating:/ i tried to figure out a solution for the last 8 days… and still nothin… Why does Ammo.js raycast vehicle work so well? am i dumb? probably.

Give me a second I’ll post a example.

In premise:

        const input = new Vec3.Zero()
        const accel = 1
        onUpdate(deltaTime){
            const body = mesh.physicsImposter
            const vel = mesh.getLinearVelocity()
            if(vel.length() > maxSpeed){
                body.applyImpulse(input.clone().scale(accel * deltaTime), body.absolutePosition)
            }
        }

        onInput(){
            input.set(-1:1, -1:1, -1:1)
        }

This is really simplified, but if you break down the idea to per axis you can clamp each one of them independently.

In Practice with constraints per Axes:

This is a little different of an application but the same premise, it also might be hard to go through it because of the control mapping and how I am applying the input state but the idea is the same.