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

06.12.2003, 11:53

BoxHitsTriangle

Hi,

weiß jemand eine genaue Möglichkeit, um zu gucken, ob ein "Kasten" (2 Vektoren) ein Dreieck trifft, und wenn ja, wo.

Vielen Dank,

Chrissi

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

06.12.2003, 11:55

1. Testen, ob die drei Verbindungslinien im Dreieck die Box treffen
2. Testen, ob die Seitenhalbierenden die Box treffen

Wenn beides zutrifft, schneidet das Dreieck die Box.
Es ist allerdings nicht 100% genau. Ist das Dreieck sehr groß, kann es leicht passieren, dass die Kollision nicht erfasst wird.

3

07.12.2003, 18:22

Danke für die schnelle Antwort,

aber, wie erkenne ich, wo die Kollisions stattgefunden hat, bzw, wie Implenmentiere ich das ganz konkret hier?!

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Kollision zwischen Box und Octree berechnen (rekursiv)
TRIBASE_API BOOL tbBoxHitsOctreeRec(const tbVector3& vBoxA,
                                     const tbVector3& vBoxB,
                                     tbMatrix mTransformation,
                                     const tbOctree* pOctree,
                                     const tbOctreeNode* pNode,
                                     int* piClosestTriangle,
                                     float* pfClosestCollision,
                                     tbOctreeNode** ppClosestNode,
                                     BOOL bSimpleMode,
                                     BOOL* pbStop)
{
    // Prüfen, ob der Quader den Umgebungsquader des Knotens trifft.
    // Falls nicht, können wir sofort abbrechen
    if(!tbBoxHitsBox(vBoxA, vBoxB, mTransformation,
                      pNode->vBoundingBoxMin,
                      pNode->vBoundingBoxMax,
                      tbMatrixIdentity(), 3))
    {
        // Abbruch!
        return FALSE;
    }

    // Ist dieser Knoten ein Endknoten? Falls ja, dann testen wir die
    // Kollision jetzt auf Dreiecksebene.
    if(pNode->bIsLeaf)
    {
        // Nun jedes Dreieck dieses Knotens durchgehen und
        // nach der nächsten Kollisionen suchen
        for(DWORD t = 0; t < pNode->dwNumIndices / 3; t++)
        {                       
            /*1. Testen, ob die drei Verbindungslinien im Dreieck die Box treffen 
            2. Testen, ob die Seitenhalbierenden die Box treffen 

            Wenn beides zutrifft, schneidet das Dreieck die Box. */

            if(COLLISION)
            {
                // Wenn der Benutzer den Ort der Kollision nicht kennen möchte
                // (bSimpleMode = TRUE), dann können wir jetzt schon abbrechen.
                if(bSimpleMode)
                {
                    *pbStop = TRUE;
                    return TRUE;
                }
            }
        }
    }
    else
    {
        // Dieser Knoten ist kein Endknoten.
        // Wir gehen seine Unterknoten durch und testen diese.
        for(DWORD i = 0; i < 8; i++)
        {
            tbBoxHitsOctreeRec(vBoxA, vBoxB, mTransformation, pOctree, pNode->apChild[i],
                                piClosestTriangle, pfClosestCollision, ppClosestNode,
                                bSimpleMode, pbStop);

            // Wurde die pbStop-Variable auf TRUE gesetzt?
            // Falls ja, dann brechen wir ab und liefern TRUE zurück.
            if(*pbStop) return TRUE;
        }

        // Wenn es eine Kollision gab, wird TRUE geliefert.
        if(*piClosestTriangle != -1) return TRUE;
    }

    // Keine Kollision!
    return FALSE;
}

// ******************************************************************
// Kollision zwischen Linie und Octree berechnen
TRIBASE_API BOOL tbBoxHitsOctree(const tbVector3& vBoxA,
                                  const tbVector3& vBoxB,
                                  tbMatrix mTransformation,
                                  const tbOctree* pOctree,
                                  const float fTolerance,   // = 0.0f
                                  tbVector3* pvOutPos,      // = NULL
                                  tbVector3* pvOutNormal,   // = NULL
                                  int* piOutTriangle,       // = NULL
                                  tbOctreeNode** ppOutNode) // = NULL
{
    // Parameter prüfen
    if(pOctree == NULL)         TB_ERROR_NULL_POINTER("pOctree", TB_ERROR);
    if(!pOctree->m_bExtraData)  TB_ERROR("Der Octree hat keine Extradaten!", TB_ERROR);


    // Startwerte setzen
    int iClosestTriangle = -1;
    float fClosestCollision = 100000.0f;
    BOOL bStop = FALSE;
    tbOctreeNode* pNode;

    // Rekursive Funktion aufrufen
    tbBoxHitsOctreeRec(vBoxA, vBoxB, mTransformation, pOctree, pOctree->m_pRootNode,
                        &iClosestTriangle, &fClosestCollision, &pNode,
                        pvOutPos == NULL, &bStop);

    // Gab es eine Kollision?
    if(iClosestTriangle != -1)
    {
        // Falls erwünscht: Ort der Kollision berechnen
        //if(pvOutPos != NULL) *pvOutPos = vLineA + fClosestCollision * (vLineB - vLineA);

        // Normalvektor des getroffenen Dreiecks eintragen
        if(pvOutNormal != NULL)
        {
            // Wir erhalten den Normalvektor aus der Ebenengleichung des getroffenen Dreiecks.
            *pvOutNormal = pNode->pTrianglePlanes[iClosestTriangle * 4].n;
        }

        // Das getroffene Dreieck und den Knoten selbst eintragen
        if(piOutTriangle != NULL) *piOutTriangle = iClosestTriangle;
        if(ppOutNode != NULL) *ppOutNode = pNode;

        return TRUE;
    }

    // Keine Kollision!
    return FALSE;
}


Danke,

Chrissi

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

07.12.2003, 18:37

Danke, ich kenne meinen eigenen Code ;)
Naja, wenn man sich mal ein Dreieck und eine Box vorstellt - wie willst Du da den genauen "Ort" der Kollision bestimmen? Schneidet man ein Dreieck mit einer Box, dann kommt ja im Allgemeinen kein Punkt dabei heraus, sondern ein Dreieck.
Wozu brauchst Du das überhaupt? Ist es wirklich nötig?

5

08.12.2003, 12:53

Da liegt ja gerade das Problem.
Ich versteh deinen Code nicht, aber ich muss es ja wohl oder über so wie du machen. Naja,

trotzdem nochmal danke,

schüssi,

Chrissi

6

13.12.2003, 09:04

Hi,

ich habe mich jetzt mal wieder an den PC gesetzt. Nun habe ich mal eine Frage: Wie kommt man auf die Normalvektoren jedes Dreiecks jedes Octree-Knotens

Das ist ja noch klar:

Quellcode

1
2
3
4
        // Alle Dreiecke vom Octree durchgehen
        for(DWORD tb = 0; tb < pOctreeNode->dwNumIndices / 3; tb++)
        {
        }


aber wie man hir rauf kommt

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        // Ersten Vektor dieses Dreiecks vom Octree transformieren
            pvVector = &pOctree->m_pvVectors[pOctreeNode->pdwIndices[tb * 3]];
            vTriA.x = pvVector->x * mInvMatrix.m11 + pvVector->y * mInvMatrix.m21 + pvVector->z * mInvMatrix.m31 + mInvMatrix.m41;
            vTriA.y = pvVector->x * mInvMatrix.m12 + pvVector->y * mInvMatrix.m22 + pvVector->z * mInvMatrix.m32 + mInvMatrix.m42;
            vTriA.z = pvVector->x * mInvMatrix.m13 + pvVector->y * mInvMatrix.m23 + pvVector->z * mInvMatrix.m33 + mInvMatrix.m43;

            // Zweiten Vektor dieses Dreiecks vom Octree transformieren
            pvVector = &pOctree->m_pvVectors[pOctreeNode->pdwIndices[tb * 3 + 1]];
            vTriB.x = pvVector->x * mInvMatrix.m11 + pvVector->y * mInvMatrix.m21 + pvVector->z * mInvMatrix.m31 + mInvMatrix.m41;
            vTriB.y = pvVector->x * mInvMatrix.m12 + pvVector->y * mInvMatrix.m22 + pvVector->z * mInvMatrix.m32 + mInvMatrix.m42;
            vTriB.z = pvVector->x * mInvMatrix.m13 + pvVector->y * mInvMatrix.m23 + pvVector->z * mInvMatrix.m33 + mInvMatrix.m43;

            // Dritten Vektor dieses Dreiecks vom Octree transformieren
            pvVector = &pOctree->m_pvVectors[pOctreeNode->pdwIndices[tb * 3 + 2]];
            vTriC.x = pvVector->x * mInvMatrix.m11 + pvVector->y * mInvMatrix.m21 + pvVector->z * mInvMatrix.m31 + mInvMatrix.m41;
            vTriC.y = pvVector->x * mInvMatrix.m12 + pvVector->y * mInvMatrix.m22 + pvVector->z * mInvMatrix.m32 + mInvMatrix.m42;
            vTriC.z = pvVector->x * mInvMatrix.m13 + pvVector->y * mInvMatrix.m23 + pvVector->z * mInvMatrix.m33 + mInvMatrix.m43;
ist mir schleierhaft.

Was hat da die Matrix zusuchen? Ist das überhaupt richtig???

danke,

Chrissi

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

7

13.12.2003, 16:22

Du hast diese Stelle aus tbModelHitsOctreeRec kopiert.
Da wird getestet, ob ein Modell mit einem Octree kollidiert.
Das Modell besitzt eine Transformationsmatrix, seine Vektoren sind also relativ. Nun kann man entweder die Vektoren des Modells in Weltkoordinaten umrechnen, oder man rechnet die Vektoren des Octrees in Modellkoordinaten um. Und genau das wird hier getan, mit der inversen Matrix.

8

13.12.2003, 19:03

Erstmal danke für die schnelle Antwort...

So ist das also.

Dann würde ich die Normalvektoren kriege, indem ich "nur"

soetwas schreibe:

Quellcode

1
2
3
vTriA=&pOctree->m_pvVectors[pOctreeNode->pdwIndices[tb * 3]];;
vTriB=&pOctree->m_pvVectors[pOctreeNode->pdwIndices[(tb * 3) + 1]];
vTriC=&pOctree->m_pvVectors[pOctreeNode->pdwIndices[(tb * 3) + 2]];


Danke,

Chrissi



PS: Für die nächste TriBase-Version sollte es dann zu der GetRoot()-Funktion eine GetVectors()-funktion hinzugefügt werden....

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

13.12.2003, 19:53

Aber was hat das denn mit Normalenvektoren zu tun?

10

14.12.2003, 10:58

Hää,

jetzt versteh ich gar nichts mehr. Ein Spiel besteht doch aus einem großen Koordinatensystem. Einen Vektor darin nennt man doch Normalvektor. Und nun möchte ich alle Normalvektoren der Dreiecke eines Octree-Nodes haben.

Oder sind die Vektoren von m_pvVectors relativ???

Danke, Chrissi

Werbeanzeige