Ray Casting in Lüfterkonfiguration erzeugt eine Punktwolke mit Krümmung. Wie kann die Krümmung beseitigt werden?

7

Ich versuche, einen Schnittpunkttest mit Ray Casting durchzuführen (nicht sicher, ob der Begriff korrekt ist, bitte verzeihen Sie mir, wenn nicht) und gebe die Schnittpunkte als Punktwolke aus. Die Punktwolke zeigt die Krümmung (nur auf der Z-Achse, die Die Punktwolke ist auf der Y-Achse vollständig flach, und die horizontale Achse in diesem Bild ist die X-Achse. Geben Sie hier die Bildbeschreibung ein

Ich habe Konzepte von der Scratchapixel-Website ausgeliehen, insbesondere http://scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-box-intersection .

Im Wesentlichen generiere ich 16 Strahlen, alle mit demselben Ursprungsvektor. Die Richtungsvektoren beginnen bei +15 Grad in der YZ-Ebene und setzen sich in Schritten von -2 Grad bis -15 fort. Ich habe einen achsenausgerichteten Begrenzungsrahmen, mit dem ich den Schnittpunkt teste. Ich benutze eine Rotationstransformation, um die 16 Strahlen gegen den Uhrzeigersinn um die Z-Achse zu drehen. Ich führe den Schnittpunkttest für alle 16 Strahlen mit jeweils 0,1 Grad durch. Wenn er wahr ist, füge ich den Punkt zur Punktwolke hinzu.

Hier ist mein Kreuzungscode:

bool test_intersect(Box b, Ray r, Vec3f& intersect_point)
{
    float txmin = 0.0f, txmax = 0.0f, tymin = 0.0f, tymax = 0.0f, tzmin = 0.0f, tzmax = 0.0f;
    float t_min = 0.0f, t_max = 0.0f, t = 0.0f;

    // Determine inverse direction of ray to alleviate 0 = -0 issues
    Vec3f inverse_direction(1 / r.direction.x, 1 / r.direction.y, 1 / r.direction.z);

    // Solving box_min/box_max0 = O + Dt 
    txmin = (b.box_min.x - r.origin.x) * inverse_direction.x;
    txmax = (b.box_max.x - r.origin.x) * inverse_direction.x;
    tymin = (b.box_min.y - r.origin.y) * inverse_direction.y;
    tymax = (b.box_max.y - r.origin.y) * inverse_direction.y;
    tzmin = (b.box_min.z - r.origin.z) * inverse_direction.z;
    tzmax = (b.box_max.z - r.origin.z) * inverse_direction.z;

    // Depending on direction of ray tmin may > tmax, so we may need to swap
    if (txmin > txmax) std::swap(txmin, txmax);
    if (tymin > tymax) std::swap(tymin, tymax);
    if (tzmin > tzmax) std::swap(tzmin, tzmax);

    t_min = txmin;
    t_max = txmax;

    // If t-value of a min is greater than t-value of max,
    // we missed the object in that plane.
    if ((t_min > tymax) || (tymin > t_max))
        return false;

    if (tymin > t_min)
        t_min = tymin;
    if (tymax < t_max)
        t_max = tymax;

    if ((t_min > tzmax) || (tzmin > t_max))
        return false;

    if (tzmin > t_min)
        t_min = tzmin;
    if (tzmax < t_max)
        t_max = tzmax;

    if (t_min > 0)
        t = t_min;
    else
        if (t_max > 0)
            t = t_max;
        else
            return false;

    intersect_point.x = r.origin.x + r.direction.x * t;
    intersect_point.y = r.origin.y + r.direction.y * t;
    intersect_point.z = r.origin.z + r.direction.z * t;

    return true;

}

Und meine Rotation:

// Rotation around z axis, for rotating array and checking beam intersections
void transform_rotate_z(Vec3f& in_vector, float angle)
{
    float radians = angle * (M_PI / 180);

    float result_x = cos(radians) * in_vector.x + -sin(radians) * in_vector.y;
    float result_y = sin(radians) * in_vector.x + cos(radians) * in_vector.y;
    in_vector.x = result_x;
    in_vector.y = result_y;

}

Ich habe mir eine ganze Weile den Kopf zerbrochen, aber ich kann anscheinend nicht feststellen, wie ich diese Krümmung verhindern kann. Ich bin sicher, ich übersehen etwas Einfaches. Ich wäre Ihnen für jede Hilfe dankbar, die Sie leisten können.

EDIT 18.09.16: Es stellte sich heraus, dass ich fälschlicherweise geglaubt hatte, dass physikalische LIDAR-Einheiten eine algorithmische Methode zum "Begradigen" der Kurven haben, was nicht der Fall ist! Die Ausgabe soll wie im Bild oben aussehen.

Irongrave
quelle

Antworten:

9

Die Richtungsvektoren beginnen bei +15 Grad in der YZ-Ebene und setzen sich in Schritten von -2 Grad bis -15 fort.

Es gibt Ihr Problem: Wenn Sie die Strahlen auf diese Weise erzeugen, machen Sie eher eine sphärische Projektion oder eine Fischaugenprojektion, keine lineare perspektivische Projektion. Die nichtlineare Projektion ist der Ursprung der Krümmung, die Sie sehen.

Um stattdessen eine perspektivische Projektion zu erhalten, ist konzeptionell die Art und Weise, wie man darüber nachdenkt, dass vor der Kamera ein Bildrechteck schwebt, das in Gitterquadrate (Pixel) unterteilt ist, und Sie einen Strahl von der Kameraposition in Richtung der Mitte jedes Pixels abfeuern . Im Code sieht das ungefähr so ​​aus:

p = tan(horizontalFOV / 2)
q = tan(verticalFOV / 2)
for y = 0 to imageHeight - 1
    for x = 0 to imageWidth - 1
        rayDirection = Vec3f(1.0,
                             p * ((x + 0.5) / imageWidth * 2.0 - 1.0)
                             q * ((y + 0.5) / imageHeight * 2.0 - 1.0)).normalize()

Man beachte , dass die so erzeugten Richtungen sind nicht gleichmäßig im Winkel beabstandet sind (sie sind näher zusammen in Winkel zu den Rändern des Bildes als in der Mitte), aber sie sind in gleicher Weise in Abstand auf dem Bildrechteck beabstandet.

Nathan Reed
quelle
Danke Nathan! Ich versuche, einen LIDAR-Scanner zu simulieren. Das ist der Grund für den Fächerstrahl und den gleichen Winkelabstand. Der spezielle Scanner, nach dem ich meine Simulation modelliere, hat seine Laser in der Fächerstrahlkonfiguration außerhalb des Gehäuses, aber wenn die Rückflüsse eintreten, werden sie von einem Fächerstrahl in parallele Strahlen (über eine Linse) umgeleitet. Ich versuche einen Weg zu finden, dieses Modell beizubehalten, um die Simulation so genau wie möglich zu gestalten. Irgendwelche Gedanken darüber, wie ich das machen könnte?
Irongrave
@ Irongrave Sorry, ich weiß nicht viel über LIDAR-Scanner. Haben Sie ein Diagramm oder etwas vom Setup mit dem von Ihnen erwähnten Objektiv? Es fällt mir schwer, es mir vorzustellen.
Nathan Reed
Hier ist ein Bild aus dem Handbuch: ( imgur.com/a/czhpt )
Irongrave
1
Es stellte sich heraus, dass ich fälschlicherweise geglaubt hatte, dass physikalische LIDAR-Einheiten eine algorithmische Methode zum "Begradigen" der Kurven hatten, was nicht der Fall ist. Ihr Beitrag hat mir geholfen, zu einem endgültigen Ergebnis zu gelangen. Vielen Dank, und ich habe ihn als Antwort ausgewählt, da Sie richtig waren.
Irongrave