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

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

1

02.11.2004, 16:42

Punkt <-> Box Kollision, fehler in der Berechnung?

Hi,

Kurz und schmerzlos: Ich will eine Rotierte Box mit einem Punkt kollidieren lassen ohne die invertierte Matrix zu benutzen, also erstelle ich für die Box die 6 Planes und teste die dann zu dem Punkt.

Das will jedoch leider nicht. Nach ca. 4 Stunden suche habe ich es aufgegeben und hoff nun hier auf Hilfe :(

Hier die Relevanten Code-Stücke:

C-/C++-Quelltext

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
46
47
48
49
50
51
52
53
inline plane createPlaneNormal (const vector &_point, const vector &_normal)
{
    return plane (_normal, -_normal.x * _point.x - _normal.y * _point.y - _normal.z * _point.z);
} 

inline plane PlaneTransform (const plane& _plane, const matrix& _matrix)
{
    float a = _plane.x * _matrix._11 + _plane.y * _matrix._21 + _plane.z * _matrix._31;
    float b = _plane.x * _matrix._12 + _plane.y * _matrix._22 + _plane.z * _matrix._32;
    float c = _plane.x * _matrix._13 + _plane.y * _matrix._23 + _plane.z * _matrix._33;

    return plane(a, b, c, _plane.distance - (a * _matrix._41 + b * _matrix._42 + c * _matrix._43));
}

inline void ComputeBoxPlanes (const vector& boxMin, const vector& boxMax, const matrix& boxTrans, plane* out)
{
    out[0] = createPlaneNormal (boxMin, vector(-1.0f,  0.0f,  0.0f)); // Linke Ebene

    out[1] = createPlaneNormal (boxMax, vector( 1.0f,  0.0f,  0.0f)); // Rechte Ebene

    out[2] = createPlaneNormal (boxMax, vector( 0.0f,  1.0f,  0.0f)); // Obere Ebene

    out[3] = createPlaneNormal (boxMin, vector( 0.0f, -1.0f,  0.0f)); // Untere Ebene

    out[4] = createPlaneNormal (boxMin, vector( 0.0f,  0.0f, -1.0f)); // Vordere Ebene

    out[5] = createPlaneNormal (boxMax, vector( 0.0f,  0.0f,  1.0f)); // Hintere Ebene


    for(int i=0; i<6; ++i)
    {
        out[i] = PlaneTransform(out[i], boxTrans);
    }
}

inline float dotPlaneProductCoords (plane _plane, const vector &_vector)
{ 
    return (_plane.x * _vector.x + _plane.y * _vector.y + _plane.z * _vector.z) + _plane.distance;
} 

inline bool PointHitsBox (const vector& point, const plane* boxPlanes)
{
    if(dotPlaneProductCoords (boxPlanes[0], point) > 0.0001f) return (false);
    if(dotPlaneProductCoords (boxPlanes[1], point) > 0.0001f) return (false);
    if(dotPlaneProductCoords (boxPlanes[2], point) > 0.0001f) return (false);
    if(dotPlaneProductCoords (boxPlanes[3], point) > 0.0001f) return (false);
    if(dotPlaneProductCoords (boxPlanes[4], point) > 0.0001f) return (false);

    return (dotPlaneProductCoords (boxPlanes[5], point) <= 0.0001f);
}

inline bool PointHitsBox (const vector& point, const vector& boxMin, const vector& boxMax, const matrix& boxTrans)
{
    plane BoxPlane[6];

    ComputeBoxPlanes(boxMin, boxMax, boxTrans, BoxPlane);

    return PointHitsBox(point, BoxPlane);
}


das zu den Hilfsfunktionen und hier nun die Funktionen der Plane:

C-/C++-Quelltext

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
class plane
{
public:
    union 
    {
        struct
        {
            mutable float x;
            mutable float y;
            mutable float z;
            mutable float distance;
        };
        struct
        {
            mutable vector normal;
            mutable float distance;
        };

        float values[4];
    };

        // Constructors

    plane                   (void);
    plane                   (const plane &other);
    plane                   (float x, float y, float z, float distance);
    plane                   (const float (&value)[4]);
    plane                   (const vector &_vector, float distance);
// [...]

};


ist etwas viel Code ich weiß, aber ich konnte bisher nicht rausfinden wo der Fehler in der Berechnung liegt (ist bestimmt mal wieder ein Designfehler oder ein Logikfehler!).

p.s.: Die Position des Punktes ist innerhalb der Box und mit einer invertierten Matrix (ist eine Extra-Funktion) funktioniert es einwandfrei.

- Patrick

edit: code überarbietet damit es übersichtlicher ist

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

2

02.11.2004, 17:45

Zitat

(*this) = createFromPointNormal(point1, (point3-point2).crossProduct(point1 - point2));


Hmmm kannst du mich darüber aufklären was der Punkt da genauer tut?

Sonst fällt mir persönlich nichts auf....

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

3

02.11.2004, 17:48

Nox
Es bildet das Kreuzprodukt aus (point3-point2) und (point1 - point2).

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

4

02.11.2004, 22:21

Ich habe den code was überarbeitet damit er übersichtlicher ist, jetzt hab ichs zu einer kollision gebracht, nur egal wo der Punkt liegt, es gibt immer eine Kollision? Egal ob er in der Box ist oder nicht :(

Ist kein Matheguru da? ???

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

5

02.11.2004, 23:18

Tausch doch einfach mal das Minus in

Zitat


return plane(a, b, c, _plane.distance - (a * _matrix._41 + b * _matrix._42 + c * _matrix._43));


gegen ein Plus aus :P
"Games are algorithmic entertainment."

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

6

02.11.2004, 23:23

selbes Ergebnis, das hatte ich auch schon probiert.

Osram

Alter Hase

Beiträge: 889

Wohnort: Weissenthurm

Beruf: SW Entwickler

  • Private Nachricht senden

7

02.11.2004, 23:43

Hm, dann hast Du wahrscheinlich 2 Fehler. Wo ich mir unsicher bin ist, ob Du nicht beim Zugriff auf die Matrix ij mit ji vertauscht hast.

Am besten einfach mal ein Beispiel auf Papier machen und Rechnen und dann Deine Zwischenergbnisse mit denen des Rechners vergleichen.

Übrigens, geht es auch schief, wenn die Transformationsmatrix die Identität ist? Wenn es eine reine Verschiebung, eine reine Rotation ist?
"Games are algorithmic entertainment."

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

8

03.11.2004, 08:11

Hi,

so sieht die Abfrage aus:

C-/C++-Quelltext

1
if (utils::PointHitsBox(vector(0,0,10), vector(-1,-1,-1), vector(1,1,1), (rotX*rotY*rotZ*trans)))


rotX, rotY, rotZ haben beide einen Winkel von 45 Grad und trans steht auf 0,0,10 und der Punkt ist bei 0,0,0 ohne Transformation, rotation und co. halt an das Weltkoordiantensystem ausgerichtet.

Wie schon gesagt mit der Invertierten Matrix geht es. :(

Patrick

Alter Hase

  • »Patrick« ist der Autor dieses Themas

Beiträge: 1 264

Wohnort: Düren

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

9

03.11.2004, 21:27

Osram
auch bei einer identitätsmatrix geht nix, bei einer rotationsmatrix oder bei einer Translationsmatrix, ja sogar mit skalierung hab ichs probiert! selbes ergebnis -> Kollision wo keine sein darf!

Interessanterweise hab ich was sehr faszinierendes Festgestellt mit dem debugger: Jede der 6 Planes haben identitische normalen und distanzen! alles ist auf 0,0,0,-1!

Auf der Suche habe ich festgestellt, das der default-constructor von vector aufgerufen wurde und der hat folgende initialisierungliste:

C-/C++-Quelltext

1
2
3
vector::vector (void) : x(1.0f), y(0.0f), z(0.0f)
{ 
} 


aus irgendeinem mir wirklich unerdenklichen grund wurde der defaultconstructor von vector in createPlaneNormal aufgerufen und der hat wieder alle übergebenen werte genullt?!?!?! (der dürfte normalerweise nicht aufgerufen werden!)

Jetzt wo ich die initialisierungsliste entfernt habe werden die werte nicht mehr reinitialisiert mit nullen und es läuft perfekt und funktioniert, auch wenn jetzt die zahlen im Debugger rot unterlaufen sind :)

Aber wie sowas passieren konnte versteh ich dennoch nicht :( naja Hauptsache es Funktioniert :)

- Patrick, der froh ist das es nun nach mehreren Tagen funktioniert und trotzdem nicht versteht wieso der defaultconstructor aufgerufen wurde.

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

10

03.11.2004, 22:24

Hmmm wieso in vc6 zeigt rot doch an mit welchen var gerade gearbeitet wird....

Werbeanzeige