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
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.
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
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.
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 ;)
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. ]
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 :-)
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*)
---------------------------------------------------------------------------
//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...
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 || tfar < 0.0f)
return FALSE;
}
else
{
//wieder keine Intersection if (rigin < mmin || 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 !
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 || 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 || u + v > det)
return FALSE;
//distanz berechnen
t = DotProduct(edge2, qvec);
float fInvDet = 1.0f / det;
t *= fInvDet;
---------------------------------------------------------------------------
//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...
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 || tfar < 0.0f)
return FALSE;
}
else
{
//wieder keine Intersection if (rigin < mmin || 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 !
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 || 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 || u + v > det)
return FALSE;
//distanz berechnen
t = DotProduct(edge2, qvec);
float fInvDet = 1.0f / det;
t *= fInvDet;
---------------------------------------------------------------------------
//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...
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 || tfar < 0.0f)
return FALSE;
}
else
{
//wieder keine Intersection if (rigin < mmin || 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 !
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 || 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 || u + v > det)
return FALSE;
//distanz berechnen
t = DotProduct(edge2, qvec);
float fInvDet = 1.0f / det;
t *= fInvDet;
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.
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.