[wiskunde] quaternion rotaties gebaseerd op meerdere assen

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@modjes: mocht dit topic hier niet thuishoren, verplaats gerust.. kon geen beter forum bedenken!

ik heb een member functie in mijn quaternion class die een quaternion instelt op basis van een as en een hoek.

C++:
1
2
Quaternion rot;
rot.SetAngleAxis(pi * 0.5, Vector(1, 0, 0));


mijn identity wijst naar beneden, dus dit zou een quaternion opleveren die horizontaal staat. werkt prima.

maar nu heb ik meerdere assen met elk een gewenste hoek, en wil op basis daarvan mn quaternion maken.

dus bijv, 0.5 pi radialen over de x as en daarna 0.5 pi radialen over de z as.

ik dacht:

C++:
1
2
3
4
5
Quaternion rotX;
rotX.SetAngleAxis(pi * 0.5, Vector(1, 0, 0));
Quaternion rotZ;
rotZ.SetAngleAxis(pi * 0.5, Vector(0, 0, 1));
Quaternion resultaat = rotX * rotZ;


maar dit lijkt niet te werken (krijg iig een quaternion die in zoverre ongeldig is dat er bij omzetting naar de rotatiematrix die ik aan opengl stuur weinig meer zichtbaar is :P)

zit er een fout in mijn code of mag je uberhaupt niet hoeken+asjes op deze manier met elkaar minglen?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het lijkt me een fout in je quaternion code :). Een quaternion is vergelijkbaar met een matrix, waarbij een unit quaternion altijd een orthonormale rotatiematrix oplevert. Twee quaternions met elkaar vermenigvuldigen en daar de matrix van nemen zou hetzelfde resultaat moeten geven als van de twee quaternions de matrices nemen en die met elkaar vermenigvuldigen.

Gezien het feit dat een enkele quaternion wel goed gaat lijkt de fout in de vermenigvuldiging te zitten. Kun je die posten?

[ Voor 14% gewijzigd door .oisyn op 02-11-2009 15:03 ]

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!

Verwijderd

Topicstarter
je hebt gelijk .oisyn, er was een foutje ingeslopen :)

voor de liefhebber hier nog even de correcte:

C++:
1
2
3
4
5
6
7
8
9
10
Quaternion Quaternion::operator * (const Quaternion &fac) const {
  Quaternion result;

  result.elements[0] = elements[3] * fac.elements[0] + elements[0] * fac.elements[3] + elements[1] * fac.elements[2] - elements[2] * fac.elements[1];
  result.elements[1] = elements[3] * fac.elements[1] + elements[1] * fac.elements[3] + elements[2] * fac.elements[0] - elements[0] * fac.elements[2];
  result.elements[2] = elements[3] * fac.elements[2] + elements[2] * fac.elements[3] + elements[0] * fac.elements[1] - elements[1] * fac.elements[0];
  result.elements[3] = elements[3] * fac.elements[3] - elements[0] * fac.elements[0] - elements[1] * fac.elements[1] - elements[2] * fac.elements[2];

  return result;
}


(waarbij de w in elements[3])

heb wel het vermoeden dat deze functie wat efficienter kan, maargoed :P het werkt iig nu!

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 19-09 21:24

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als je je quaternion benadert als een (w, v) paar met w een scalar en v een 3-vector, dan is het resultaat van (a, b) * (c, d) gelijk aan (ac - b∙d, ad + cb + b×d)

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!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
Oef, regels van 150 chars... Dat zou voor mij aanleiding zijn om een operator\[] te introduceren en de boel te herschrijven tot:
C++:
1
2
3
4
5
6
7
8
9
Quaternion operator*(const Quaternion &a, const Quaternion &b)
{
  Quaternion c;
  c[0] = a[3]*b[0] + a[0]*b[3] + a[1]*b[2] - a[2]*b[1];
  c[1] = a[3]*b[1] + a[1]*b[3] + a[2]*b[0] - a[0]*b[2];
  c[2] = a[3]*b[2] + a[2]*b[3] + a[0]*b[1] - a[1]*b[0];
  c[3] = a[3]*b[3] - a[0]*b[0] - a[1]*b[1] - a[2]*b[2];
  return c;
}

Maar iederen z'n meug natuurlijk. ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
bedankt voor de suggesties mensen!

elke clocktick telt natuurlijk :)

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dan moet je handmatig de SSE code fine-tunen :) (in mijn ervaring hoeft quaternion code helemaal niet snel te zijn; die stukken worden bijna niet uitgevoerd. Overal waar je echt vaak iets doet loont het meestal om eerst de quaternion naar een matrix om te zetten.)

[ Voor 34% gewijzigd door Zoijar op 02-11-2009 17:23 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
hm ik zet em alleen om naar een matrix voor het renderen, als hij aan opengl wordt gevoerd. verder wordt er intern toch wel veel met quaternions gerekend, bijvoorbeeld bij het traversen van de scenegraph, om de afgeleide quaternion te krijgen van een object dat onder allerlei nodes hangt.. misschien toch wel handig dus, zo'n optimalisatie :)

jammer alleen dat gprof niet zo lekker werkt met multithreaded code :/

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 18:51
gprof is sowieso niet handig; al die instrumentation code verandert het (code én data) cacheprofiel van je code. Het is leuk om een ruw idee te krijgen van welke functies hoe vaak aangeroepen worden, maar niet echt handig om low-level te profilen (zeker niet in een taal als C++ waarin allerlei functies geïnlined worden; v.z.i.w. heb je met gprof alleen function call profiles, dus inlined functies worden meegeteld bij de functies die ze aanroepen).

Dan kun je beter een low-overhead profiler als oprofile gebruiken die in principe op instructieniveau werkt. Valgrind kan ook handig zijn als je kleine testcases kan maken, als je geïnteresseerd bent in het cacheprofiel van je code.
Pagina: 1