Directx, 3D Objekte mit der Maus auswählen

Antarex

Grünschnabel
Moin,
Ich bin eher als Anfänger einzustufen.

mein Problem ist: wie kann ich kann ich mit der Maus ein 3D-Objekt auswählen?

Am liebsten wäre mir wenn mir das Jemand anhand eines kleinen Beispielprogrammes erklären würde.
Das einzige was ich bisher dazu gefunden habe war ein C-Beispiel, welches mir alledings zu komplex war um durchzublicken.
 
Für einen Anfänger sind Directx-Anwendungen vermutlich nicht der richtige Einstieg, da diese wohl grundsätzlich einige Vorkenntnisse erfordern.

Außerdem schreibst Du nicht, was nun eigentlich Dein Problem ist, ich kann mir wenig unter Deiner Aussage vorstellen.

Grüsse
ronaldh
 
naja Anfänger ..
Ich bin mit VB6 schon etwas vertrauter, würde mich aber immer noch als Anfänger bezeichnen.

Um anspruchsvollere Grafik darzustellen (in 3D) kommt man wohl um Direktx schwer herum. Und damit habe ich jetzt eben angefangen.

Das Problem:
Ich habe mehrere Quader die frei im Raum liegen/schweben.

Code:
Private Type LITVERTEX    
    x As Single    
    y As Single
    z As Single
    color As Long
    Specular As Long
    tu As Single
    tv As Single
End Type

Dim Cube(18, 20, 20) As LITVERTEX

Wobei die erste Dimension die einzelnen Verticen der Cuben sind, die zweite und dritte stehen dann für die Cuben.
Und ich möchte daraus jetzt einen mit der Maus auswählen können.
 
Jo Danke für den Link.
Das darstellen war nicht mein Problem.

Hab jetzt doch recht lange gebraucht um eine Lösung zu finden.
teils direkt (Mousekoordinaten in Weltvektoren) und den Rest holperig aus irgendwelchen c-Quellen übersetzt.
Hier also die Lösung die ich gesucht habe, vielleicht hat ja noch jemand das selbe Problem ;)

aus der Mausposition 2 Vertizen (D3DVECTOR) machen:
Die matrizen sind global
Code:
Sub Conv2Dto3D(Device As Direct3DDevice8, ScreenX, ScreenY, ByRef NearPoint As D3DVECTOR, ByRef FarPoint As D3DVECTOR)
Dim viewp As D3DVIEWPORT8
Dim vec As D3DVECTOR
    Device.GetTransform D3DTS_VIEW, matView
    Device.GetTransform D3DTS_PROJECTION, matProj
    Device.GetTransform D3DTS_WORLD, matWorld
    Device.GetViewport viewp
    D3DXVec3Unproject NearPoint, MakeVector(CSng(ScreenX), CSng(ScreenY), 0), viewp, matProj, matView, matWorld
    D3DXVec3Unproject FarPoint, MakeVector(CSng(ScreenX), CSng(ScreenY), 1), viewp, matProj, matView, matWorld
End Sub

Private Function MakeVector(X As Single, Y As Single, z As Single) As D3DVECTOR
    With MakeVector
        .X = X
        .Y = Y
        .z = z
    End With
End Function

und die Funktionen zur Prüfung ob der Mausvektor durch Dreieck geht:
Code:
Private Function LineHitsPlane(LineA As D3DVECTOR, LineB As D3DVECTOR, Plan As D3DPLANE, ByRef pvOut As D3DVECTOR) As Boolean
Dim vDir As D3DVECTOR
Dim Denominator As Single
Dim s As Single

    D3DXVec3Subtract vDir, LineB, LineA
    Denominator = Plan.a * vDir.X + Plan.b * vDir.Y + Plan.c * vDir.z
    If Abs(Denominator) < 0.0001 Then
        LineHitsPlane = False
        Exit Function
    End If
    s = (-Plan.a * LineA.X - Plan.b * LineA.Y - Plan.c * LineA.z - Plan.d) / Denominator
    If (s < 0#) Then
        LineHitsPlane = False
        Exit Function
    End If
    If (s > 1#) Then
        LineHitsPlane = False
        Exit Function
    End If
    D3DXVec3Scale pvOut, vDir, s
    D3DXVec3Add pvOut, pvOut, LineA
    LineHitsPlane = True
End Function

Private Function LineHitsTriangle(LineA As D3DVECTOR, LineB As D3DVECTOR, p1 As D3DVECTOR, p2 As D3DVECTOR, p3 As D3DVECTOR) As Boolean
Dim Plan As D3DPLANE
Dim vTemp As D3DVECTOR, vTemp2 As D3DVECTOR, vTemp3 As D3DVECTOR
Dim vInter As D3DVECTOR
    
    D3DXPlaneFromPoints Plan, p1, p2, p3
    
    If Not (LineHitsPlane(LineA, LineB, Plan, vInter)) Then
        LineHitsTriangle = False
        Exit Function
    End If
    
    vTemp3 = MakeVector(Plan.a, Plan.b, Plan.c)
    
    D3DXVec3Subtract vTemp2, p1, p2
    D3DXVec3Cross vTemp, vTemp2, vTemp3
    D3DXPlaneFromPointNormal Plan, p1, vTemp
    If D3DXPlaneDotCoord(Plan, vInter) < 0# Then
        LineHitsTriangle = False
        Exit Function
    End If
   
    D3DXVec3Subtract vTemp2, p2, p3
    D3DXVec3Cross vTemp, vTemp2, vTemp3
    D3DXPlaneFromPointNormal Plan, p2, vTemp
    If D3DXPlaneDotCoord(Plan, vInter) < 0# Then
        LineHitsTriangle = False
        Exit Function
    End If
    
    D3DXVec3Subtract vTemp2, p3, p1
    D3DXVec3Cross vTemp, vTemp2, vTemp3
    D3DXPlaneFromPointNormal Plan, p3, vTemp
    If D3DXPlaneDotCoord(Plan, vInter) < 0# Then
        LineHitsTriangle = False
        Exit Function
    End If
    
    LineHitsTriangle = True

End Function

Der Aufruf:
Code:
Dim D3DDevice As Direct3DDevice8
Dim MausVecFar As D3DVECTOR, MausVecNer As D3DVECTOR
Dim TriVec1 As D3DVECTOR, TriVec2 As D3DVECTOR, TriVec3 As D3DVECTOR 'Die koordinaten des Dreiecks


Conv2Dto3D D3DDevice, MousePosX, MousePosY, MausVecFar, MausVecNer

If LineHitsTriangle(MausVecFar, MausVecNer, TriVec1, TriVec2, TriVec3) Then
' entsprechende Maßnahmen
End If
Man muss jetzt nur noch jedes Dreieck welches in Frage kommt überprüfen.

Ich verstehe allerdings nicht warum ich die Dreiecks-Koordinaten nicht noch durch die weltmatrix anpassen muss
Egal, es klappt bei jeder Drehung der weltmatrix.
Ich bin stolz auf mich ;)

btw: dass ich von Matrizen Null Ahnung habe, brauch ich wohl nicht mehr deutlich machen, oder?

Edit: hier das kompilierte Zwischenergebnis
rechte Maustaste: auswählen + special Effect + Mausvektor (sieht man natürlich nur wenn man anschließend zoomt oder dreht - sonst ist nu ein Punkt zu sehen)
linke Maustaste: rotieren
Mausrad : zoom
Prg beenden mit Maustaste 4 - zurücktaste
 

Anhänge

Zuletzt bearbeitet:
Zurück