Archive 17/01/2023.

Support for Steering Behaviors (RotateToward)

Leith

In order to implement intelligent steering behaviours, we need a way to know which way to turn.
I used this code as the basis for steering,

    /// Calculate signed angle between two vectors - needed for AI steering behaviours!
    float SignedAngle(Vector3 from, Vector3 to, Vector3 upVector)
    {
        float unsignedAngle = from.Angle(to);
        float sign = upVector.DotProduct(from.CrossProduct(to));
        if(sign<0)
            unsignedAngle = -unsignedAngle;
        return unsignedAngle;
    }

Yell if it dont werk, I’ll fix the post, it will be so.

throwawayerino

Why not use abs instead of conditional? It guarantees that it won’t return -0 in some edge cases

George1

Maybe name the thread title to be something related to steering :slight_smile:
I would create a gif and link it here to show the point.

TheComet

I don’t think an up vector belongs in a Vector3::SignedAngle method, given that Vector3::Angle doesn’t have one either. It would however be nice to have a signed angle method:

float Vector3::SignedAngle(const Vector3& rhs)
{
    return Angle(rhs) * Urho3D::Sign(DotProduct(CrossProduct(rhs)));
}
Leith

TheComet - Its not really an up vector, its a vector we expect to be “relatively” orthonormal to the other two, which acts as a reference for discerning the sign. It’s an arbitrary axis for comparing against. I couldn’t think of a way to entirely eliminate it, given we want to effectively perform a planar partitioning (the dot product versus some normal)
We are making a + or - decision about the state of a 3D spatial system… a binary decision. The sign of a dot product is a binary result of a 3D comparison of two vectors.

Leith

George1 - Done :slight_smile:

Leith

throwawayerino - the entire point is to determine the unknown sign of a known but unsigned angle - abs eliminates sign, we want to discover it :wink: The result of the dot product is a value between -1 and +1 , and we just want to know the sign, and then apply it to the unsigned angle, so we are returning a signed angle.

Leith

Example implementation:

                // Compute the angle between current and new directions
                float angle = SignedAngle(currentDir, newDir, Vector3::UP);

                // Apply angular velocity
                angle *= 5 * timeStep;

                // Rotate character toward target direction
                characterNode_->Rotate( Quaternion(angle, Vector3::UP));
TheComet
Leith

TheComet - I’ll check it out, thanks for taking your time to look

Leith

@TheComet - Comments indicate what I already suspected - there appears to be no reliable way to discern sign without a reference vector, and especially if our other two vectors are moving.