Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

22.01.2023, 16:37

Distanz von Ebenen nicht korrekt!

Hallo zusammen,

Meine Absicht ist es jedem Objekt(Würfeln, Pyramiden oder eben andere Formen) einen Umgebungsquader zu verpassen, damit diese später per Mausklick ausgewählt werden können.

Aber wie im Betreff schon erwähnt, werden die Distanzen der 6 Ebenen vom Umgebungsquader falsch berechnet. Zumindest lese und verstehe ich die Ausgabe so.
Bei einigen Ebenen sieht es nämlich so aus, dass die Zahl korrekt ist aber ein Minuszeichen davor ist wo es keins geben sollte oder andersherum. Verstehe einfach nicht woran das liegt und würde mich über einen kleinen Tipp ohne die Lösung sehr freuen. :)

Der Code von der Struktur "PLANE":

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct PLANE
{
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
    float w = 0.0f;

    // Erstellt eine Ebene durch die Angabe von 3 Vektoren
    void Create(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3);
};

void PLANE::Create(glm::vec3 p1, glm::vec3 p2, glm::vec3 p3)
{
    glm::vec3 AB;
    glm::vec3 AC;
    glm::vec3 normal;

    AB = p2 - p1;
    AC = p3 - p1;

    normal = glm::normalize(glm::cross(AB, AC));

    this->x = normal.x;
    this->y = normal.y;
    this->z = normal.z;

    // Ermittle die Distanz durch das Einsetzen eines gegebenen Punktes
    this->w = p1.x * this->x + p1.y * this->y + p1.z * this->z;
}


Der Code für die beiden Vektoren min und max:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void OBJECT::SetBoundingBoxMin(void)
{
    float x, y, z;

    x = this->vertex[0].x;
    y = this->vertex[0].y;
    z = this->vertex[0].z;

    for (unsigned int i = 1; i < this->ui_nVertices; i++)
    {
        if (this->vertex[i].x < x)
            x = this->vertex[i].x;

        if (this->vertex[i].y < y)
            y = this->vertex[i].y;

        if (this->vertex[i].z < z)
            z = this->vertex[i].z;
    }

    this->vec3_BoundingBoxMin = glm::vec3(x, y, z);
}

void OBJECT::SetBoundingBoxMax(void)
{
    float x, y, z;

    x = this->vertex[0].x;
    y = this->vertex[0].y;
    z = this->vertex[0].z;

    for (unsigned int i = 1; i < this->ui_nVertices; i++)
    {
        if (this->vertex[i].x > x)
            x = this->vertex[i].x;

        if (this->vertex[i].y > y)
            y = this->vertex[i].y;

        if (this->vertex[i].z > z)
            z = this->vertex[i].z;
    }

    this->vec3_BoundingBoxMax = glm::vec3(x, y, z);
}


Der Code zum festlegen der 8 Eckpunkten:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Ermittle die 8 Ecken eines AABBs(Axis Aligned Bounding Box)
glm::vec3 ohl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMin.z); // ECKE - OBEN - HINTEN LINKS
glm::vec3 ohr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMin.z); // ECKE - OBEN - HINTEN RECHTS
glm::vec3 ovl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMax.z); // ECKE - OBEN - VORNE LINKS
glm::vec3 ovr = object->vec3_BoundingBoxMax; // ECKE - OBEN - VORNE RECHTS

glm::vec3 uhl = object->vec3_BoundingBoxMin; // ECKE - UNTEN - HINTEN LINKS
glm::vec3 uhr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMin.z); // ECKE - UNTEN - HINTEN RECHTS
glm::vec3 uvl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMax.z); // ECKE - UNTEN - VORNE LINKS
glm::vec3 uvr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMax.z); // ECKE - UNTEN - VORNE RECHTS

// Erstelle die 6 Ebenen mithilfe der Ecken
object->plane_left.Create(ohl, uhl, ovl);
object->plane_front.Create(ovl, uvl, ovr);
object->plane_right.Create(ovr, uvr, ohr);
object->plane_back.Create(ohr, uhr, ohl);
object->plane_top.Create(ohl, ovl, ohr);
object->plane_bottom.Create(uvl, uhl, uvr);


Hier ist die Ausgabe und der Würfel:


Gruß

Erdem

2

23.01.2023, 15:49

Hallo zusammen,

habe mich erneut mit dem Thema Ebenen und Umgebungsquader befasst und festgestellt, dass ich es mir unnötig umständlich und noch dazu etwas falsch gemacht habe.

Der Umgebungsquader umschließt das Objekt vollständig ein und ist in meinem Fall immer entlang der Achsen ausgerichtet(AABB).
Das bedeutet gleichzeitig, dass keine besonderen Rechnungen notwendig sind, um die Ebenen des Umgebungsquaders anzulegen.

Die linke Ebene kann sich nur auf der X-Achse bewegen und der Normalvektor bei der linken Ebene zeigt immer in die negative Richtung.
Der Normalvektor kann also ruhig mit -1.0f per Hand festgelegt werden.
Die Distanz der linken Ebene kann zu Beginn auch per Hand festgelegt werden, mithilfe des minimalen Vektors(BoundingBoxMin).
Die Distanz der linken Ebene vom Umgebungsquader ist immer die X-Komponente des Vektors BoundingBoxMin.

Der alte Code:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Ermittle die 8 Ecken eines AABBs(Axis Aligned Bounding Box)
glm::vec3 ohl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMin.z); // ECKE - OBEN - HINTEN LINKS
glm::vec3 ohr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMin.z); // ECKE - OBEN - HINTEN RECHTS
glm::vec3 ovl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMax.y, object->vec3_BoundingBoxMax.z); // ECKE - OBEN - VORNE LINKS
glm::vec3 ovr = object->vec3_BoundingBoxMax; // ECKE - OBEN - VORNE RECHTS

glm::vec3 uhl = object->vec3_BoundingBoxMin; // ECKE - UNTEN - HINTEN LINKS
glm::vec3 uhr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMin.z); // ECKE - UNTEN - HINTEN RECHTS
glm::vec3 uvl = glm::vec3(object->vec3_BoundingBoxMin.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMax.z); // ECKE - UNTEN - VORNE LINKS
glm::vec3 uvr = glm::vec3(object->vec3_BoundingBoxMax.x, object->vec3_BoundingBoxMin.y, object->vec3_BoundingBoxMax.z); // ECKE - UNTEN - VORNE RECHTS

// Erstelle die 6 Ebenen mithilfe der Ecken
object->plane_left.Create(ohl, uhl, ovl);
object->plane_front.Create(ovl, uvl, ovr);
object->plane_right.Create(ovr, uvr, ohr);
object->plane_back.Create(ohr, uhr, ohl);
object->plane_top.Create(ohl, ovl, ohr);
object->plane_bottom.Create(uvl, uhl, uvr);


Der alte Code wurde nun mit dem folgenden neuen Code ersetzt:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
object->SetBoundingBoxMin();
object->SetBoundingBoxMax();

object->plane_left.normal = glm::vec3(-1.0f, 0.0f, 0.0f);
object->plane_left.w = object->vec3_BoundingBoxMin.x;

object->plane_right.normal = glm::vec3(1.0f, 0.0f, 0.0f);
object->plane_right.w = object->vec3_BoundingBoxMax.x;

object->plane_front.normal = glm::vec3(0.0f, 0.0f, 1.0f);
object->plane_front.w = object->vec3_BoundingBoxMax.z;

object->plane_back.normal = glm::vec3(0.0f, 0.0f, -1.0f);
object->plane_back.w = object->vec3_BoundingBoxMin.z;

object->plane_top.normal = glm::vec3(0.0f, 1.0, 0.0f);
object->plane_top.w = object->vec3_BoundingBoxMax.y;

object->plane_bottom.normal = glm::vec3(0.0f, -1.0f, 0.0);
object->plane_bottom.w = object->vec3_BoundingBoxMin.y;


Jetzt scheint alles in Ordnung zu sein:


Ist es denn jetzt richtig oder habe ich es schon wieder falsch verstanden? :)

Gruß

Erdem

3

25.01.2023, 19:12

Hallo zusammen,

habe die letzten Werte geprüft, indem ich der Ebenengleichung die Werte von der Ebene und ein Punkt eingesetzt habe.
Ergebnis war natürlich nicht so wie erwartet.

Erneut das Thema Ebenen im Buch 3D-Spieleprogrammierung auf Seite 75 durchgelesen und auf etwas wichtiges gestoßen.
Da wird nicht nur über die Ebenengleichung sondern auch über die Distanz und seine Eigenschaft gesprochen.

Habe die Gleichung nun angepasst und jetzt ist alles richtig:

Quellcode

1
distance = (normal.x * Point.x + normal.y * Point.y + normal.z * Point.z) * -1.0f;




Natürlich wurde auch hier auf Richtigkeit geprüft, indem ich die Werte(Normalvektor und Distanz) der jeweiligen Ebene und ein Punkt(x, y und z) in die Ebenengleichung eingesetzt habe.
Jede Mal richtiges Ergebnis.

Ein Punkt das vor der Ebene ist, ist nun Positiv und ein Punkt das hinter der Ebene ist, ist negativ. Und wenn es genau auf der Ebene ist, so ist das Ergebnis 0. :)

Gruß

Erdem

Werbeanzeige