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

10.06.2012, 17:50

"Picking" - D3DXIntersect (C++ DirectX9)

Hallo zusammen,

ich würde ganz gerne aus einer Reihe von Models (liegen als Mesh vor) jenes auf das der Spieler mit der Maus zeigt markieren. (Ähnliches Prinzip wie in dem Spiel Minecraft). Mit meinem bisherigen Quellcode funktioniert das auch schon ganz gut. Meine Objekte liegen in einer Liste vor und werden dann nacheinander gerendert. Vor dem Rendern wird die Methode Pick() aufgerufen. Die Objekte werden dann als Wireframe gerendert, wenn sie "getroffen" werden. Leider hat das ganze noch den Nachteil, das schonmal mehrere Objekte auf einmal markiert werden, es darf aber immer nur max. ein Objekt markiert sein. Gibt es eine Möglichkeit den Intersect bei dem ersten Treffer abzubrechen? So dass dahinter liegende Objekte gar nicht mehr geprüft werden.

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
void MeshModel::Pick()
{
    // get the current transform matrices
    D3DXMATRIX p_matProjection, p_matView, p_matWorld, p_matInverse;
    g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &p_matProjection);
    g_pd3dDevice->GetTransform(D3DTS_VIEW, &p_matView);
    g_pd3dDevice->GetTransform(D3DTS_WORLD, &p_matWorld);

    // use the mouse coordinates to get the mouse angle
    POINT MousePos;
    GetCursorPos(&MousePos);
    float xAngle = (((2.0f * MousePos.x) / EngineManager::width) - 1.0f) / p_matProjection(0, 0);
    float yAngle = (((-2.0f * MousePos.y) / EngineManager::height) + 1.0f) / p_matProjection(1, 1);

    D3DXVECTOR3 origin, direction;
    origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    direction = D3DXVECTOR3(xAngle, yAngle, 1.0f);

    // find the inverse matrix
    D3DXMatrixInverse(&p_matInverse, NULL, &(p_matWorld * p_matView));

    // convert origin and direction into model space
    D3DXVec3TransformCoord(&origin, &origin, &p_matInverse);
    D3DXVec3TransformNormal(&direction, &direction, &p_matInverse);
    D3DXVec3Normalize(&direction, &direction);

    // detect picking
    BOOL hit;
    float dist = 0;
    D3DXIntersect(mesh, &origin, &direction, &hit, NULL, NULL, NULL, &dist, NULL, NULL);
    
    if(hit && dist < EngineManager::marked && dist < 10)
    {
        g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
        EngineManager::marked=dist;
    }
    
    else
    {
        g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
        EngineManager::marked=1000;
    }
    
}


Viele Grüße
Daniel Weber

2

10.06.2012, 17:55

hatte gerade einen Geistesblitz. Ich markiere einfach pro Listendurchgang das zuerst getroffene Objekt. Nach dem Rendern aller Objekte setze ich diese markierung wieder auf 0. Fertig :)

EDIT:
naja ganz war es das noch nicht:
Bei einigen Objekten wird das dahinter liegende markiert, scheinbar, weil es in der Liste als erstes gerendert wird, somit wird das auch als erstes markiert... doof :/

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »daniel.weber« (10.06.2012, 18:53)