Rollende Kugel mit Textur

  • Dieses Thema soll als Diskussionsort für ein Problem dienen, welches wir kurz in der Shoutbox mit UEZ erörtert haben.

    Auch wenn du ( UEZ) paar Tage nichts von mir gehört hast, war ich nicht untätig.
    Ich habe mir brav FreeBasic angesehen.
    Da aber sowohl die Sprache, als auch die Thematik, für mich Neuland waren, musste ich ein eigenes Programm von Grundauf erstellen um die Sache zu verstehen, anstatt am vorhandenen Skript rumzudoktorn.
    Kurzum: Irgendwann habe ich aber entnervt aufgegeben - FB und ich werden wohl keine Freunde mehr.

    Anstatt mich nun noch mit einer anderen Sprache rumzuschlagen habe ich mir für das Thema good old AutoIt wieder hochgeholt und versucht damit nun zu zeigen wie ich mir das algorithmisch vorstelle, was ich in der Shoutbox beschrieben habe.
    Das ganze hat dann aber auch länger gebraucht, da ich absolut Null Plan von GDI+ hatte.

    Am Ende habe ich aber nun etwas vorzeigbares erstellt was evtl. als Grundlage für weitere Diskussionen und Verbesserungen dienen kann.
    Im Idealfall sind hieran die Mathematik dahinter schon erkennbar, so dass du bestimmte Dinge in dein FB-Programm übernehmen kannst:

    Die Texturdatei liegt im Anhang.

  • Vielen Dank AspirinJunkie :thumbup:

    Das Ganze läuft in Autoit ziemlich langsam ab (liegt in der Natur von Autoit) und mir kommt es vor, dass die Projektion des Bildes auf die Kugel nicht richtig aussieht, aber ich ziehe mir mal deine Mathematik rein. Bin sehr eingerostet, was Vektoren angeht.

    Ich habe den FB Code ein wenig frisiert und allen 15 Kugeln Texturen verpasst, die entsprechend dem Bewegungsvektor angezeigt werden, leider nicht physikalisch immer korrekt. Ich habe eukalyptus ' ASM Sinus / Cosinus verwendet, was zu einem echten Performance Boost gebracht hat. Der Flaschenhals waren Trigonometrie aufrufe in der MapImage2Sphere() Funktion.

    OneDrive: https://1drv.ms/f/s!AiLeZOpaFqSayCvkcMeBwRcp9ySN?e=qYN7qU (Simple 2D Ball Collision - Billiard Opening5.bas / .exe + die Bitmap Dateien 1-15).

    Schade, dass du dich nicht mit FB anfreunden wirst / kannst / willst! Irgendwie gefällt mir die Sprache besser als Autoit.

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (22. November 2025 um 19:29)

  • Sehr interessant. Hier noch eine Idee: Finde eine Transformation um die Einzelpixelrechnung komplett aus dem Spiel zu nehmen.

    Der Texturabdruck dieser Formel ist auch nicht ganz richtig für eine "korrekte" perspektivische Projektion einer Ebene auf eine Kugeloberfläche (Das Abbild ist eine um 45° gedrehte Raute). Da ich hier kein Profi bin ist Folgendes nur eine Vermutung: Die 3x2 Matrizen aus GDI+ werden hierfür wahrscheinlich nicht reichen, weil sie die Verzerrung nicht abbilden können. Dafür müsste man dann doch wieder nichtlineare Elemente einbringen die GDI+ nicht abbilden kann sodass man sie doch von Hand ausrechnen muss... Ist wahrscheinlich im Endeffekt kein Vorteil, aber ganz kurz dachte ich "vielleicht reicht die GDI+ übliche Matrix ja doch". Bin da kein Profi, von daher: Vielleicht bringt die Idee ja irgendwen weiter :D

    Den Texturfootprint kann man mit folgendem Skript einsehen:

    lg

    M

  • mir kommt es vor, dass die Projektion des Bildes auf die Kugel nicht richtig aussieht

    Evtl. kommt dies dadurch zustande, dass derzeit nur die Rotation um die X und Y-Achse implementiert wurde.
    Das sieht erstmal komisch aus, wenn die Geraden in der Textur immer gleich ausgerichtet bleiben.
    Aber für die reine Kugelbewegung ohne Spin gibt es tatsächlich ja auch keine Drehung um die Z-Achse.
    Das werde ich später sicherlich auch noch mit einbauen aber für die Thematik einer rollenden Kugel hier war das noch nicht nötig.

    Der Flaschenhals waren Trigonometrie aufrufe in der MapImage2Sphere() Funktion.

    Und jetzt stell dir vor wie deine Funktion rennen würde, wenn du die trigonometrischen Funktionen auf ein Minimum reduzieren könntest.
    Genau das habe ich ja versucht in meiner Funktion umzusetzen.
    Wenn man eine Kugel mit einem Radius von 25 Pixeln zeichnen lässt, dann sind die einzigen Aufrufe trigonometrischer Funktionen bei mir 25x ein ArcSin - das wars.

    Und wie man schön an Mars Beispiel sieht, ist die Texture-Map starr. Das heißt man kann diese für jede Kugel nur einmal erstellen und braucht dann lediglich die Offsets aufgrund der Rotationen hinzuzufügen. Dann kommt jeder neue Kugelframe komplett ohne trigonometrische Funktionsaufrufe aus.

    Mir ist schon bewusst, dass man sich das Leben viel leichter machen könnte, wenn man mit UV-Mapping da herangeht.
    Aber dann haben wir halt diese exzessive Nutzung von trigonometrischen Funktionen und ich denke unser Anspruch liegt höher ;)

    Der Texturabdruck dieser Formel ist auch nicht ganz richtig für eine "korrekte" perspektivische Projektion einer Ebene auf eine Kugeloberfläche (Das Abbild ist eine um 45° gedrehte Raute).

    Also perspektivisch stimmt das aus meiner Sicht schon erst einmal - Korrekturen sind aber natürlich erwünscht wenn ich daneben liegen sollte.
    Ein wirklicher Fehler steckt aber tatsächlich im Texturemapping - und zwar beim Mapping der Y-Koordinate.
    Wenn dort ein Bereichsüberlauf stattfindet, dann springt er auf die andere Seite (Modulo lässt grüßen).
    Bei der X-Koordinate ist das ja auch so richtig.
    Stattdessen wäre es aber ja für die Y-Koordinate korrekt den Überlauf an der jeweiligen Kante zu spiegeln.
    Oder um es plastisch zu machen: Wenn man die Erde mappt und bei der Arktis über den Nordpol hinaus mappt, dann hat man auf einmal die Antarktis als nächsten Pixel...
    Das passe ich natürlich unbedingt noch an - ist mir bei dieser symmetrischen Textur hier nicht aufgefallen.

  • Man(n) kann auch GDI+ benutzen, um die Textur auf die Kugel zu projizieren.

    Beispiel:

    Der Kern des Codes ist aus dem "Rotating Earth" Beispiel, irgendwann hier im Forum gepostet...


    Hier der FB Code + Exe.

  • Das ist ein super Beispiel. Hier wird Die Kugel einfach "Scheibchenweise" mit einer linearen Matrix gezeichnet, sodass insgesamt der Eindruck entsteht man hätte es irgendwie nichtlinear gelöst. Dafür muss man aber ein Sleep(100) einbauen und $iStep = 15 setzen, sonst sieht man das nicht weil es zu schnell und zu fein aufgelöst ist :D

  • Ihr habt beide komplett Recht.
    Da ist noch ein ziemlicher Schnitzer in der Projektion.
    Ich will aber auf Teufel komm raus kein klassisches UV-Mapping umsetzen sondern versuche immer noch eine möglichst performantere Variante zu finden.
    Mal sehen ob und wie weit ich komme.
    Bis dahin ist obiges Skript natürlich zu ignorieren.

  • Ich habe nach langer Pause weitergemacht und mit Unterstützung der KIs in Free Basic es hinbekommen, dass die Textur Rotation gemäß dem Richtungsvektor realistisch aussieht.

    Siehe Post#2 für die Link zu meinem 1Drv.


    https://i.ibb.co/GQf6S9xk/Captured.webp

    [Blockierte Grafik: https://i.ibb.co/GQf6S9xk/Captured.webp]

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    4 Mal editiert, zuletzt von UEZ (13. August 2025 um 12:29)

  • Hallo, 👋

    mein Ansatz hat zwar nichts mit FreeBasic zu tun, aber ich fand die Idee der texturierten, rollenden Kugeln interessant und habe eine Version in Verbindung mit OpenGL geschrieben. Als Textur nutze ich die BMP von UEZ aus der "Simple 2D Ball Collision - Billiard Opening2.7z" aus Post #5 in diesem Thread.


    Billard_OpenGL.au3:

  • Getestet habe ich es unter Windows 10.

    Da du den Tisch siehst (der ohne Tiefentest gezeichnet wird), aber die Kugeln nicht (die den Tiefentest nutzen), liegt das Problem fast sicher daran, dass kein Tiefenpuffer (Depth Buffer) erstellt wurde.

    Lösungsansätze

    1. MSAA deaktivieren

    Ändere in der Funktion _SetupOpenGL die Zeile:

    Code
    Local $iPixelFormat = _GetMultisamplePixelFormat()

    zu:

    Code
    Local $iPixelFormat = 0 ; _GetMultisamplePixelFormat()

    Hier ist die vollständige, angepasste Funktion:

    2. Tiefentest temporär deaktivieren

    Kommentiere dazu in der _Main-Funktion diese Zeile aus:

    Code
    ; _glEnable($GL_DEPTH_TEST)

    Hier ist die angepasste _Main-Funktion:

    3. Könnte an den Texturen liegen, eher sehr unwahrscheinlich.


    Die Ansätze funktionieren unabhängig voneinander. Ich würde mit 1. anfangen. :)


    So sieht es bei mir aus (habe keinen freien Videorekorder):

  • Beitrag von Douky (22. November 2025 um 23:34)

    Dieser Beitrag wurde vom Autor gelöscht (23. November 2025 um 00:25).
  • Ich habe eine Windows-11-VM (25H2) zum Testen eingerichtet. Dort wurden zwar die Kugeln angezeigt, jedoch nicht der Holzrahmen und auch die weiße Kugel nicht.

    Neben den Änderungen wurden auch ein paar Ausgaben in der Konsole ergänzt.

    Vor den Änderungen:

    Nach den Änderungen:

    Umgesetzte Änderungen:

    1. Composition-Flag definieren und setzen

    Code
    Global Const $PFD_SUPPORT_COMPOSITION = 0x00008000

    In beiden Funktionen (_SetupOpenGL und _GetMultisamplePixelFormat) :

    Code
    DllStructSetData($tPFD, "Flags", BitOR($PFD_DRAW_TO_WINDOW, $PFD_SUPPORT_OPENGL, $PFD_DOUBLEBUFFER, $PFD_SUPPORT_COMPOSITION))

    2. Weiße Dummy-Textur statt Textur-Deaktivierung

    Code
    Func _CreateBlankTexture()
        ; ... Generiert eine weiße 1x1 Pixel Textur ...
        _glTexImage2D($GL_TEXTURE_2D, 0, 4, 1, 1, 0, $GL_RGBA, $GL_UNSIGNED_BYTE, DllStructGetPtr($tData))
        Return $iTexID
    EndFunc

    Im Render-Loop (ersetzt _glDisable($GL_TEXTURE_2D)) :

    Code
    _glEnable($GL_TEXTURE_2D)
    _glBindTexture($GL_TEXTURE_2D, $g_iTexBlank)

    3. Dreiecke statt Vierecke verwenden

    Code
    ; In _DrawRect:
    _glBegin($GL_TRIANGLES) ; Statt $GL_QUADS
    ; ... Vertex-Koordinaten für 2 Dreiecke ...

    4. Projektion in jedem Frame neu setzen

    Code
    ; Am Anfang von _Render:
    _glViewport(0, 0, $iWidth, $iHeight)
    _glMatrixMode($GL_PROJECTION)
    _glLoadIdentity()
    _glOrtho(0, $iWidth, $iHeight, 0, -100, 100)


    Billard_OpenGL_Win11.au3:

    Durch die Nutzung von Display Lists (statt des direkten Zeichnens im Immediate Mode) sollte sich die Performance unter Windows 10 erhöhen. Unter Windows 10 laufen bei mir beide Versionen.

    Ich bin gespannt, ob es nun auch auf anderen Geräten funktioniert :)

  • Gleiches Resultat:

    Code
    > _SetupOpenGL: Start
    > MSAA Enabled (Format Index: 39)
    > Selected PixelFormat: 39
    > SetPixelFormat Result: 1
    > wglCreateContext Result: 0x00020000
    > wglMakeCurrent Result: 1
    --- OpenGL Info ---
    Version:  4.6.0 - Build 32.0.101.6881
    Vendor:   Intel
    Renderer: Intel(R) Graphics

    Vielleicht hängt's an den Treibern...

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (23. November 2025 um 13:38)

  • Code
    > _SetupOpenGL: Start
    > MSAA Enabled (Format Index: 41)
    > Selected PixelFormat: 41
    > SetPixelFormat Result: 1
    > wglCreateContext Result: 0x00020000
    > wglMakeCurrent Result: 1
    --- OpenGL Info ---
    Version:  4.6.0 NVIDIA 576.57
    Vendor:   NVIDIA Corporation
    Renderer: NVIDIA GeForce RTX 3070/PCIe/SSE2
  • Gleiches Resultat:

    Code
    > _SetupOpenGL: Start
    > MSAA Enabled (Format Index: 39)
    > Selected PixelFormat: 39
    > SetPixelFormat Result: 1
    > wglCreateContext Result: 0x00020000
    > wglMakeCurrent Result: 1
    --- OpenGL Info ---
    Version:  4.6.0 - Build 32.0.101.6881
    Vendor:   Intel
    Renderer: Intel(R) Graphics

    Vielleicht hängt's an den Treibern...

    Das, dass bei dir quasi so gar nichts angezeigt wird, kann ich mir noch nicht so recht erklären.


    Code
    > _SetupOpenGL: Start
    > MSAA Enabled (Format Index: 41)
    > Selected PixelFormat: 41
    > SetPixelFormat Result: 1
    > wglCreateContext Result: 0x00020000
    > wglMakeCurrent Result: 1
    --- OpenGL Info ---
    Version:  4.6.0 NVIDIA 576.57
    Vendor:   NVIDIA Corporation
    Renderer: NVIDIA GeForce RTX 3070/PCIe/SSE2

    Das sieht für mich im ersten Moment so aus, als hättest du einfach die Texturen nicht im selben Verzeichnis wie die .au3. In einer alten Version vom Script sind sie in einem Paket enthalten: https://autoit.de/wcf/file-download/302/

  • Douky

    Ich muss die OpenGL DLL (ältere Version v5.1) in ScriptDir kopieren und folgendes Skript wandelt die Texturen korrekt um, sodass jetzt alles so aussieht, wie in deinem Screenshot oben.

    Ohne die DLL in ScriptDir sehe ich nur ein grünes Rechteck, wie oben gezeigt. Scheint an der OpenGL32.dll v10 (Win11) zu liegen...

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (28. November 2025 um 21:54)