Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: FAQ - Grafik-/Spieleprogrammierung ::  Fenster in Weltkoordinaten umwandeln     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
Ulli
Unregistrierter




Beitrag Ulli Unregistrierter 22:52:00 16.07.2002   Titel:   Fenster in Weltkoordinaten umwandeln            Zitieren

Ich habs schon n paar mal probiert aber komme einfach nicht weiter: Wie wandle ich die 2D Koordinaten der maus auf einem Fenster in 3D Koordinaten in meinem "Raum" um? :?: Das ganze in OpenGL also bitte keine DX8 Funktionen posten :D
Werbeunterbrechung
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 10:32:00 17.07.2002   Titel:              Zitieren

Kurz gesagt: es geht nicht

Der Mauszeiger hat keine Koordinaten im 3D-Raum, da er nur zweidimensional ist. Du kannst nur einen Strahl vom Kamerapunkt zur Mausposition ziehen, und schauen, was alles draufliegt.


Bye, TGGC

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
Ulli
Unregistrierter




Beitrag Ulli Unregistrierter 11:30:00 17.07.2002   Titel:              Zitieren

"Du kannst nur einen Strahl vom Kamerapunkt zur Mausposition ziehen, und schauen, was alles draufliegt."

Genau das meinte ich ja aber wie mach ich das?
Headhunter
Moderator

Benutzerprofil
Anmeldungsdatum: 20.08.2000
Beiträge: 3567
Beitrag Headhunter Moderator 11:49:00 17.07.2002   Titel:              Zitieren

Hi !

Gibts da nicht was im FAQ ??
Naja, in der DX8 SDK gibts ein tolles Sample dazu.
Wenn du möchtest kann ich dir aber auch etwas Code
zuschicken... Mail mir einfach / poste hier

_________________
(Mod im Spiele&Grafikforum)

Viele Grüße, headhunter
Ulli
Unregistrierter




Beitrag Ulli Unregistrierter 13:10:00 17.07.2002   Titel:              Zitieren

Ich hab jetz extra nochmal in der FAQ nachgeschut aber wieder nix gefunden, wäre nett wenn du mir das angebotene Beispiel zusenden könntest (Jakob-Lang@gmx.de) vieleicht wäre es aber besser es zu posten und den Thread dann ins FAQ zu verschieben.
µ
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.06.2001
Beiträge: 1552
Beitrag µ Mitglied 13:14:00 17.07.2002   Titel:              Zitieren

gluUnProject heißt die Funktion.

Siehe hier: http://www.eecs.tulane.edu/www/graphics/doc/OpenGL-Man-Pages/gluUnProject.html

Die erwartet aber neben winx und winy Koordinaten noch einen winz Parameter. Den kannst du mit glReadPixels bestimmen (Depth-Buffer auslesen)
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 13:22:00 17.07.2002   Titel:              Zitieren

Zitat:
Original erstellt von <Ulli>:
"Du kannst nur einen Strahl vom Kamerapunkt zur Mausposition ziehen, und schauen, was alles draufliegt."

Genau das meinte ich ja aber wie mach ich das?


Also das würd ich so machen:
Du bestimmst das Rechteck, das von der near clipping Plane sichtbar ist (bzw. wenigsten 3 seiner Eckpunkte). Dazu brauchst du ja einfach nur die planes des view frustrums entsprechend schneiden oder du machst eine Rücktransformation der entsprechenden Eckpunkte des view frustrums. Ich seh, schon, das kapiert keiner, Zeichnung:
http://www.fh-merseburg.de/~roesch/trash/raypick.jpg

Also du bekommst jetzt O, das ist der Punkt der near clipping Plane, der nach (0,0) auf den Monitor transformiert wurde. Ausserdem können A und B bestimmt werden, die das Rechteck aufspannen. Jetzt skalierst du A und B, so wie die Mausposition auf den Bildschirm ist (z.B. in der Mitte mal 0.5) und bestimmst so den Durchstosspunkt. Den Punkt mit V (die Kameraposition) verbinden, fertig!

P.S.: spätenstens jetzt sollte es was im FAQ geben ;)


Bye, TGGC

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
Rumex
Mitglied

Benutzerprofil
Anmeldungsdatum: 19.12.2001
Beiträge: 24
Beitrag Rumex Mitglied 13:22:00 17.07.2002   Titel:              Zitieren

Hi Headhunter,

kannste es mir auch zuschicken falls du es net postest?
sowelu@gmx.de

_________________
mfg Rumex

Wer aufgibt verliert, wer nicht aufgibt, kann verlieren.
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 18:26:00 21.07.2002   Titel:              Zitieren

@Headhunter: Vorschlag, poste dein Code noch hier her und verschieb das Teil mal in die FAQ, oder isses das nich wert?

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
RPD
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.05.2001
Beiträge: 1344
Beitrag RPD Mitglied 19:04:00 21.07.2002   Titel:              Zitieren

da braucht er nicht den ganzen code posten, dass sample ist beim sdk dabei und zwar hier:

(SDK root)\Samples\Multimedia\Direct3D\Pick
:)

_________________
Gruß
RPD
µ
Mitglied

Benutzerprofil
Anmeldungsdatum: 14.06.2001
Beiträge: 1552
Beitrag µ Mitglied 19:21:00 21.07.2002   Titel:              Zitieren

Öh, wieso redet hier jeder von der DXSDK ?

Zitat:

Das ganze in OpenGL also bitte keine DX8 Funktionen posten
RPD
Mitglied

Benutzerprofil
Anmeldungsdatum: 03.05.2001
Beiträge: 1344
Beitrag RPD Mitglied 19:28:00 21.07.2002   Titel:              Zitieren

:rolleyes:
hab ich garnicht mitgekriegt, wiedermal zu faul alles zu lesen...
naja, aber für die faq kanns ja nicht schaden...

_________________
Gruß
RPD
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 20:07:00 21.07.2002   Titel:              Zitieren

Ich habs auch so verstanden als hätte er 'nen anderen Source (für OpenGL tausglich). Ausserdem wäre ein Sprachen und Api unabhängiger Ansatz nicht sowieso wertvoller, zumindest für die FAQ?


Bye, TGGC

[ Dieser Beitrag wurde am 21.07.2002 um 20:09 Uhr von TGGC editiert. ]

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
Headhunter
Moderator

Benutzerprofil
Anmeldungsdatum: 20.08.2000
Beiträge: 3567
Beitrag Headhunter Moderator 13:40:00 23.07.2002   Titel:              Zitieren

Hi !

Ich hab wirklich ne vollkommen Apiunabhängige
klasse dafür (eigene Matrix, Vektoren, BBox ... Klasse,
kein Zugriff auf D3D benötigt)

Leider habe ich im moment damit ein kleines Problem :
Es wird immer das Falsche ausgewählt, bzw es werden
Objekte ausgewählt die eigentlich gar nicht in der BBox
sind...
Ich bin völlig ratlos, versuche aber das Problem zu beheben.
Dann kann ich den Source hier gerne posten :-)

_________________
(Mod im Spiele&Grafikforum)

Viele Grüße, headhunter
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 10:53:00 31.07.2002   Titel:              Zitieren

Wenn das noch lange dauert ist der Thread weg, und wir haben wieder nix für die FAQ :(

Also fix!


Bye, TGGC

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
Headhunter
Moderator

Benutzerprofil
Anmeldungsdatum: 20.08.2000
Beiträge: 3567
Beitrag Headhunter Moderator 14:03:00 31.07.2002   Titel:              Zitieren

Hi !

Ok, ok, ich hab mal geguckt was der Fehler sein kann...
Leider bin ich _absolut_ ratlos wo das Problem ist...

Folgende Probleme :

D3DXMATRIX matrix;
GetRenderState (D3DRS_WORLD/D3DRS_VIEW/D3DRS_PROJECTION, &matrix);

Klappt NICHT !! Jedes mal bekomme ich D3DERR_INVALIDCALL zurück.
Der Fehler tritt aber nur in meiner Rayklasse auf, die auf meine
D3D Klassezugreift.

Ich kann mal gucken, ich hab glaubich noch ein älteres
Sample dazu, allerdings ohne meine eigene Matrixklasse...

_________________
(Mod im Spiele&Grafikforum)

Viele Grüße, headhunter
TGGC
Mitglied

Benutzerprofil
Anmeldungsdatum: 01.02.2001
Beiträge: 1895
Beitrag TGGC Mitglied 14:15:00 31.07.2002   Titel:              Zitieren

Zitat:
Original erstellt von Headhunter:
Hi !

Ok, ok, ich hab mal geguckt was der Fehler sein kann...
Leider bin ich _absolut_ ratlos wo das Problem ist...

Folgende Probleme :

D3DXMATRIX matrix;
GetRenderState (D3DRS_WORLD/D3DRS_VIEW/D3DRS_PROJECTION, &matrix);

Klappt NICHT !! Jedes mal bekomme ich D3DERR_INVALIDCALL zurück.
Der Fehler tritt aber nur in meiner Rayklasse auf, die auf meine
D3D Klassezugreift.

Ich kann mal gucken, ich hab glaubich noch ein älteres
Sample dazu, allerdings ohne meine eigene Matrixklasse...

Merk dir doch einfach die Matrizen, wenn du sie setzt?! Bei Gelegenheit schau ich auch nochmal in die SDK Doku dazu...


Bye, TGGC

_________________
Was wirklich zählt, ist klar.
http://www.fh-merseburg.de/~roesch | ICQ#: 109019884
Headhunter
Moderator

Benutzerprofil
Anmeldungsdatum: 20.08.2000
Beiträge: 3567
Beitrag Headhunter Moderator 11:39:00 01.08.2002   Titel:              Zitieren

Hi !

Hier ist der Code meiner Rayclass, mit zusätzlichen Comments...
Bei Fragen könnt ihr hier posten / mir mailen
Der Code stammt wie gesagt aus meiner alten Engine,
OHNE meine Matrixklasse, d.h. ich greife auf ein
paar D3DX Funktionen zu, sollte aber kein Problem sein
die durch andere zu ersetzen...

Ich hoffe das Forum kann so lange Posts darstellen :-)

(Hehe, wenn ich euch ärgen will würd ich jetzt Syntaxcoloring
ausscalten *gg*)

C/C++ Code:
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
---------------------------------------------------------------------------
//smartbbox.h
class CSmartBBox
{
    CSmartVector min, max;
};
---------------------------------------------------------------------------
//smartplane.h
class CSmartPlane
{
public :
    CSmartVector    n;
    float           d;
};
---------------------------------------------------------------------------
#include
"smartplane.h"
#include
"smartbbox.h"
#include
"smartvector.h"
#include
"smartinput.h"
#include
"smartd3d.h"
//smartray.h
class CSmartRay
{
public :

    //hiermit wird die Rayklasse m.h. der Mauskoordinaten erstellt.
    //d.h. man hat dann einen Strahl den man für Intersection tests verwenden
    //kann ("auf etwas in der 3D scene klicken")

    void FillFromMouse ();
   
    //naja, checkt ob der Ray ein triangle trifft,
    //v MUSS ein array der größe 3 sein (CSmartVector* v = new CSmartVector[3];)
    //in "t" kommt die Entfernung m_start->Punkt auf dem Triangle wo der Ray "reintraf"

    BOOL IntersectTriangle (CSmartVector* v,float& t) const;    
   
    //hiermit kann man testen ob der Ray eine Boundingbox schneidet.
    //wenn ja wird TRUE returned, in "in" kommt die Distanz m_start->Intersection point,
    //in "out" kommt die Distanz von m_start->Punkt wo der Ray AUS der Box kommt

    BOOL IntersectBoundingBox (CSmartBBox&b, float& in, float& out) const;  
   
    //intersection von dem Ray und ner Ebene, ist nüztlich für Collision detection
    BOOL IntersectPlane (const CSmartPlane& p) const;  

    //das hier ist der Startpunkt des Rays in Weltkoordinaten
    //CSmartVector ist ne Vektorklasse (*echt* ??)

    CSmartVector            m_start;
    //das ist die Richtung in die der Ray "zeigt". Dieser Vektor
    //ist normalisiert

    CSmartVector            m_dir;
};
---------------------------------------------------------------------------
//smartray.cpp
BOOL CSmartRay::FillFromMouse ()
{
    //in rx und ry kommt die Auflösung bzw die Größe des Fensters
    //GetResolution ermittelt die Werte indem es einfach die
    //breite und höhe des Backbuffer returned

    int rx,ry;
    g_smartD3D.GetResolution (rx,ry);
    //nun holen wir uns die Projection matrix von D3D
    //in meiner neuen Engine gibts hier einen Fehler : D3DERR_INVALIDCALL,
    //hier klappt es aber einwandfrei

    D3DXMATRIX matProj;
    g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_PROJECTION, &matProj);

    //nun wandeln wir die Mausposition (von DirectInput in diesem Fall)
    //in einen 3D Punkt um

    CSmartVector v;
    v.x =  (((2.0f * g_smartInput.m_x) / rx) - 1.0f) / matProj._11;
    v.y = -(((2.0f * g_smartInput.m_y) / ry) - 1.0f) / matProj._22;
    v.z =  1.0f;

    //hier holen wir uns die Viewmatrix und invertieren sie
    D3DXMATRIX matView, m;
    g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_VIEW, &matView);
    D3DXMatrixInverse (&m, NULL, &matView);

    //jetzt wird die Raydirection m.h. der invertierten Viewmatrix
    //ermittelt.

    m_dir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
    m_dir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
    m_dir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
    //und die Startposition gesetzt
    m_start.x = m._41;
    m_start.y = m._42;
    m_start.z = m._43;
    m_dir.Normalize ();
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectBBox (CSmartBBox&b, float& enter, float& leave)
{
    //der Algorithmus den ich hier verwende heißt "Kay and Kayjia "slab" method"
    //komischer Name :-)
    //ich hab hier keine Comments zu der Funktion, da ich durch die Mathe
    //nicht ganz durchblicke...

   
    float tnear = -99999.0f;
    float tfar =   99999.0f;
    for (int i=0; i<3; i++)
    {
        //ich habe bei meinen Vektoren den operator [] überladen
        //Bsp :
        //CSmartVector v;
        //v[0] = 2; // v.x = 3;
        //v[1] = 3; // v.y = 2;
        //v[2] = 0; // v.z = 0;

        float origin = m_start[i];
        float direction = m_dir[i];
        float mmin = b.min[i];
        float mmax = b.max[i];
       
        if (direction)
        {
            direction = 1.0f / direction;
            float t1 = (mmin - origin) * direction;
            float t2 = (mmax - origin) * direction;
           
            if (t1 > t2)
            {
                if (t2 > tnear) tnear = t2;
                if (t1 < tfar) tfar = t1;
            }
            else
            {
                if (t1 > tnear) tnear = t1;
                if (t2 < tfar) tfar = t2;
            }
       
            //keine intersection
            if (tnear > tfar &#0124;&#0124; tfar < 0.0f)
                return FALSE;
        }
        else
        {
            //wieder keine Intersection
            if (rigin < mmin &#0124;&#0124; origin > mmax)
                return FALSE;
        }
    }

    //Werte speichern
    enter = tnear;
    leave = tfar;

    //ray hits box
    return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectTriangle (CSmartVector* vv,float& t)
{
    //diese Methode wurde von Möller entwickelt (k.a. wie der mit
    //Vornamen heißt, er ist auf jeden Fall der größte Theoretiker
    //was Mathematik usw bei Games angeht, Einfach mal was googlen...
    //der Code stammt btw aus dem DX8 SDK, wo er super implementiert wurde !
   
    //keinen NULLPointer annehmen !

    assert (vv != NULL);
   
    float u,v;
    //die Eckvectoren des Triangles finden
    CSmartVector edge1 = vv[1]- vv[0];
    CSmartVector edge2 = vv[2]- vv[0];

    //determinant berechnen, wird auch für U (texturkoordinate) verwendet
    CSmartVector pvec;
    pvec=CrossProduct(m_dir, edge2);
    //wenn der determinant fast 0 ist, ist der Ray paralell zum Triangle (=> keine Intersection)
    float det = DotProduct(edge1, pvec);
    if (det < 0.0001f)
        return FALSE;

    //distanz von vv[0] zu m_start berechnen
    CSmartVector tvec = m_start - vv[0];

    //berechnen U, und check ob der Ray überhaupt treffen kann
    u = DotProduct(tvec,pvec);
    if (u < 0.0f &#0124;&#0124; u > det)
        return FALSE;

    //gleich berechnen wir V (texturkoordinate)
    CSmartVector qvec;
    qvec=CrossProduct(tvec, edge1);

    //so ähnlich wie ein paar Zeilen oben :-)
    v = DotProduct(m_dir, qvec);
    if (v < 0.0f &#0124;&#0124; u + v > det)
        return FALSE;

    //distanz berechnen
    t = DotProduct(edge2, qvec);
    float fInvDet = 1.0f / det;
    t *= fInvDet;

    //juhu ! intersection
    return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectPlane (const CSmartPlane& p) const
{
    //diesmal ziemlich kurz, he ?
    float dista = m_start.Length ();
    float distb = (m_start + m_dir).GetLength();
    if ((dista > 0.0f)&&(distb < 0.0f)) return TRUE;
    if ((dista < 0.0f)&&(distb > 0.0f)) return TRUE;
    return FALSE;
}
---------------------------------------------------------------------------
C/C++ Code:
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
---------------------------------------------------------------------------
//smartbbox.h
class CSmartBBox
{
CSmartVector min, max;
};
---------------------------------------------------------------------------
//smartplane.h
class CSmartPlane
{
public :
CSmartVector n;
float d;
};
---------------------------------------------------------------------------
#include
"smartplane.h"
#include
"smartbbox.h"
#include
"smartvector.h"
#include
"smartinput.h"
#include
"smartd3d.h"
//smartray.h
class CSmartRay
{
public :

//hiermit wird die Rayklasse m.h. der Mauskoordinaten erstellt.
//d.h. man hat dann einen Strahl den man für Intersection tests verwenden
//kann ("auf etwas in der 3D scene klicken")

void FillFromMouse ();

//naja, checkt ob der Ray ein triangle trifft,
//v MUSS ein array der größe 3 sein (CSmartVector* v = new CSmartVector[3];)
//in "t" kommt die Entfernung m_start->Punkt auf dem Triangle wo der Ray "reintraf"

BOOL IntersectTriangle (CSmartVector* v,float& t) const;

//hiermit kann man testen ob der Ray eine Boundingbox schneidet.
//wenn ja wird TRUE returned, in "in" kommt die Distanz m_start->Intersection point,
//in "out" kommt die Distanz von m_start->Punkt wo der Ray AUS der Box kommt

BOOL IntersectBoundingBox (CSmartBBox&b, float& in, float& out) const;

//intersection von dem Ray und ner Ebene, ist nüztlich für Collision detection
BOOL IntersectPlane (const CSmartPlane& p) const;

//das hier ist der Startpunkt des Rays in Weltkoordinaten
//CSmartVector ist ne Vektorklasse (*echt* ??)

CSmartVector m_start;
//das ist die Richtung in die der Ray "zeigt". Dieser Vektor
//ist normalisiert

CSmartVector m_dir;
};
---------------------------------------------------------------------------
//smartray.cpp
BOOL CSmartRay::FillFromMouse ()
{
//in rx und ry kommt die Auflösung bzw die Größe des Fensters
//GetResolution ermittelt die Werte indem es einfach die
//breite und höhe des Backbuffer returned

int rx,ry;
g_smartD3D.GetResolution (rx,ry);
//nun holen wir uns die Projection matrix von D3D
//in meiner neuen Engine gibts hier einen Fehler : D3DERR_INVALIDCALL,
//hier klappt es aber einwandfrei

D3DXMATRIX matProj;
g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_PROJECTION, &matProj);

//nun wandeln wir die Mausposition (von DirectInput in diesem Fall)
//in einen 3D Punkt um

CSmartVector v;
v.x = (((2.0f * g_smartInput.m_x) / rx) - 1.0f) / matProj._11;
v.y = -(((2.0f * g_smartInput.m_y) / ry) - 1.0f) / matProj._22;
v.z = 1.0f;

//hier holen wir uns die Viewmatrix und invertieren sie
D3DXMATRIX matView, m;
g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_VIEW, &matView);
D3DXMatrixInverse (&m, NULL, &matView);

//jetzt wird die Raydirection m.h. der invertierten Viewmatrix
//ermittelt.

m_dir.x = v.x*m._11 + v.y*m._21 + v.z*m._31;
m_dir.y = v.x*m._12 + v.y*m._22 + v.z*m._32;
m_dir.z = v.x*m._13 + v.y*m._23 + v.z*m._33;
//und die Startposition gesetzt
m_start.x = m._41;
m_start.y = m._42;
m_start.z = m._43;
m_dir.Normalize ();
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectBBox (CSmartBBox&b, float& enter, float& leave)
{
//der Algorithmus den ich hier verwende heißt "Kay and Kayjia "slab" method"
//komischer Name :-)
//ich hab hier keine Comments zu der Funktion, da ich durch die Mathe
//nicht ganz durchblicke...


float tnear = -99999.0f;
float tfar = 99999.0f;
for (int i=0; i<3; i++)
{
//ich habe bei meinen Vektoren den operator [] überladen
//Bsp :
//CSmartVector v;
//v[0] = 2; // v.x = 3;
//v[1] = 3; // v.y = 2;
//v[2] = 0; // v.z = 0;

float origin = m_start[i];
float direction = m_dir[i];
float mmin = b.min[i];
float mmax = b.max[i];

if (direction)
{
direction = 1.0f / direction;
float t1 = (mmin - origin) * direction;
float t2 = (mmax - origin) * direction;

if (t1 > t2)
{
if (t2 > tnear) tnear = t2;
if (t1 < tfar) tfar = t1;
}
else
{
if (t1 > tnear) tnear = t1;
if (t2 < tfar) tfar = t2;
}

//keine intersection
if (tnear > tfar &#0124;&#0124; tfar < 0.0f)
return FALSE;
}
else
{
//wieder keine Intersection
if (rigin < mmin &#0124;&#0124; origin > mmax)
return FALSE;
}
}

//Werte speichern
enter = tnear;
leave = tfar;

//ray hits box
return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectTriangle (CSmartVector* vv,float& t)
{
//diese Methode wurde von Möller entwickelt (k.a. wie der mit
//Vornamen heißt, er ist auf jeden Fall der größte Theoretiker
//was Mathematik usw bei Games angeht, Einfach mal was googlen...
//der Code stammt btw aus dem DX8 SDK, wo er super implementiert wurde !

//keinen NULLPointer annehmen !

assert (vv != NULL);

float u,v;
//die Eckvectoren des Triangles finden
CSmartVector edge1 = vv[1]- vv[0];
CSmartVector edge2 = vv[2]- vv[0];

//determinant berechnen, wird auch für U (texturkoordinate) verwendet
CSmartVector pvec;
pvec=CrossProduct(m_dir, edge2);
//wenn der determinant fast 0 ist, ist der Ray paralell zum Triangle (=> keine Intersection)
float det = DotProduct(edge1, pvec);
if (det < 0.0001f)
return FALSE;

//distanz von vv[0] zu m_start berechnen
CSmartVector tvec = m_start - vv[0];

//berechnen U, und check ob der Ray überhaupt treffen kann
u = DotProduct(tvec,pvec);
if (u < 0.0f &#0124;&#0124; u > det)
return FALSE;

//gleich berechnen wir V (texturkoordinate)
CSmartVector qvec;
qvec=CrossProduct(tvec, edge1);

//so ähnlich wie ein paar Zeilen oben :-)
v = DotProduct(m_dir, qvec);
if (v < 0.0f &#0124;&#0124; u + v > det)
return FALSE;

//distanz berechnen
t = DotProduct(edge2, qvec);
float fInvDet = 1.0f / det;
t *= fInvDet;

//juhu ! intersection
return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectPlane (const CSmartPlane& p) const
{
//diesmal ziemlich kurz, he ?
float dista = m_start.Length ();
float distb = (m_start + m_dir).GetLength();
if ((dista > 0.0f)&&(distb < 0.0f)) return TRUE;
if ((dista < 0.0f)&&(distb > 0.0f)) return TRUE;
return FALSE;
}
---------------------------------------------------------------------------
C/C++ Code:
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
---------------------------------------------------------------------------
//smartbbox.h
class CSmartBBox
{
    CSmartVector min, max;
};
---------------------------------------------------------------------------
//smartplane.h
class CSmartPlane
{
public :
    CSmartVector    n;
    float           d;
};
---------------------------------------------------------------------------
#include
"smartplane.h"
#include
"smartbbox.h"
#include
"smartvector.h"
#include
"smartinput.h"
#include
"smartd3d.h"
//smartray.h
class CSmartRay
{
public :

    //hiermit wird die Rayklasse m.h. der Mauskoordinaten erstellt.
    //d.h. man hat dann einen Strahl den man für Intersection tests verwenden
    //kann ("auf etwas in der 3D scene klicken")

    void FillFromMouse ();
   
    //naja, checkt ob der Ray ein triangle trifft,
    //v MUSS ein array der größe 3 sein (CSmartVector* v = new CSmartVector[3];)
    //in "t" kommt die Entfernung m_start->Punkt auf dem Triangle wo der Ray "reintraf"

    BOOL IntersectTriangle (CSmartVector* v,float& t) const;    
   
    //hiermit kann man testen ob der Ray eine Boundingbox schneidet.
    //wenn ja wird TRUE returned, in "in" kommt die Distanz m_start->Intersection point,
    //in "out" kommt die Distanz von m_start->Punkt wo der Ray AUS der Box kommt

    BOOL IntersectBoundingBox (CSmartBBox&b, float& in, float& out) const;  
   
    //intersection von dem Ray und ner Ebene, ist nüztlich für Collision detection
    BOOL IntersectPlane (const CSmartPlane& p) const;  

    //das hier ist der Startpunkt des Rays in Weltkoordinaten
    //CSmartVector ist ne Vektorklasse (*echt* ??)

    CSmartVector            m_start;
    //das ist die Richtung in die der Ray "zeigt". Dieser Vektor
    //ist normalisiert

    CSmartVector            m_dir;
};
---------------------------------------------------------------------------
//smartray.cpp
BOOL CSmartRay::FillFromMouse ()
{
    //in rx und ry kommt die Auflösung bzw die Größe des Fensters
    //GetResolution ermittelt die Werte indem es einfach die
    //breite und höhe des Backbuffer returned

    int rx,ry;
    g_smartD3D.GetResolution (rx,ry);
    //nun holen wir uns die Projection matrix von D3D
    //in meiner neuen Engine gibts hier einen Fehler : D3DERR_INVALIDCALL,
    //hier klappt es aber einwandfrei

    D3DXMATRIX matProj;
    g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_PROJECTION, &matProj);

    //nun wandeln wir die Mausposition (von DirectInput in diesem Fall)
    //in einen 3D Punkt um

    CSmartVector v;
    v.x =  (((2.0f * g_smartInput.m_x) / rx) - 1.0f) / matProj._11;
    v.y = -(((2.0f * g_smartInput.m_y) / ry) - 1.0f) / matProj._22;
    v.z =  1.0f;

    //hier holen wir uns die Viewmatrix und invertieren sie
    D3DXMATRIX matView, m;
    g_smartD3D.GetD3DDevice()->GetTransform (D3DTS_VIEW, &matView);
    D3DXMatrixInverse (&m, NULL, &matView);

    //jetzt wird die Raydirection m.h. der invertierten Viewmatrix
    //ermittelt.

    m_dir.x  = v.x*m._11 + v.y*m._21 + v.z*m._31;
    m_dir.y  = v.x*m._12 + v.y*m._22 + v.z*m._32;
    m_dir.z  = v.x*m._13 + v.y*m._23 + v.z*m._33;
    //und die Startposition gesetzt
    m_start.x = m._41;
    m_start.y = m._42;
    m_start.z = m._43;
    m_dir.Normalize ();
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectBBox (CSmartBBox&b, float& enter, float& leave)
{
    //der Algorithmus den ich hier verwende heißt "Kay and Kayjia "slab" method"
    //komischer Name :-)
    //ich hab hier keine Comments zu der Funktion, da ich durch die Mathe
    //nicht ganz durchblicke...

   
    float tnear = -99999.0f;
    float tfar =   99999.0f;
    for (int i=0; i<3; i++)
    {
        //ich habe bei meinen Vektoren den operator [] überladen
        //Bsp :
        //CSmartVector v;
        //v[0] = 2; // v.x = 3;
        //v[1] = 3; // v.y = 2;
        //v[2] = 0; // v.z = 0;

        float origin = m_start[i];
        float direction = m_dir[i];
        float mmin = b.min[i];
        float mmax = b.max[i];
       
        if (direction)
        {
            direction = 1.0f / direction;
            float t1 = (mmin - origin) * direction;
            float t2 = (mmax - origin) * direction;
           
            if (t1 > t2)
            {
                if (t2 > tnear) tnear = t2;
                if (t1 < tfar) tfar = t1;
            }
            else
            {
                if (t1 > tnear) tnear = t1;
                if (t2 < tfar) tfar = t2;
            }
       
            //keine intersection
            if (tnear > tfar &#0124;&#0124; tfar < 0.0f)
                return FALSE;
        }
        else
        {
            //wieder keine Intersection
            if (rigin < mmin &#0124;&#0124; origin > mmax)
                return FALSE;
        }
    }

    //Werte speichern
    enter = tnear;
    leave = tfar;

    //ray hits box
    return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectTriangle (CSmartVector* vv,float& t)
{
    //diese Methode wurde von Möller entwickelt (k.a. wie der mit
    //Vornamen heißt, er ist auf jeden Fall der größte Theoretiker
    //was Mathematik usw bei Games angeht, Einfach mal was googlen...
    //der Code stammt btw aus dem DX8 SDK, wo er super implementiert wurde !
   
    //keinen NULLPointer annehmen !

    assert (vv != NULL);
   
    float u,v;
    //die Eckvectoren des Triangles finden
    CSmartVector edge1 = vv[1]- vv[0];
    CSmartVector edge2 = vv[2]- vv[0];

    //determinant berechnen, wird auch für U (texturkoordinate) verwendet
    CSmartVector pvec;
    pvec=CrossProduct(m_dir, edge2);
    //wenn der determinant fast 0 ist, ist der Ray paralell zum Triangle (=> keine Intersection)
    float det = DotProduct(edge1, pvec);
    if (det < 0.0001f)
        return FALSE;

    //distanz von vv[0] zu m_start berechnen
    CSmartVector tvec = m_start - vv[0];

    //berechnen U, und check ob der Ray überhaupt treffen kann
    u = DotProduct(tvec,pvec);
    if (u < 0.0f &#0124;&#0124; u > det)
        return FALSE;

    //gleich berechnen wir V (texturkoordinate)
    CSmartVector qvec;
    qvec=CrossProduct(tvec, edge1);

    //so ähnlich wie ein paar Zeilen oben :-)
    v = DotProduct(m_dir, qvec);
    if (v < 0.0f &#0124;&#0124; u + v > det)
        return FALSE;

    //distanz berechnen
    t = DotProduct(edge2, qvec);
    float fInvDet = 1.0f / det;
    t *= fInvDet;

    //juhu ! intersection
    return TRUE;
}
---------------------------------------------------------------------------
BOOL CSmartRay::IntersectPlane (const CSmartPlane& p) const
{
    //diesmal ziemlich kurz, he ?
    float dista = m_start.Length ();
    float distb = (m_start + m_dir).GetLength();
    if ((dista > 0.0f)&&(distb < 0.0f)) return TRUE;
    if ((dista < 0.0f)&&(distb > 0.0f)) return TRUE;
    return FALSE;
}
---------------------------------------------------------------------------

_________________
(Mod im Spiele&Grafikforum)

Viele Grüße, headhunter
C/C++ Forum :: FAQ - Grafik-/Spieleprogrammierung ::  Fenster in Weltkoordinaten umwandeln   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.