Toon posts:

[C++] Raycasting op Boundingbox intersection

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hey,

Ik ben bezig om in mijn engine een stukje raycasting in te bouwen die op intersection van boundingboxes moet gaan checken. Nou ben ik al wat redelijk tutorials tegengekomen waarin dit redelijk goed word uitgelegd alleen blijf ik nog een beetje hangen op het intersection gebeuren. ik heb verschillende pogingen gedaan om het goed werkend te krijgen en ik denk (zoals het ernaar uitziet althans) dat mijn calculaties goed gaan, alleen dat hij niet goed op de intersection test.

de engine is abstract en ik wil dus geen directe DX code of iets dergelijks gebruiken, maar ben op zoek naar een stukje code dat lijkt op D3DXBoxBoundProbe. Ik heb namelijk een orgin en een direction van mn ray en ik heb alle waardes van mijn boundingboxes.

ik doe dit samen met een vriend van me en hij heeft het intersection deels geschreven, het lijkt te werken in zijn engine, echter daar gebruikt hij ook delen DX code.

Dit is wat ik tot dusver heb:

C++:
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
// Build the ray with the mouse position
void Ray::createRay(int mouseX, int mouseY, Matrix* mProjMatrix, Matrix* mViewMatrix, Matrix* mWorldMatrix)
{
    // Calculate projection stuff
    v.x = ((( 2.0f*mouseX) / 640.0f)  - 1.0f) / mProjMatrix->_11;
    v.y = (((-2.0f*mouseY) / 480.0f) + 1.0f) / mProjMatrix->_22;
    v.z = 1.0f;

    Matrix* mInverse;

    mInverse = &mViewMatrix->Inverse();

    // Transform the screen space pick ray into 3D space
    vDirection.x  = v.x * mInverse->_11 + v.y * mInverse->_21 + v.z * mInverse->_31;
    vDirection.y  = v.x * mInverse->_12 + v.y * mInverse->_22 + v.z * mInverse->_32;
    vDirection.z  = v.x * mInverse->_13 + v.y * mInverse->_23 + v.z * mInverse->_33;

    vOrigin.x = mInverse->_41;
    vOrigin.y = mInverse->_42;
    vOrigin.z = mInverse->_43;

    Matrix* Matinverse;
    Matinverse = &mWorldMatrix->Inverse();

    //rayObjOrigin = Matinverse->TransformVectorByMatrix(&vOrigin); function not working

    rayObjOrigin.x = vOrigin.x * Matinverse->_11 + vOrigin.y * Matinverse->_21 + vOrigin.z * Matinverse->_31 + Matinverse->_41;
    rayObjOrigin.y = vOrigin.x * Matinverse->_12 + vOrigin.y * Matinverse->_22 + vOrigin.z * Matinverse->_32 + Matinverse->_42;
    rayObjOrigin.z = vOrigin.x * Matinverse->_13 + vOrigin.y * Matinverse->_23 + vOrigin.z * Matinverse->_33 + Matinverse->_43;

    //rayObjeDirection = Matinverse->TransformVectorNormalByMatrix(&vDirection); function not working
    rayObjeDirection.x = vDirection.x * Matinverse->_11 + vDirection.y * Matinverse->_21 + vDirection.z * Matinverse->_31;
    rayObjeDirection.y = vDirection.x * Matinverse->_12 + vDirection.y * Matinverse->_22 + vDirection.z * Matinverse->_32;
    rayObjeDirection.z = vDirection.x * Matinverse->_13 + vDirection.y * Matinverse->_23 + vDirection.z * Matinverse->_33;

    rayObjeDirection.Normalize();

}

// Now we check to see if we are going through anything
bool Ray::checkCollisionAtBB(BoundingBox* box)
{
    // By default we don't hit
    bool hit = false;

    // First grab the entity's bounding box
    Vector boxPos;
    Vector diff;

    // Now calculate the position of the box
    // We have the two corners of the box so we only need to calculate the average
    boxPos.x = ((box->minX + box->maxX) / 2.0f);
    boxPos.y = ((box->minY + box->maxY) / 2.0f);
    boxPos.z = ((box->minZ + box->maxZ) / 2.0f);

    // Now calculate width and height
    // NOTE: Not sure how to use boxes rather than spheres for checking collision, yet...
    float boxWidth = box->maxX - box->minX;
    float boxLength = box->maxZ - box->minZ;
    float boxHeight = box->maxY - box->minY;

    // Make sure the above values are positive
    if(boxWidth < 0){boxWidth = 0 - boxWidth;}
    if(boxLength < 0){boxLength = 0 - boxLength;}
    if(boxHeight < 0){boxHeight = 0 - boxHeight;}

    // Create a new vector
    diff.x = (this->rayObjOrigin.x - boxPos.x);
    diff.y = (this->rayObjOrigin.y - boxPos.y);
    diff.z = (this->rayObjOrigin.z - boxPos.z);

    // Calculate the dot products
    float dotA = 2.0f * this->rayObjeDirection.DotProduct(diff);
    float dotB = diff.DotProduct(diff) - (boxWidth * boxLength);

    // Discrimant thingy-ma-jiggy, who comes up with this shit...
    float fDiscriminant = (dotA * dotA) - (4.0f * dotB);

    // Check discrimant
    if(fDiscriminant > 0.0f)
    {
        // Square root
        fDiscriminant = sqrtf(fDiscriminant);

        float fSearchA = (-dotA + fDiscriminant) / 2.0f;
        float fSearchB = (-dotA - fDiscriminant) / 2.0f;

        // If it's larger than 0.0f, we've hit something
        if(fSearchA >= 0.0f || fSearchB >= 0.0f)
        {
            // Set to true
            hit = true;
        }
    }

    // Return result
    return hit;
}

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat werkt er niet, waarom werkt dat niet, welke resultaten krijg je, etc.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb nog een keer gekeken en het volgende gebeurd (niet):

ik heb de straal gerendered en het lijkt erop dat hij in ieder geval de waardes niet goed omrekent. de straal gaat namelijk direct naar een entity toe vanuit een wat lijkt willekeurig positie, maar wel veranderd naarmate de positie veranderd.

wat ik wil is dat ik vanuit het midden van mijn scherm "schiet" op een entity en aan de hand daarvan een true of false waarde krijg als ik deze intersect of niet.

ik denk dus dat er toch nog ergens iets fout gaan in de berekeningen van de ray.

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 19-09 10:19
Verwijderd schreef op maandag 16 maart 2009 @ 13:51:
Ik heb nog een keer gekeken en het volgende gebeurd (niet):

ik heb de straal gerendered en het lijkt erop dat hij in ieder geval de waardes niet goed omrekent. de straal gaat namelijk direct naar een entity toe vanuit een wat lijkt willekeurig positie, maar wel veranderd naarmate de positie veranderd.

wat ik wil is dat ik vanuit het midden van mijn scherm "schiet" op een entity en aan de hand daarvan een true of false waarde krijg als ik deze intersect of niet.

ik denk dus dat er toch nog ergens iets fout gaan in de berekeningen van de ray.
Zorg je er wel voor dat je ray omgezet wordt naar screenspace? (Is er trouwens een goede reden om het 3dlib onafhankelijk te houden? Anders kost dit je veel snelheid en veel extra tijd).

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
roy-t schreef op maandag 16 maart 2009 @ 14:17:
[...]


Zorg je er wel voor dat je ray omgezet wordt naar screenspace? (Is er trouwens een goede reden om het 3dlib onafhankelijk te houden? Anders kost dit je veel snelheid en veel extra tijd).
Voor zover ik weet is dit wel het geval, maar gaat het *ergens* niet goed en ik kom er niet achter waar het dus niet goed gaat. het omzetten van screenspace naar modelspace heb ik gedaan aan de hand van verscheidene tutorials die het allemaal op een zo goed als dezelfde manier van elkaar doen met hier en daar een aanpassing om de benodigde waardes goed door te laten geven. als ik tijdens het "schieten" de waardes print dan krijg ik ook de goede waardes terug vanwaar hij behoort te schieten, echter schiet hij niet vanaf de positie, de rotatie daarentegen lijkt wel goed te gaan.

de reden waarom het 3dlib onafhankelijk moet zijn is omdat dit een schoolproject is waarop we verder bouwen op een door andere studenten hiervoor gebouwde engine dus de reden is "omdat het moet van school" wat dus reden genoeg is voor hen ;)