[3d/math] Transformaties samenvoegen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Stel ik heb twee transformatie nodes die een quaternion (m_r) voor orientatie en een vector (m_t) voor translatie/positie bevatten. De transformatie van punt p is dan: im(m_r * p * conj(m_r)) + m_t, of als we quaternion/vector vemenigvuldiging definieren: m_r*p + m_t

Nu voeg ik twee zulke transformaties samen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
// n2 after n1, as in (n2 o n1)(x)
template <typename T>
TransformationNode<T> operator*(const TransformationNode<T>& n2, const TransformationNode<T>& n1) {
    // R2*(R1*p + t1) + t2
    // = R2*R1*p + R2*t1 + t2
    // = (R2*R1)*p + (R2*t1 + t2)

    return TransformationNode<T>(
                n2.getRotation() * n1.getRotation(), 
                transformVector(n2.getRotation(), n1.getTranslation())
                + n2.getTranslation()
    );
}

So far so good. Gewoon uitschrijven en dan de delen invullen zoals in de 3 regels commentaar.

Ik wil nu nog een schaal factor toevoegen. Je krijgt dan met een schaal vector m_s voor de xform: m_r*(m_s*p) + m_t, dus schalen, roteren, transleren.

Vraag: kan je met schaal op een zelfde manier twee transformaties samenvoegen?

Ik kom hierop: // R2*s2*(R1*s1*p + t1) + t2 = R2*s2*R1*s1*p + R2*s2*t1 + t2, maar weet niet hoe ik dat in de juiste delen (schaal, rotatie, translatie) op moet splitsen. Kan het ook nergens vinden online. Doet niemand dat? (sidenote: als ik alles naar matrices omzet en vermenigvuldig is het triviaal natuurlijk, maar kan het rechtstreeks zoals boven?)


Tweede vraag uit nieuwgierigheid: ik heb ook dual quaternions geimplementeerd, die encapsuleren rotatie/translatie; wordt dat door mensen gebruikt in graphics pipelines zoals mijn eerste voorbeeld boven? Of eigenlijk alleen voor skinning en quaternion blending? Ik zie namelijk als blending niet nodig is niet echt voordeel over een quaternion/translatie paar. Sterker nog, dat is 7 floats ipv 8 en normaliseert makkelijker.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Hmm volgens mij heb ik het al (schaal aan de andere kant vermenigvuldigen), maar ik weet niet 100% zeker of het klopt. Geeft wel dezelfde antwoorden als matrices. Klopt dit?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// n2 after n1, as in (n2 o n1)(x)
template <typename T>
TransformationNode<T> operator*(const TransformationNode<T>& n2, const TransformationNode<T>& n1) {
    // R2*((R1*(p*s1) + t1)*s2) + t2 = R2*(R1*p*s1*s2 + t1*s2) + t2 = R2*R1*p*s1*s2 + R2*t1*s2 + t2
    // (R2*R1)*(p*(s1*s2)) + (R2*(t1*s2) + t2)

    return TransformationNode<T>(
                n2.getRotation() * n1.getRotation(),
                transformVector(n2.getRotation(), n1.getTranslation() * n2.getScale()) + n2.getTranslation(),
                n1.getScale() * n2.getScale()
    );

//  return TransformationNode<T>(n2.getLocalToParentMatrix() * n1.getLocalToParentMatrix());
}

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

Heb je dan niet een volgorde probleem?

Normaal bouw je een matrix zodanig dat je in volgorde doet [scaling, rotation, translation].
Vermenigvuldinging van 2 matrices word dan [scaling1, rotation1, translation1, scaling2, rotation2, translation2]
In jouw formule zie ik (p * (s1 * s2)) langskomen, dus jij begint met [scaling1, scaling2].

Ik ben geen 3D expert, dus wat ik zou doen is gewoon proberen met een setje random input (vergeet niet om non-uniform scaling te gebruiken) in een loop, durrt niet zo lang om te schrijven :)

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat jij wil kan volgens mij helemaal niet. Een scale kun je niet altijd louter uitdrukken in termen van X, Y en Z.

Een voorbeeld in 2D. Stel we hebben een vierkant met lengte en breedte 1. Dan roteren we die met 45 graden (het wordt een ruit), vervolgens schalen we over de X-as met 2 (een brede ruit / parallellogram), en dan draaien we weer terug met 45 graden.

Wat je overhoudt is een vierkant die over de vector (0.707, 0.707) geschaald is met factor 2. Het rotatiegedeelte van je vierkant is 0, maar die schaal kun je niet uitdrukken in termen van individuele schalen op de unit-assen (X en Y zou dan gelijk zijn, maar dat is een uniform scale dus dat klopt niet). Het enige dat je kunt doen is 3 vectors bijhouden voor de richting en schaal van de originele assen, maar dan heb je gewoon een 3x3 matrix en heb je je quaternions ook niet meer nodig :)

[ Voor 12% gewijzigd door .oisyn op 11-04-2012 10:29 ]

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!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Maar het is altijd lokale scale. Dus als je een vierkant 45 graden draait en over de/zijn x-as schaalt, wordt het een rechthoek. Als je de parent van dat vierkant schaalt over zijn x-as, dan wordt het een ruit.

Het lijkt te doen wat ik ervan verwacht, maar ik ben nog niet overtuigd. Verder hoef ik geen "rare" scale operaties; unit size uitdrukken is genoeg in principe, i.e. dit object is in meters, deze in halve centimeters.

@MLM: ja, dat is precies waar ik bang voor ben. Maar tot dusver lijkt het alsof ik dezelfde matrices eruit krijg.

(ik reken ook terug van matrix naar transform door de lengte van de drie basis vectoren te nemen voor scale, die te normaliseren, quaternion van maken, en dan translatie rij er uit pakken voor positie. als er een shear oid in zit werkt dat volgens mij ook niet)

[ Voor 30% gewijzigd door Zoijar op 11-04-2012 10:49 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is niet altijd een lokale schaal, want de (geroteerde) translatie schaal je wel. Alleen het rotatiegedeelte dus niet. Niet echt bepaald intuitief als je het mij vraagt :)

[ Voor 3% gewijzigd door .oisyn op 11-04-2012 10:52 ]

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!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Dat komt omdat de translatie van een child wordt uitgedrukt in parent coordinaten; dat is bij een matrix ook zo, omdat je translatie als laatste doet ben je al in parent space. Dus schaal je de translatie vector met de schaal factor van de parent om op dezelfde eenheden te komen... denk ik :) En waarom eerst schalen en dan roteren gelijk is aan eerst roteren en dan schalen in dit geval, is omdat je de schaal in de geroteerde/lokale ruimte uitvoert. Als ik de x-as 2x schaal en 45 graden roteer heb ik een 45 graden lijn. Als ik de x-as meteen 45 graden roteer en dan over de nieuwe x-as schaal, heb ik weer een 45 graden lijn.

(ik denk hardop...)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als ik de x-as meteen 45 graden roteer en dan over de nieuwe x-as schaal, heb ik weer een 45 graden lijn.
Dat is dus niet waar. Als de lijn oorspronkelijk door de punten (0, 0) en (1, 0) gaat, dan gaat ie naar 45 graden rotatie door de punten (0, 0) en (0.707, 0.707). Als je dat tweede punt over de nieuwe x-as schaalt met 2x dan krijg je (1.414, 0.707). De lijn door (0, 0) en (1.414, 0.707) heeft geen 45 graden slope.

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!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Maar de nieuwe x-as is ook 45 graden gedraaid dan, dus (0,0) -> (0.707, 0.707). als ik daar 2x over schaal krijg ik (1.414, 1.414). Als ik over de oude x-as schaal krijg ik (1.414, 0.707). Dat bedoelde ik. (kan dat ik onzin uitkraam hoor :) )

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Oh ja ik zou "nieuw" en "oud" precies hebben omgedraaid ;).

Kijk, als je wilt dat het zo werkt dan werkt het natuurlijk prima, maar persoonlijk vind ik het raar dat je met jouw implementatie wel kunt doen:
1. rotatie om een punt: transleer -> roteer -> -transleer
2. scaling om een punt: transleer -> scale -> -transleer

Maar niet:
3. scale over een specifieke as: roteer -> scale -> -roteer

Punt 2 geeft de indruk dat je schaalt in word space, waardoor punt 3 ook zou kunnen, maar die kan niet. Maar je schaalt ook niet in local space, want dan zou punt 2 niet kunnen. Je schaalt in een soort van world space die ontdaan is van alle rotaties tov de local space.

[ Voor 14% gewijzigd door .oisyn op 11-04-2012 11:34 ]

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!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
.oisyn schreef op woensdag 11 april 2012 @ 11:32:
Kijk, als je wilt dat het zo werkt dan werkt het natuurlijk prima,
Voor wat ik nodig heb werkt het volgens mij wel ja. Ik kan nu verschillende objecten in andere units samenvoegen. Ik kan een enkel geometrisch object met unit afmetinen op de GPU zetten, zoals een bounding box, cylinder of bol, en die niet-uniform schalen naar de juiste afmetingen. Ik zie eigenlijk niet in wanneer ik over een andere as zou willen schalen.
maar persoonlijk vind ik het raar dat je met jouw implementatie wel kunt doen:
1. rotatie om een punt: transleer -> roteer -> -transleer
2. scaling om een punt: transleer -> scale -> -transleer

Maar niet:
3. scale over een specifieke as: roteer -> scale -> -roteer
Ja, daar heb je gelijk in. Nouja, ik zou liever een algemene oplossing hebben, maar ik zie niet hoe ik dat moet doen. Ik heb ook nog dit gevonden:http://www.euclideanspace.com/maths/geometry/affine/nonMatrix/index.htm en als je dan helemaal onderaan kijkt probeert hij hetzelfde, zonder succes (?)

Hoe doet een normale game engine dit dan? Gewoon geen schaal? Of alles naar matrix vorm omzetten? QR decompositie op al je matrices? Ik dacht dat quaternion/translatie wel veel gebruikt werd, maar hoe zit dat dan met schaal?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 17-09 14:05

.oisyn

Moderator Devschuur®

Demotivational Speaker

Bone transformations bevatten typisch geen scale. En anders moet je aan matrices gaan denken ja, of alleen uniform scale toestaan.

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