Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
OpenGL(OpenTK) 3d Koordinaten zu Client Koordinaten vise versa
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 655
Herkunft: Hamburg

Themenstarter:

OpenGL(OpenTK) 3d Koordinaten zu Client Koordinaten vise versa

beantworten | zitieren | melden

Hallo,

ich möchte Schaltflächen in OpenGL(OpenTK) erstellen.
Jetzt muss ich herausfinden, wann sich die Maus über meiner Schalfläche befindet.
Dazu bräuchte ich die 2d Client Koordinaten meines 3d Vectors. Wie ist es möglich ?
Auch anderes rum wäre es sehr Praktisch also 2d Client zu 3d. Würde mich über eure Hilfe sehr freuen.
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5963
Herkunft: Leipzig

beantworten | zitieren | melden

Hi Ayke,

dir ist sicherlich bewußt, daß es keine eindeutige Umrechnung von 2D- in 3D-Koordinaten geben kann. Ein (Maus-)Punkt in 2D stellt immer einen Strahl in 3D dar (bestehend aus 2 Vektoren). Du kannst dir also eine Mausposition als Strahl darstellen lassen, ausgehend von der Kameraposition. Damit kannst du dann gegen Bounding Volumes prüfen, ob der Strahl dein Objekt trifft oder nicht.

Andersherum ist die Konvertierung einfacher. Mit Hilfe der ViewProjectionMatrix kannst du einfach einen 3D-Punkt in 2D umrechnen.

Christian
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 655
Herkunft: Hamburg

Themenstarter:

beantworten | zitieren | melden

Hallo MrSparkle,
danke für den Leitfaden. Hilft mir bestimmt weiter.
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 655
Herkunft: Hamburg

Themenstarter:

beantworten | zitieren | melden

        public static Vector3 ClientToWorld(int x, int y)
        {
            var viewport = new int[4];
            Matrix4 modelviewMatrix, projectionMatrix;
            GL.GetFloat(GetPName.ModelviewMatrix, out modelviewMatrix);
            GL.GetFloat(GetPName.ProjectionMatrix, out projectionMatrix);
            GL.GetInteger(GetPName.Viewport, viewport);

            var t = new float[1];
            GL.ReadPixels(x, Properties.ViewProperties.ViewPortHeight - y, 1, 1, PixelFormat.DepthComponent, PixelType.Float, t);

            return UnProject(new Vector3(x, viewport[3] - y, t[0]), modelviewMatrix, projectionMatrix, viewport);
        }

        private static Vector3 UnProject(Vector3 screen, Matrix4 view, Matrix4 projection, IList<int> viewPort)
        {
            var pos = new Vector4();

            pos.X = (screen.X - viewPort[0]) / viewPort[2] * 2.0f - 1.0f;
            pos.Y = (screen.Y - viewPort[1]) / viewPort[3] * 2.0f - 1.0f;
            pos.Z = screen.Z * 2.0f - 1.0f;
            pos.W = 1.0f;

            var pos2 = Vector4.Transform(pos, Matrix4.Invert(Matrix4.Mult(view, projection)));
            var posOut = new Vector3(pos2.X, pos2.Y, pos2.Z);

            return posOut / pos2.W;
        }
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Ayke am .
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 655
Herkunft: Hamburg

Themenstarter:

beantworten | zitieren | melden

Performance fresser... kanns doch nicht sein. Wie machen das den die Professionellen Spiele- Entwickler.
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5963
Herkunft: Leipzig

beantworten | zitieren | melden

Hi Ayke,

"professionelle Spieleentwickler" kochen auch nur mit Wasser. Ich weiß zwar nicht, was die OpenGL-Methoden (GetInt, GetFloat) genau machen, aber ich habe auf die Schnelle folgenden Code gefunden, der ohne diese Methoden auskommt: GluProject and gluUnProject code.

Am aufwändigsten ist wahrscheinlich die Berechnung der Invertierten Matrix, die könnte man aber zwischenspeichern, und man braucht sie nur zu aktualisieren, wenn sich die Kamera geändert hat.

Christian
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
Shaarigan
myCSharp.de - Member



Dabei seit:
Beiträge: 51

beantworten | zitieren | melden

Hallo Ayke

das ist zwar nicht OTK, aber in der Mathematik sehr ähnlich aufgebaut. Ich verwende die Methode um Lichtquellen in Echtzeit verschieben. Du solltest auf alle fälle mal darüber nachdenken, ob du nicht deine Matritzen selber berechnen willst. Das ist nicht so schwer wies sich anhört und dürfte mit OTK auch nicht komplizierter sein.


//From Device.cs
public static void PointToScreen(ref Vector3 point, ref Matrix4 modelview, ref Matrix4 projection)
        {
            int[] viewport = new int[4];

            unsafe
            {
                fixed (int* ptr = viewport)
                {
                    gCore.GetIntegerv(GetPName.Viewport, ptr);
                }
            }

            Matrix4.Project(ref point, ref modelview, ref projection, viewport, out point);
            point.Y = (float)viewport[3] - point.Y;
        }

//From Matrix3.cs
public static bool Project(ref Vector3 world, ref Matrix4 modelviewMatrix, ref Matrix4 projectionMatrix, int[] viewport, out Vector3 screen)
        {
            Vector4 _in = new Vector4(world, 1.0f);
            Vector4 _out = new Vector4();

            //__gluMultMatrixVecd(modelMatrix, in, out);
            //__gluMultMatrixVecd(projMatrix, out, in);
            Vector4.Transform(ref _in, ref modelviewMatrix, out _out);
            Vector4.Transform(ref _out, ref projectionMatrix, out _in);

            if (_in.W == 0.0f)
            {
                screen = Vector3.Zero;
                return false;
            }

            _in.X /= _in.W;
            _in.Y /= _in.W;
            _in.Z /= _in.W;

            /* Map x, y and z to range 0-1 */
            _in.X = _in.X * 0.5f + 0.5f;
            _in.Y = _in.Y * 0.5f + 0.5f;
            _in.Z = _in.Z * 0.5f + 0.5f;

            /* Map x,y to viewport */
            _in.X = _in.X * viewport[2] + viewport[0];
            _in.Y = _in.Y * viewport[3] + viewport[1];

            screen = new Vector3(_in);
            return true;
        }

Die Performance liegt so zwischen 40 und 50 Microsekunden auf meinem 6 Jahre alten Rechner mit 2 GHz DualCore, sollte also ausreichend sein.
private Nachricht | Beiträge des Benutzers
Ayke
myCSharp.de - Member

Avatar #avatar-2293.gif


Dabei seit:
Beiträge: 655
Herkunft: Hamburg

Themenstarter:

beantworten | zitieren | melden

danke MrSparkle, Shaarigan vorallem für die Zeit damit habe ich mal eine Referenz.
private Nachricht | Beiträge des Benutzers