[OpenGL] Quaternions om Gimbal Lock te vermijden -> trillen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • tripkip
  • Registratie: Oktober 2008
  • Laatst online: 08-08 07:54
Zonder de Quaternions zit ik met een gumbal lock.
De bedoeling van het opengl project is een object die rond zijn x en z as kan roteren.
xrot en zrot stellen deze rotaties voor.

Met de quaternions geimplementeerd staat het object van links naar rechts te "trillen"...

*snip*

Graag een beetje hulp ;)

[ Voor 83% gewijzigd door Creepy op 14-03-2010 21:08 ]

Twitter iCouchPotato


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Afgezien dat je topic niet aan de quickstart voldoet (je plempt een lap code neer en verwacht van ons dat wij het dan maar fixen), snap ik niet waarom gimbal lock een probleem is. Ik heb een godshekel aan die viewers die rotaties in world space doen ipv local space. Dan hangt het object op een gegeven moment schuin en moet je rare capriolen uithalen om 'm weer recht te krijgen.

Wat imho beter werkt is gewoon zoals je de camera bestuurt in een game. En ja, dan is het idd zo dat als je 90 graden omhoog of naar beneden kijkt en je stuurt dan naar links/rechts dat het beeld dan ronddraait ipv dat je naar links of rechts draait, maar het is wél een intuitief systeem en het object komt nooit scheef te hangen.

Hoe dat werkt is door simpelweg de rotaties in je xrot en zrot te accumuleren, en daar elke keer een nieuwe matrix van te maken (ipv de vorige matrix steeds opnieuw te roteren adhv de input)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 12-09 10:03

Creepy

Tactical Espionage Splatterer

(jarig!)
Zoals .oisyn al terecht opmerkt missen we nogal wat info uit je startpost. Ook heb ik je code verwijderd, het was nogal een aardig lap. Als je code post, post dan alleen de relevante code. Ga gewoon eerst eens zelf debuggen, en geef dan ook vervolgens hier aan wat je zelf al hebt geprobreerd, welke stappen je met debuggen hebt ondernomen en waarom je denkt dat je een probleem hebt en waar je denkt dat dat aan zou kunnen liggen. Domweg een lap code posten en aangeven dat het "trilt" en dat wij je maar moeten gaan helpen is niet de bedoeling.

[ Voor 5% gewijzigd door Creepy op 14-03-2010 21:10 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Ik dacht eerst dat je met een camera zat, dan is het wat ingewikkelder maar met een object draaien is het gewoon een questie van goede volgorde.

Sla de Yaw, Pitch en Roll op van je object. Zorg ervoor dat deze waarden los van elkaar ge-edit kunnen worden. Dan na het editten, voordat je gaat tekenen apply je eerst de Yaw dan de Pitch en dan de Roll op de worldmatrix van het model, en tadaa het werkt :).

Volgende frame doe je weer exact het zelfde, verander je yaw, pitch en roll variabelen, begin met een Matrix.Identity doet de yaw pitch en roll berekeningen en daarna zet je de worldmatrix van het model naar deze matrix.

Scale kun je geloof ik altijd doen (ik zou het voor het draaien doen) en translations doe je als laatste, dit zou moeten werken :).

Gimbal lock onstaat in software doordat je een al gedraaid object verder probeert te draaien terwijl 2 assen parrallel aan elkaar zijn, dat zou op deze manier niet kunnen gebeuren, omdat je telkens bij 0 begint.

[ Voor 12% gewijzigd door roy-t op 15-03-2010 09:19 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Als je object trilt is dat een teken dat je niet nauwkeurig genoeg je berekeningen doet. Vaak komt dat omdat je door hele kleine getallen deelt. Goede quaternion code heeft veel check of iets dicht bij de nul ligt en volgt dan een ander (vaak lineair) code pad.

(of je vermenigvuldigt steeds een matrix met een "delta", zonder te normalizeren, in plaats van hem helemaal opnieuw op te bouwen)

[ Voor 20% gewijzigd door Zoijar op 15-03-2010 10:28 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

roy-t schreef op maandag 15 maart 2010 @ 09:18:
Gimbal lock onstaat in software doordat je een al gedraaid object verder probeert te draaien terwijl 2 assen parrallel aan elkaar zijn, dat zou op deze manier niet kunnen gebeuren, omdat je telkens bij 0 begint.
Het is juist precies andersom. Bij het systeem wat jij (en ik) voorstelde krijg je juist "last" van gimbal lock. Als je pitch 90 graden is, dan doen yaw en roll hetzelfde. Bij geaccumuleerde transformaties in world space ipv local space heb je dat probleem niet. Dan is een draai linksom altijd linksom, onafhankelijk van de huidige orientatie van het object. Het probleem daarmee is dat je vaak het roll component (draaiing om de kijk-as) niet kunt besturen, en het object dus na een paar transformaties scheef hangt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Zoijar schreef op maandag 15 maart 2010 @ 10:16:
Als je object trilt is dat een teken dat je niet nauwkeurig genoeg je berekeningen doet.
Of dat je niet meer met een unit-length quaternion zit en 'm dus vaker moet normalizen. Eg. je krijgt ook translations mee.

[ Voor 5% gewijzigd door PrisonerOfPain op 15-03-2010 12:29 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

PrisonerOfPain schreef op maandag 15 maart 2010 @ 12:28:
Of dat je niet meer met een unit-length quaternion zit en 'm dus vaker moet normalizen. Eg. je krijgt ook translations mee.
Ja, dat kan ook, dat je quat niet meer unit length is.

Overigens hebben quats geen translatie component. Voglens mij moet je dan dual quaternions gebruiken, maar ik heb me daar nooit zo in verdiept eerlijk gezegd. Heb wel eens wat papers gezien die stelden dat dat beter is voor skinning.

Verder ben ik ook voorstander van het systeem waar je twee rotatie waardes aangeeft met je muis X/Y as en die steeds samenvoegd tot een nieuwe rotatie matrix.

(wiki legt gimbal lock prima uit met matrices: Wikipedia: Gimbal lock Je ziet meteen dat alpha en gamma hetzelfde doen als beta nul is )

[ Voor 14% gewijzigd door Zoijar op 15-03-2010 12:36 ]


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Zoijar schreef op maandag 15 maart 2010 @ 12:34:
[...]

Ja, dat kan ook, dat je quat niet meer unit length is.

Overigens hebben quats geen translatie component. Voglens mij moet je dan dual quaternions gebruiken, maar ik heb me daar nooit zo in verdiept eerlijk gezegd. Heb wel eens wat papers gezien die stelden dat dat beter is voor skinning.
Ze krijgen een translatie component als je ze naar een 4x4 matrix converteert om verderop in de pipeline te gebruiken. Normaal gezien is dat component 0 als je quaternion genormalized is, maar als 'ie niet genormalized is kan er daardoor ongewenste translatie plaatsvinden.

[ Voor 5% gewijzigd door PrisonerOfPain op 15-03-2010 13:27 ]


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

PrisonerOfPain schreef op maandag 15 maart 2010 @ 13:26:
Ze krijgen een translatie component als je ze naar een 4x4 matrix converteert om verderop in de pipeline te gebruiken.
Een quaternion kan je alleen naar een 3x3 matrix converteren. (je kan er later wel een translatie bij zetten en er homogene assen van maken om naar een 4x4 matrix te gaan, maar dat zit niet in de quaternion)

(maar je zal met een niet-unit quat geen orthonormale basis krijgen, wat resulteert in scaling en/of shearing. Misschien lijkt dat op kleine translaties)

[ Voor 34% gewijzigd door Zoijar op 15-03-2010 13:50 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Idd, quaternions werken per definitie alleen op het 3x3 'rotatie' deel van de matrix. De 4e rij en kolom worden nooit aangeraakt, ongeacht de componenten van de quaternion.

Hierarchische transformaties van quaternions en translaties kan trouwens ook vrij gemakkelijk zonder gebruik te maken van tussenliggende matrices. De rotatiequaternions kun je gewoon met elkaar vermenigvuldigen, de translaties moet je transformeren adhv de voorgaande rotaties en dan de huidige translatie erbij optellen. Een vector p transformeren met een quaternion q kan door simpelweg q∙p∙q- te doen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
Zoijar schreef op maandag 15 maart 2010 @ 13:34:
[...]

Een quaternion kan je alleen naar een 3x3 matrix converteren. (je kan er later wel een translatie bij zetten en er homogene assen van maken om naar een 4x4 matrix te gaan, maar dat zit niet in de quaternion)
Je hebt gelijk dat 't enkel nuttig is als 3x3 matrix ik zat verkeerd te denken, omdat je (aangezien het een complex getal is) de quaternion wel als matrix (2x2, of 4x4) uit kunt drukken. Echter heb je daar meestal niets aan.

Het punt was echter dat zodra je een non-unit quaternion converteert naar een matrix de matrix geen pure rotatiematrix meer is en er daardoor artifacts optreden omdat er geen geometrische interpretatie bestaat van deze quaternions.

De meeste fouten die ik heb gezien bij quaternions zijn vooralsnog accumulatiefouten, meestal optredende bij een integratiestap, welke opgelost kunnen worden door regelmatig(er) te normaliseren. Echter is het zonder relevante code niet makkelijk om vast te stellen of dat dat daadwerkelijk het geval is.

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
.oisyn schreef op maandag 15 maart 2010 @ 12:18:
[...]

Het is juist precies andersom. Bij het systeem wat jij (en ik) voorstelde krijg je juist "last" van gimbal lock. Als je pitch 90 graden is, dan doen yaw en roll hetzelfde. Bij geaccumuleerde transformaties in world space ipv local space heb je dat probleem niet. Dan is een draai linksom altijd linksom, onafhankelijk van de huidige orientatie van het object. Het probleem daarmee is dat je vaak het roll component (draaiing om de kijk-as) niet kunt besturen, en het object dus na een paar transformaties scheef hangt.
Je hebt helemaal gelijk, ik was even in de war met een framework methode die in 1 keer een Matrix maakt dmv Matrix.CreateFromYawPitchRoll(y,p,r) en intern dit probleem vermijd, het is dus inderdaad niet zo dat je, als je het in volgorde doet, wel werkt... doh excuses!

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • The Flying Dutchman
  • Registratie: Mei 2000
  • Laatst online: 29-07 21:57
Als je kijkt naar manieren om objecten rond te laten draaien, dan kun je ook eens zoeken op `arcball rotation'. Zelf ben ik daar nogal een fan van en ik vind dat het intuitief werkt. Deze methode maakt gebruik van een virtuele bol en je draait om het centrum van deze virtuele bol door met je muis op het oppervlak van de bol te klikken en die dan rond te draaien.

Als je op je scherm klikt met je muis, dan kun je uitrekenen op welk punt van het 3d oppervlak van de virtuele bol de pointer zich bevind (immers: je weet de center coordinaten van de bol en je weet de xy coordinaten van je muis, daarmee kun je de virtuele z coordinaat van je muis pointer uitrekenen). Als je begint met slepen sla je de vector van het centrum van de bol naar het beginpunt van de sleepactie op. Vervolgens reken je tijdens het slepen steeds uit wat de vector van centrum naar het huidige punt van de muis is.

Op die manier heb je altijd twee vectoren:
1. de vector van centrum van bol naar beginpunt van de sleep actie
2. de vector van centrum van bol naar huidige positie van de muis

Merk op dat de vectoren genormaliseerd moeten zijn... het is handig om dit al vroeg te doen: als je virtuele bol in de x richting bijvoorbeeld een radius van 400 pixels heeft en in de y richting een radius van 200 pixels, dan deel je de (x,y) coordinaten van je muis direct door (400,200), en dan is de z-component van je vector dus 1.0 - sqrt(x² + y²), of als x² + y² groter is dan 1, dan wordt z=0 en moet je de vector (x,y,0) normaliseren tot lengte 1 (overigens: misschien is het gewoon intuitiever om de virtuele bol in beide dimensies dezelfde afmeting te geven, het maakt niet uit of het volledige scherm gebruikt wordt of niet).

Met behulp van deze twee vectoren kun je de rotatie as uitrekenen (kruisproduct van de twee vectoren) en de hoek waarover gedraaid is (de hoek tussen de twee vectoren). Deze rotatie kun je dan met OpenGL eenvoudig uitvoeren. Geen quaternions nodig. Gimbal lock treed ook niet op.

Het voordeel van deze methode is dat het (in tegenstelling tot sommige andere methoden) niet uitmaakt op welke manier je de muis van punt A naar punt B sleept, het eindresultaat van de rotatie is altijd hetzelfde.

The Flying Dutchman


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

The Flying Dutchman schreef op woensdag 17 maart 2010 @ 11:59:
Als je kijkt naar manieren om objecten rond te laten draaien, dan kun je ook eens zoeken op `arcball rotation'. Zelf ben ik daar nogal een fan van en ik vind dat het intuitief werkt. Deze methode maakt gebruik van een virtuele bol en je draait om het centrum van deze virtuele bol door met je muis op het oppervlak van de bol te klikken en die dan rond te draaien.
Dat is vergelijkbaar met geaccumuleerde rotaties in world space, en heeft hetzelfde probleem dat het object op een gegeven moment scheef hangt. Kun je wel weer recht krijgen door een roterende beweging te maken met de muis, maar ik blijf het onhandig vinden.
Het voordeel van deze methode is dat het (in tegenstelling tot sommige andere methoden) niet uitmaakt op welke manier je de muis van punt A naar punt B sleept, het eindresultaat van de rotatie is altijd hetzelfde.
Onjuist. Je muis eerst naar beneden bewegen en dan naar rechts geeft een ander resultaat dan de muis over een rechte lijn naar het eindpunt bewegen. Heeft ook te maken met het punt wat ik hierboven opmerkte. Tenzij je altijd de rotatie berekent tussen het origineel geklikte punt en waar de muis momenteel is, maar dan werkt het niet meer intuitief.

[ Voor 5% gewijzigd door .oisyn op 17-03-2010 12:06 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • The Flying Dutchman
  • Registratie: Mei 2000
  • Laatst online: 29-07 21:57
.oisyn schreef op woensdag 17 maart 2010 @ 12:03:
[...]

Onjuist. Je muis eerst naar beneden bewegen en dan naar rechts geeft een ander resultaat dan de muis over een rechte lijn naar het eindpunt bewegen. Heeft ook te maken met het punt wat ik hierboven opmerkte. Tenzij je altijd de rotatie berekent tussen het origineel geklikte punt en waar de muis momenteel is, maar dan werkt het niet meer intuitief.
Nee hoor, je muist eerst naar beneden en dan naar rechts geeft precies hetzelfde eind resultaat als je muis in een rechte lijn bewegen. De reden is heel eenvoudig: je bewaart de vector van het begin van de rotatie actie, deze vector blijft hetzelfde gedurende de gehele actie. De vector aan het einde van de rotatie is ook exact hetzelfde (of je nou in een rechte lijn of in een zigzag beweging naar het eindpunt beweegt, dat eindpunt is hetzelfde).

Dus je hebt twee dezelfde vectoren, dat betekend: dezelfde normaal (rotatie as) en dezelfde rotatie hoek (hoek tussen vectoren). Dan is je rotatie per definitie gelijk hoe je ook van punt A naar punt B beweegt.

edit: bedoel je misschien dat twee opeenvolgende rotatie acties (van punt A naar C, dan van punt C naar B ) een ander resultaat oplevert dan een directe rotatie actie (van punt A direct naar B )? Dat zou inderdaad verschillende resultaten op kunnen leveren denk ik. Ik had het over een enkele rotatie actie (van punt A naar B, maar via punt C zonder de rotatie actie te beeindigen op punt C). In dat geval heb je wel hetzelfde resultaat ongeacht op welke manier je de muis van punt A naar B beweegt namelijk.

edit 2: nogmaals naar je reactie gekeken, volgens mij zeg je dat het niet meer intuitief is als je de rotatie altijd ten opzichte van het originele punt (het begin punt van de rotatie dus) berekend, maar ben je het wel met me eens dat je dan altijd dezelfde rotatie verkrijgt... Dat is nou precies wat ik bedoelde: je moet de rotatie vanaf het origineel geklikte punt berekenen. Persoonlijk vind ik dat wel intuitief, maar daarover zullen de meningen misschien wel verschillen neem ik aan ;).

[ Voor 31% gewijzigd door The Flying Dutchman op 19-03-2010 10:55 ]

The Flying Dutchman


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

We zeggen idd hetzelfde, maar we zijn het oneens over de intuitie van het geheel :)

Ik vind het niet intuitief omdat het systeem doet lijken alsof je echt met je vinger een bal over z'n as roteert. Echter is dat niet het geval, als je je muis eerst naar beneden beweegt, en dan naar rechts, dan zal de bal in de beweging naar rechts niet een mooie draai rechtsom maken, maar ook iets om de kijkrichting draaien. Ik vermoed dat dit voor een rare ervaring zorgt.

[ Voor 5% gewijzigd door .oisyn op 19-03-2010 11:14 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1