[DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Marserdling
Beiträge: 15
Registriert: 02.05.2009, 11:45
Benutzertext: Erdling vom Mars.

[DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Marserdling »

Hi, bin neu hier :)
Ich hänge bereits einige Tage an 2 Dingen, hoffe ihr könnt mir helfen:
Meine Raumschiffe sollen auf alle auf einen Punkt rotiert werden, und ich mache das so:

Code: Alles auswählen

D3DXVECTOR3 v1 = this->flightUnitVector; // Richtung in die das Raumschiff zeigt
D3DXVECTOR3 v2 = focussedPoint - ship->getCenterPosition(); //Vektor vom Raumschiffmittelpunkt zum Planetenmittelpunkt
float angle = atan2(v2.y, v2.x) - atan2(v1.y, v1.x);
if (angle < 0) angle += 2 * PI;
setRotation(angle)
Was ist hier falsch? angle hat dauernd seltsame Werte ala -4.74586869e-007. Floating Point errors? Wenn ja, warum? Es könnte sein dass mein v2 Vektor in die falsche Richtung zeigt, aber dann käme höchstens 0 als Winkel raus, da er dann in dieselbe Richtung zeigen würde wie v1. Außerdem passiert das bei jeder Stellung.

Die zweite Sache ist: Ich will GUI 2D Elemente in meinem Weltkoordinatensystem platzieren und sie NICHT mitzoomen lassen. Das reinpositionieren hat geklappt, das nicht mitzoomen auch. Aber wenn ich zoome, bleibt das Ding nicht an derselben Position. Was ich gemacht habe: Bevor ich die GUI zeichne, und nachdem ich alles andere gezeichnet habe, rufe ich nochmal D3DXMatrixOrthoOffCenterLH und dividiere alle Parameter statt durch einen Zoomfaktor, durch nichts/Eins. Außerdem probiert habe ich die Viewmatrix mit einer Einheitsmatrix zu ersetzen, was zu keiner Darstellung geführt hat.
Bin froh über jede Hilfe! Wie ihr euch vorstellen könnt, sind diese Dinge sehr frustrierend wenn man mehr als 2 Tage keiner Lösung nahekommt.
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Jörg »

Ich kann versuchen, gut zu raten, da dein Code nicht sehr aussagekraeftig ist:

Wenn setRotation das macht, was man vermutet, naemlich eine absolute Rotation zu setzen, dann ergibt es keinen Sinn, vorher eine relative Rotation zu bilden, sprich, die Subtraktion der Winkel passt hier nicht ganz.

Zur Positionierung der GUI-Elemente: Einfach die 2D-Position ausrechnen, an denen sie erscheinen sollen, und dann mit Einheitsmatrizen zeichnen lassen...

Joerg
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Schrompf »

Der Fließkommawert ist irgendwas bei 10^-7... das ist also praktisch 0 und will dir damit nur sagen, dass keine rotation nötig ist. Ansonsten hat jörg ja bereits den potentiellen fehler genannt: du errechnest eine relative rotation und scheinst die dann aber als absolute ausrichtung zu benutzen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Marserdling
Beiträge: 15
Registriert: 02.05.2009, 11:45
Benutzertext: Erdling vom Mars.

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Marserdling »

Wie verhindere oder fange ich solche jenseitigen float Werte ab? Ich bekomme das aus einer Winkelberechnung, will aber ordentliche Werte, also 0 statt 1.4538155-e009..
Zur Positionierung der GUI-Elemente: Einfach die 2D-Position ausrechnen, an denen sie erscheinen sollen, und dann mit Einheitsmatrizen zeichnen lassen...
Najo, genau das hätte ich schon probiert. Wie gesagt, Viewmatrix auf Einheitsmatrix setzen verhindert gänzlich die Darstellung. Aber wenn ihr sagt dass das so gehen muss, dann muss es wohl..ich nehm mal an, dass ich pro Frame händisch die Position vom Element nachkorrigieren muss, da die Weltkoordinaten nicht mehr mit der Darstellung zusammenpassen wenn per Orthoprojektion gezoomt wurde.
Benutzeravatar
Aramis
Moderator
Beiträge: 1458
Registriert: 25.02.2009, 19:50
Echter Name: Alexander Gessler
Wohnort: 2016
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Aramis »

Wie verhindere oder fange ich solche jenseitigen float Werte ab?
Gar nicht, sie sind ein Nebenprodukt von IEEE 754 mit dem man leben muss. Du kannst allenfalls versuchen deinen Compiler davon abhalten Optimierungen durchzuführen die die Diskrepanzen bei Fließkommarechnungen noch erhöhen könnten (/fp:precise, ist aber defaultmäßig bereits aktiviert). Ansonsten kannst du natürlich auch alle paar Rechenschritte runden, musst Dir aber darüber im klaren sein dass Du die Ungenauigkeit damit sogar noch erhöhst :-)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Schrompf »

Marserdling hat geschrieben:Wie verhindere oder fange ich solche jenseitigen float Werte ab? Ich bekomme das aus einer Winkelberechnung, will aber ordentliche Werte, also 0 statt 1.4538155-e009..
Gaaanz falsche Denkweise! 1.459285e-009 sind für den Computer so sehr 0, wie es gebraucht wird. Du aber setzt hier menschlich ästhetische Kriterien an. Damit machst Du es nur schlimmer - Aramis hat das ja bereits ausgeführt. Lass die Zahlen unbedingt so, wie sie sind. Diese Textdarstellung siehst doch nur Du im Debugger. Nach deren optischem Erscheinungsbild zu optimieren ist ein kreuzgefährlicher Gedanke.
Najo, genau das hätte ich schon probiert. Wie gesagt, Viewmatrix auf Einheitsmatrix setzen verhindert gänzlich die Darstellung. Aber wenn ihr sagt dass das so gehen muss, dann muss es wohl..ich nehm mal an, dass ich pro Frame händisch die Position vom Element nachkorrigieren muss, da die Weltkoordinaten nicht mehr mit der Darstellung zusammenpassen wenn per Orthoprojektion gezoomt wurde.
Dann hast Du wohl was falsch gemacht. Die Weltmatrix muss natürlich auch auf Einheit gesetzt werden, genauso wie die Sichtmatrix UND die Projektionsmatrix. Wenn Deine Vertexpositionen auf diese Art wirklich untransformiert durchkommen, dann gilt für den Wertebereich: X geht von links -1 bis rechts 1, Y von unten -1 bis oben +1, Z von 0 bis 1 ohne optische Wirkung. Danach müsstest Du jetzt exakt berechnen können, wie Du Deine GUI-Vertizes platzieren musst. Das plus evtl. den Artikel "Directly mapping texels to pixels" aus der DX-Doku.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Marserdling
Beiträge: 15
Registriert: 02.05.2009, 11:45
Benutzertext: Erdling vom Mars.

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Marserdling »

Dann hast Du wohl was falsch gemacht. Die Weltmatrix muss natürlich auch auf Einheit gesetzt werden, genauso wie die Sichtmatrix UND die Projektionsmatrix. Wenn Deine Vertexpositionen auf diese Art wirklich untransformiert durchkommen, dann gilt für den Wertebereich: X geht von links -1 bis rechts 1, Y von unten -1 bis oben +1, Z von 0 bis 1 ohne optische Wirkung. Danach müsstest Du jetzt exakt berechnen können, wie Du Deine GUI-Vertizes platzieren musst. Das plus evtl. den Artikel "Directly mapping texels to pixels" aus der DX-Doku.
Also ich benutze das DirectX Sprite Interface für meine ganzen Grafiken. Vielleicht ist es da ja anders, aber so funktioniert es bei mir auf jeden Fall nicht.
Hier update() aus meinem Gameloop:

Code: Alles auswählen

m_model->update(); 
m_controller->handleInput();
d3dManager.updateCamera();
// alle anderen Spielgrafiken
render(); 
// Grafiken die nicht mitgezoomt werden sollen, aber trotzdem auf dem gleichen Weltkoordinatenplatz bleiben sollen.
m_model->drawGUI();
 // 2ter Aufruf damit die Spielkoordinatenberechnung nicht durcheinander kommt. Setzt View und Projection
d3dManager.updateCamera(); 

drawGUI() Methode:

Code: Alles auswählen

dxManager.setOrthoIdentity();
dxManager.setViewIdentity();
dxManager.setWorldIdentity();
m_planet_menu->setPosition(0,0);
m_planet_menu->render();
Alle Matrizen auf Identity setzen:

Code: Alles auswählen

void dxManager::setViewIdentity()
{
	D3DXMATRIX temp;
	D3DXMatrixIdentity(&temp);
 	m_pDevice->SetTransform(D3DTS_VIEW, &temp);
}
void dxManager::setOrthoIdentity()
{
	D3DXMATRIX temp;
	D3DXMatrixIdentity(&temp);
	m_pDevice->SetTransform(D3DTS_PROJECTION, &temp);
}
void dxManager::setWorldIdentity()
{
	D3DXMATRIX temp;
	D3DXMatrixIdentity(&temp);
	m_pDevice->SetTransform(D3DTS_WORLD, &temp);
}
m_planet_menu->render() Methode:

Code: Alles auswählen


m_d3dspt->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_OBJECTSPACE);
m_d3dspt->SetTransform(&this->m_worldMatrix); 
//m_worldMatrix = das ist die Positionsmatrix von der Grafik, wird durch setPosition() verändert
m_d3dspt->Draw(this->texture,&(this->srcInTex),NULL,NULL,D3DCOLOR_ARGB(255,255,255,255));
m_d3dspt->End();
Sehe hier keinen Spielraum für Fehler, ich machs genauso wie du vorgeschlagen hast :(
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Schrompf »

Marserdling hat geschrieben: Sehe hier keinen Spielraum für Fehler, ich machs genauso wie du vorgeschlagen hast :(
Ich kenne mich mit dem D3DXSprite-System jetzt leider nicht aus. Mir scheint, als könnten die Sprite-Koordinaten das Problem sein. Ohne jede Transformation müssen die Koordinaten wie gesagt im Bereich (-1...+1, +1...-1, 0...1) sein, damit sie auf dem Bildschirm auftauchen. Ich weiß aber nicht, ob die Sprite-Klasse da noch irgendwelche zusätzlichen Transformationen anwendet. Das wirst Du Dir mal aus der Doku anlesen müssen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Marserdling
Beiträge: 15
Registriert: 02.05.2009, 11:45
Benutzertext: Erdling vom Mars.

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Marserdling »

Also ich hab jetzt "rausgefunden" dass mein Sprite doch angezeigt wird, aber extrem riesenhaft und gespiegelt Oo
Wenn ich es auf 0.005 skaliere und Position (0/0) setze, sehe ich es in der Mitte des Bildschirms. Gespiegelt.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4859
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Schrompf »

Ich fürchte, ich muss noch ein *drittes* Mal auf das Koordinatensystem hinweisen, dass die Grafikkarte intern benutzt. Das sieht so aus:

X: linker Bildschirmrand ist -1, rechter Bildschirmrand ist +1
Y: unterer Bildschirmrand ist -1, oberer ist +1. Das ist gegenüber den normalen Pixelkoordinaten gespiegelt, also Vorsicht da.
Z: vordere Grenze 0, hintere Grenze 1

Du musst entweder eine orthogonale Projektionsmatrix setzen, die Dir die Pixelkoordinaten (0 bis z.b. 1280, 0 bis 1024) auf den genannten Zahlenbereich abbildet, oder Du musst Deine Koordinaten direkt so an D3DXSprite übergeben.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Marserdling
Beiträge: 15
Registriert: 02.05.2009, 11:45
Benutzertext: Erdling vom Mars.

Re: [DX9] 2 Fragen: Rotation und GUI mit Weltkoordinaten

Beitrag von Marserdling »

Ok es funktioniert jetzt, es hätte eigentlich schon die erste Antwort gereicht wenn ich sie verstanden hätte ...
Lösung: pro Frame einmal die neue Screenposition aus den Weltkoordinaten der GUI berechnen und dann View und Orthomatrizen resetten. Wichtig dabei zu beachten ist die anfängliche Worldtransformation der Kamera. Die muss man beim resetten der Viewmatrix mit beachten als "eye" Vektor. (= Position der Kamera)
Ich weiß nicht warum du die Devicekoordinaten überhaupt erwähnt hast, das ist zwar eine interessante Information, hier war's aber gar nicht nötig das zu wissen.

Leider wird durch dieses Umtransformieren meine GUI in bestimmten Zoomstufen verschwommen dargestellt. Zeichne ich sie einfach sofort auf die immergleiche Bildschirmposition oder mit Weltkoordinaten scheint alles scharf zu sein.
Falls jemand dazu eine Idee hat, immer gerne. Habe bereits die üblichen Dinge wie matching Backbuffer/Clientwindow size überprüft und Filtering beim CreateTextureFromFile mit D3DX_FILTER_NONE abgeschalten.
Wie vorhin mal erwähnt benutze ich das D3DXSprite Interface, keine Ahnung ob ein Verschieben um -0.5,-0.5 des Sprites gleichbedeutend mit den Anweisungen in der msn Doku sind, aber es hat nichts gebracht.
Antworten