Da sich nun doch noch Medium und igel457 gemeldet haben:
das blitting eines ganzen frames ist nichtmal soo langsam, einzig in Wine unter Linux ist es so richtig langsam (da ist wohl bei denen was schiefgelaufen, es wurden auchs schon verschiedene Wine-Versionen mit verschiedenen Distributionen getestet), auf meinem Laptop (1280x800) braucht es 20-30ms, an meinem PC mit 1600x1200 leider runde 80-100ms. Aber das ist für die Anwendung schnell genug und wenn man nur den Panorama-viewport aktualisiert, der etwa zwei drittel des Bildschirms ausfüllt, ist es noch etwas besser. Meine stretchdraw-routine braucht für die clientarea bei 1600x1200 etwas mehr als 5ms und darin ist sowohl das skalieren der Pixelkoordinaten als das byteweise Kopieren der Pixelwerte enthalten.
Wenn man sich mit den
GDI-Wehwehchen abgefunden hat, stellt man sich die Frage: wieviel ist nötiger Rechenaufwand für ein Problem und wieviel ist overhead?
Selbst Bilder rotieren und skalieren lässt sich auf Vollbild mit > 50fps implementieren, indem man den Overhead durch Single-Arithmetik auf Integerarithmetik umbricht. Wozu erst auf 9 Nachkommastellen genau rechnen und dann runden, was beidesmal irre viel Zeit kostet, wenn die dritte oder vierte Nachkommastelle genügt und eine fixe Anzahl Stellen machbar ist?
Der Unterschied liegt in integer->single und frndint-Konversionen vs. shift-Operationen, ich denke das sieht man. Für die exakte Berechnung kann man sich mehr Zeit nehmen, aber für fließende Bewegungen ist der Betracher auch einfach zu langsam, daher kann man kleinere Fehler zeitweise zulassen. Ich suche bei dem von mir beschriebenen Verfahren nach dieser kleinen Lücke, in der ein geometrisch korrektes Panorama angezeigt wird, dessen Fehler aber erst nach einigen Sekunden Betrachtung auffallen würden, dann jedoch ist schon die exakte Version berechnet und wird drübergezeichnet.
Der Schlüssel dazu liegt darin, auf (inverse) trigonometrische Funktionen zu verzichten, denn die Zuordnunng der Quellpixel auf der Panoramakugel ist nur einmalig zu bestimmen. Ebenso verhalten sich Transformationen vom Zielbild auf die Kugel ähnlich, sodass nur beim Herauszoomen neue Informationen hinzugefügt werden müssen, der innere Bildbereich lässt sich durch Verschiebung der Zuordnungen abbilden. Und plötzlich wird alles so einfach, da man ja trotz des dreidimensionalen problems nur 2d->2d->2d-Abbildungen berechnen muss, die bis auf ein paar Sonderflälle wirklich glatt sind und sich auch leicht approximieren lassen. Bei Drehungen des viewports muss ich doch nicht die volle Transformationskette abarbeiten mit einigen sin/cos-Funktionen und 1-2 arccos, arctan, ... Funktionen - da sich nur die assoziierten Punkte in der Zwischenabbildung auf einer Oberfläche herumbewegen.
Eigentlich sollte man alle Quellpixel auf die Kugel mappen, das dauert jedoch verdammt lang und braucht viel Speicher. Außerdem liegen die Punkte unverändert nebeneinander. Das ermöglicht es dann, zwischen Stützstellen zu interpolieren, ohne dass der Fehler über den Bereich zu groß wird. Ja, irgendwo ist es der workaround eines workarounds, aber soweit ich es implementiert habe, funktioniert es auch schon zufriedenstellend.
Wie es aussieht, habe ich sowieso noch ein paar Tage Zeit zum Nachdenken, da der Quellcode auf dem Laptop ist und der liegt zuhause
Ich sehe es übrigens ein, dass
OpenGL /
DirectX angemessener wäre, jedoch habe ich auch angefangen, eine kleine Control-Hierarchie zu basteln, die auf einen buffer zeichnet (mit und ohne Alphablending). Der viewport ist die clientarea eines dieser Objekte. Eine Bildebenenverwaltung steuert das ganze. Sämtliche Algorithmen sind buffer-basierend. Ich würde die Entscheidung für
gdi drawing nicht als Fehler bezeichnen, aber ich würde doch sehr gerne ohne Tricks mit Hardwarebeschleunigung auskommen, zumal ich korrekt abzuschätzen glaube, dass der Rechenaufwand es zulässt.
Der panorama viewer ist eines der letzten features, nach dessen Implementierung und eininiger Ergänzungen / Optimierungen das Programm auf die OpenSource-Halde gekippt wird (ich bin mir sicher, dass sich da auch eine Panoramaviewer-Komponente abdestillieren lässt
). Nebenher habe ich in Zusammenarbeit mit einem Freund ein remake auf Basis von Qt begonnen und wir haben uns auch
OpenGL angesehn.