Laden...

[gelöst] Ersatz von ScaleTransform gesucht:

Erstellt von auoji vor 8 Jahren Letzter Beitrag vor 8 Jahren 5.541 Views
A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren
[gelöst] Ersatz von ScaleTransform gesucht:

Aus der UI / XAML kenne ich die Funktion ScaleTransform.TranslatePoint.

Nun in meinem XNA Spiel will ich zoomen in meine Welt/Karte, was an sich kein Problem ist. Aber ich will ein zoomen anbieten können, welches genau um den Mauspunkt zoomt. So wie das in Google/Maps und auch bei anderen Funktioniert.

Ich habe auch die Funktion dazu gefunden eben in Scaletransform. Man bereitet die Scaletransform vor indem man den Scalefaktor ScaleX und ScaleY sowie den CenterPoint ebenfalls CenterX, und CenterY angibt. Der Centerpoint ist die Mausposition. Anschliessend kann man die Funktion ScaleTransform.TranslatePoint nutzen welche ich auf den ScreenHome Point(LinksOben des sichtbaren Ausschnittes) anwenden will.
Rechnerisch funktioniert das gut. Ist der ScreenHome dann bekannt zoomt meine Karte inklusive aller sich bewegender Sprites bereits richtig.

Scaletransform.ScaleFaktorXY = 1.01; 
Scaletransform.CenterPointXY = Mausposition; 
var Point neuesXY = Scaletransform.translatePoint(altesXY); 

Also alles gelöst, bis auf das zoomen um die MausPosition. (Kann gerne Tipps geben)

Das Problem ist, dass ich keine Windows UI Elemente und sei es auch nur diese Klasse/Funktion verwenden kann in einem XNA Projekt.

Kennt jemand eine Alternative? Also eine Funktions oder Funktionssammlung mit welcher man eine Position x,y durch die bekannten Werte ScaleX/ScaleY um den Centerpunkt CenterX/CenterY transformieren kann?

Vielen Dank!

742 Beiträge seit 2005
vor 8 Jahren

Du benötigst noch eine Translation. Schau dir mal folgenden Artikel an:

A WPF Custom Control for Zooming and Panning

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Das ist schon klar. Das ist in UI(XAML) alles.

Dein Artikel benutzt eben auch ScaleTransform (in OnApplyTemplate())

Ich bin aber in einem Monogame Projekt. Da kann ich diese Funktionen nicht brauchen. Windows unterbindet das. Sorry

Aus dem ganzen brauche ich wirklich nur ein Ersatz für Scaletransform und keine der anderen Translationen. Alle andere Translationen sind bei mir gelöst.

Bei mir laufen alle Sprites schon korrekt herum und sind auch korrekt animiert, das auch während des Scrollens - alles tiptop.
Ich kann sogar zoomen. Aber nicht unter den Mauspunkt sondern immer nur auf den Screenhome linksoben.
Eigentlich könnte es man als unschönheit betrachten. Aber da man im Spiel sehr oft das zoomen brauchen wird muss die korrekte Variante unbedingt funktionieren.

Danke

C
168 Beiträge seit 2010
vor 8 Jahren

Handelt es sich um 2D oder 3D?

für 3D kannst du folgendermaßen die Position bestimmen

private Vector3 GetWorldMousePosition(MouseState ms, Matrix projection, Matrix view)
{
    Vector3 near = new Vector3(ms.X, ms.Y, 0);
    Vector3 far = new Vector3(ms.X, ms.Y, 1);
    Vector3 nearPosition = device.Viewport.Unproject(near, projection, view, Matrix.Identity);
    Vector3 farPosition = device.Viewport.Unproject(far, projection, view, Matrix.Identity);

    Vector3 direction = farPosition - nearPosition;
    Vector3 Position = nearPosition + direction * (-nearPosition.Y / direction.Y);

    return Position;
}

Anschließen muss du nur noch die Camera Position anpassen. Hier kann man auch mit dem Z wert einen Zoom erzeugen.

das ganze lässt sich aber auch auf 2D anwenden solang du eine Camera verwendest.

Auch wenn die Camera in 2D nicht zwangsläufig verwendet werden muss, lassen sich damit jedoch solchen ding sehr simple lösen.

Real programmers don't comment their code - it was hard to write, it should be hard to understand.

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Es ist in 2D. Ich werde bald Vector3 anstelle von Vector2 benutzen, aber nur um die Layertiefe der einzelnen Objekte am richtigen Ort zu speichern. (Diese laufen auch auf Türme hinauf etc.)

Interessant eine Camera in 2D. Muss ich mir anschauen.

In deinem Code verstehe ich die Parameter nicht. Leider habe ich keine Ahnung von Matrixen, vor allem ihrerer Verwendung im Code.

Ich hoffe immer noch den Body von Scaletransform.TranslationPoint(point) auf einfacher Weise zu bekommen. Mein .NET Reflector will es mir nicht zeigen.

Das Spiel wird spätestens Ende Jahr in einer Alpha Version an interessiert veröffentlicht. In einem Monat für ganz speziell interessierte.

C
168 Beiträge seit 2010
vor 8 Jahren

Ich hab mich mit 2D ohne Camera leider zu wenig beschäftigt, aber ohne Camera muss du eigentlich folgendes tun:

  1. Maus Position bestimmen
  2. Alle Bilder so verschieben das die Maus Position das Zentrum ist und die Sprites vergrößern.

So würde ich es zu mindestens ohne Camera versuchen zu Lösen, aber ob das der Richtige weg ist kann ich dir leider nicht sagen.

zu den Parametern die View und Projection Matrix sind Werte die eine Camera benötigt.
Wenn du also eine Camera einsetzen solltest benötigt diese eine View und Projection Matrix, diese wiederum werden in der oben gezeigten Funktion benötigt.

Zu der Camera in XNA wirst du aber ein Haufen Tutorials finden die ausführlich und meist sehr anschaulich dir alles erklären.

Real programmers don't comment their code - it was hard to write, it should be hard to understand.

742 Beiträge seit 2005
vor 8 Jahren

In dem Artikel wird eine ScaleTransform und ein TranslateTransform verwendet. Das ist analog zu einer SkalierungsMatrix multipliziert mit einer TranslationsMatrix (= View Matrix)

Deshalb ist der Artikel schon genau das was du suchst, denke ich.

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

OK, schaue es mir genauer an. Danke

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren

Sorry malignate,

nach genauerem Anschauen des Artikels. entweder verstehe ich zu wenig oder:

Ich habe früher selbst in WPF fleissig mit den Translationgroup und allen Transform Klassen des WPF. (Rotationtransform , ScaleTransform etc.) angewendet. Sehr ähnlich wie in diesem interessanten Artikel.

Was halt ist: Auch dieser Artikel stützt sich in **ALLEN **wichtigen Bereichen auf die Funktionen von den Transaktionsklassen der WPF und ihren starken Methoden. Ist ja logisch, dazu sind sie ja da.

Die Kernroutinen, welche diese Klassen lösen sind natürlich in deren Methoden gelöst. Dieser Artikel ist hervorragend um mit den WPF UI(XAML) TransformationsKlassen und Gruppen umzugehen. Aber die Kernroutinen,** und ich möchte ja nur eine davon,** löst er logischerweise selbst nicht.

Diese Transformationsklassen von WPF sind wirklich stark. Auch durch mein Problem, dass ich keine Alternative finde, zeigt wie stark diese Klassen in der WPF wirklich sind. Leider sind auch einzelne nützliche Funktionen an WPF gebunden und ausserhalb des UI für die Benutzung gesperrt(unnötig, aber Microsoft hat das so beschlossen)

In meiner Zeit mit WPF, bin auch darauf gestossen, dass einzelne Methoden dieser Klassen zum Teil sehr CPU-Zeitraubend sind. Es ist ja klar, diese Klassen sind nicht für Massen an Objekten gedacht welche mindestens 30 mal in der Sekunde neu gezeichnet werden müssen. Sie sind gedacht, dafür aufgrund von Benutzereingaben ein oder zwei Dutzend Berechnungen durchzuführen und dann wieder nichts zu tun zu haben.

Ein Grund warum ich jetzt Windows-Store über MonoGame programmiere, ist dass Ich das Einsetzen von zeitaufwendigen Methoden genau steuern kann. Die Lösung meines Zoom-Problems werde ich vermutlich auch nur durch zeitaufwendige Berechnung lösen können.

Ich werde diese aufwendige Berechnung, so ich sie einmal habe, auch nur auf Benutzereingaben des zoom anwenden müssen, ansonsten nicht. Ich will ja nur den ScreenHome Point damit berechnen - einmal pro Zoom-schritt. All die folgenden Updates, der ca. 3000 pro 3ms, stützen sich in meinem Spiel heute bereits auf diesen ScreenHome Point. Das geht sehr schnell, wird von mir aber auch bis an die Grenzen genutzt. Darum kann ich in reinem WPF kein hoch animiertes Spiel programmieren.

Übrigens für alle Interessierten ist mein Code und die verschiedenen Lösungen von kybernetischer Programmierung auf Anfrage verfügbar. Bevor es im Verlauf des Projektes öffentlich wird.

5.657 Beiträge seit 2006
vor 8 Jahren

Hi auoji,

ich kann deinen Ausführungen leider nicht so richtig folgen. Wenn ich es richtig verstanden habe, willst du in einem XNA-Game Zoomen, wobei der Zoom am Mauszeiger zentriert ist. Dazu brauchst du eine Translationsmatrix zum Verschieben des Mittelpunktes zum Koordinatenursprung, eine Skalierungsmatrix zum Zoomen und eine Translationsmatrix zum Zurückschieben. Das sind insgesamt drei Matrix-Multikplikationen, die auf die ViewMatrix angewendet werden.

An welcher Stelle dabei Performance-Probleme auftreten können, ist mir nicht klar.

Ebenso verstehe ich nicht, was das mit den WPF-Transformationen zu tun hat.

Christian

Weeks of programming can save you hours of planning

742 Beiträge seit 2005
vor 8 Jahren

Hi,

natürlich ist der Artikel für WPF gedacht, ich bin mir aber sicher, dass man Ihn einfach umprogrammieren kann. Im Prinzip sind Translatations in WPF nur Matrizen, die dann auf die Elemente angewendet werden. Wenn es sich um RenderTransformation handelt, dann ist das Layout ja auch gar nicht davon betroffen. Das gleiche Prinzip kannst du auch für XNA anwenden. Im Prinzip geht es mir nur um die Berechnungen, die dort durchgeführt werden. Das kann man analog übernehmen:

TranslateTransform => Matrix.CreateTranslate(x, y, 0) // Keine Z Transformation, wir sind ja in 2D
ScaleTransform => Matrix.CreateScale(zoom);
TransformationGroup => Multiplikation von Rotaton und TranslationMatrix

Und dann gibts viele weitere Analogien:

ViewportWidth => WindowWidth
ViewportHeight => WindowHeight

(Arg viel mehr steckt in WPF auch nicht dahinter)

Du musst dir eben überlegen, wie du deine ViewMatrix berechnest und da hilft der Artikel schon sehr.

5.657 Beiträge seit 2006
vor 8 Jahren

Hi malignate,

achso verstehe: Das WPF-Beispiel war nur ein Beispiel.

Es gibt aber auch für XNA passende Beispiele, z.B. Rotating and Moving the Camera, XNA Camera 2d with zoom and rotation oder XNA 2D Transform Matrix Scale at Zoom Question.

Die Matrizen muß man ja auch nicht selbst berechnen, dafür gibt es bereits passende Methoden. Bei einer 2D- (oder isometrischen) Ansicht muß man in den Beispielen die Matrix.CreatePerspective-Methoden durch die passende Matrix.CreateOrthographic-Methoden ersetzen. Auch für das Erstellen von Transformations- und Skalierungs-Matrizen gibt es die passenden Methoden.

Der Vorteil liegt aber auf der Hand: Wenn man die Kamera animiert, benötigt man 3 Matrixmultiplikationen, wenn man stattdessen 3 Millionen Objekte in der Szene animiert, sind es schon 9 Millionen Matrixmultiplikationen.

Daher stammen dann sicherlich die Performanceprobleme.

Christian

Weeks of programming can save you hours of planning

742 Beiträge seit 2005
vor 8 Jahren

Hi Christian,

ja das war nur ein Beispiel. Hatte ich gerade im Kopf und liefert auch noch viel Code für Animationen, zwei Methoden zur Matrix-Erzeugung habe ich ja auch erwähnt 😉

Die Matrixmultiplikationen führt man dann ja auch oft auf der Grafikkarte durch (bzw. berechnet die ViewProjectionMatrix vor) und sollten überhaupt nicht ins Gewicht fallen.

Viel wichtiger werden dann die Anzahl der Draw Calls.

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren
Super!!!

Damit muss es mir nun gelingen. Danke für die Tipps!

A
auoji Themenstarter:in
10 Beiträge seit 2015
vor 8 Jahren
[gelöst]

Vielen Dank Jungs. 8)
Für dieses 2D Spiel konnte ich auf Matrixen verzichten.
Ich hatte vorher schon korrekt gerechnet. In Testprojekten zeigte es sich, dass ich die ScaleTransform von WPF korrekt nachbaute. Allerdings funktioniert es in meinem Spiel nicht wie gewünscht, nur in den Testprojekten. Warum habe ich Ahnungen, weiss es aber nicht.

Lösung ist dann ganz anders entstanden und viel einfacher:

Den Punkt der Karte merken wo die Mausposition vor dem Zoom Schritt ist.

Nach dem Zoom diesen Punkt der Karte wieder genau auf die Mausposition legen.

Das war es....

Vielen Dank für eure Hilfe!!!