Wandvermeidungslenkung

8

Ich mache einen kleinen Lenksimulator mit dem Reynolds-Boid-Algorithmus. Jetzt möchte ich eine Wandvermeidungsfunktion hinzufügen. Meine Wände sind in 3D und werden mit zwei Punkten definiert:

   ---------. P2
   |        |
P1 .---------

Meine Agenten haben eine Geschwindigkeit, eine Position usw.

Können Sie mir sagen, wie ich mit meinen Agenten ausweichen kann?

Vector2D ReynoldsSteeringModel::repulsionFromWalls()
{
    Vector2D force;
    vector<Wall *> wallsList = walls();
    Point2D pos = self()->position();
    Vector2D velocity = self()->velocity();

    for (unsigned i=0; i<wallsList.size(); i++)
    {
        //TODO
    }

    return force;
}

Dann benutze ich alle Kräfte, die von meinen Boid-Funktionen zurückgegeben werden, und wende sie auf meinen Agenten an.

Ich muss nur wissen, wie ich das mit meinen Wänden machen soll.

Danke für Ihre Hilfe.

Vodemki
quelle
2
Hast du dir das Original von Reynolds Papier angesehen? Wenn ich mich richtig erinnere, enthält es Informationen zur Vermeidung von Hindernissen und zur Vermeidung von Wänden. Ich denke, das ist das Dokument: red3d.com/cwr/steer/gdc99
krolth
1
Danke, aber es erklärt, wie man kreisförmige Hindernisse vermeidet, nicht rechteckige.
Vodemki
2
Verwenden Sie den radialen Abstand vom Agenten zum Mittelpunkt des Kreises ( abzüglich des Radius der Kreiswand ).
Bobobobo

Antworten:

14

Lassen Sie jede Wand einen Einfluss auf die Geschwindigkeit ausüben.

Versuchen Sie beispielsweise, den umgekehrten Abstand (oder den umgekehrten quadratischen Abstand) von der Wand zu verwenden, um die Größe der Kraft zu bestimmen, die jede Wand "ausübt", und die Normalen der Wand, um die Richtung der Kraft zu bestimmen, die die Wand "ausübt".

Geben Sie hier die Bildbeschreibung ein

Hier interagiert das Boid also mit 4 Wänden. Da das Punktprodukt der roten Vektoren (Boid-to-Wall-Center) für 3 der 4 Wände größer als 0 ist, üben diese Wände keine Kraft auf das Boid aus.

Nur die Wand mit einem blauen Vektor (negatives Punktprodukt) hat eine Kraft.

Die Stärke der Kraft sollte groß sein, wenn das Boid zu nahe an die Wand kommt, und die Richtung der Kraft sollte in Richtung des schwarzen Pfeils an der Wand sein (der direkt von der Wand weg zeigt).

Geben Sie hier die Bildbeschreibung ein

Wenn Sie 1 / (t+1)für die Größe der Kraft verwenden, wo tder Abstand von der Wand ist, dann ist die Kraft sehr stark, wenn sie sich 0 nähert, verblasst jedoch zu nichts, wenn t höher wird (beachten Sie die Achsenskala im Diagramm, es ist nicht 0, wenn t = 5 ist, es ist 0,2). (Das t + 1 ist so, dass Sie keine unendliche Kraft / Division durch 0 erhalten, wenn das Boid zufällig in die Wand eindringt).

Wenn Sie verwenden 1/(t^2+1), ist die Kraft in der Nähe der Wand viel schärfer und fällt schneller / gleichmäßiger ab.

Geben Sie hier die Bildbeschreibung ein

Experimentieren Sie damit und sehen Sie, was Ihnen gefällt.

Bobobobo
quelle
Danke aber wie man mit einer 3D Wand umgeht. Zum Beispiel hat meine Wand 4 Kanten, daher glaube ich, dass ich nur maximal 2 Kräfte benötige (wenn die Richtung des Agenten diagonal ist).
Vodemki
In 2D sind alle 2 Punkte eine "Wand". Wenn es sich um eine quadratische Säule in der Mitte eines Raums handelt, haben Sie dort 4 Wände. Sie können Backfacing-Wände "aussortieren" (damit Backfacing-Wände den Player nicht "saugen"), wenn der Vektor vom Boid zur Wandmitte ein positives Punktprodukt mit normaler Wand aufweist.
Bobobobo
Glaubst du, das würde den Job machen? Vector2D-Abstand (WallsList [i] -> center (), pos); double dotProduct = distance *wallList [i] -> normal (); if (dotProduct> 0) {force + =wallList [i] -> normal () / distance.length (); }
Vodemki
Es sieht vernünftig aus, testen Sie es!
Bobobobo
Ein Nachteil dieses Ansatzes besteht darin, dass die Lenkung als Abstoßungskraft modelliert wird, die unabhängig von der Bewegung des Agenten ist. Das heißt, es behandelt das Mittel als geladenes Teilchen in einem elektrostatischen Feld. Stellen Sie sich den Fall vor, in dem der Agent parallel zu dieser oberen (blauen) Wand und etwas darüber (auf der Seite) „fliegt“. In diesem Fall ist keine Lenkung oder Hindernisvermeidung erforderlich. Der Agent kommt einfach vorbei und sollte nicht von der Wand weggeschoben werden. Siehe zum Beispiel „Containment“ in diesem GDC 99-Dokument .
Craig Reynolds
8

Wenn jemand den Code benötigt, können Sie ihn hier weitergeben. Ich habe versucht, es zu kommentieren, um verständlicher zu sein. Basierend auf der Bobobobo -Lösung.

Vector2D ReynoldsSteeringModel::repulsionFromWalls(vector<Vector2D *> walls)
{
    Vector2D force; // My force will be stored here
    Point2D pos = self()->position(); // Position of the agent

    // For each wall
    for (unsigned j=0; j<walls->size(); j++)
    {
        // Get the center point of the wall
        Real coordX = (walls[j]->p1().x() + walls[j]->p1().y()) / 2.0;
        Real coordY = (walls[j]->p2().x() + walls[j]->p2().y()) / 2.0;
        Point2D center(coordX, coordY);

        // Create a new vector between my agent and the center of the current wall
        Vector2D distance(center, pos);

        // If the wall is visible, calculate the force to apply
        double dotProduct = distance * partsList[j]->normal();
        if (dotProduct < 0)
        {
            force +=  partsList[j]->normal() / (distance.length() * distance.length() + 1);
        }
    }

    // Returned the calculated force
    return force;
}
Vodemki
quelle