• To: eigen@xxxxxxxxxxxxxxxxxxx
• Subject: Re: [eigen] about Transform API
• From: "Gael Guennebaud" <gael.guennebaud@xxxxxxxxx>
• Date: Wed, 27 Aug 2008 17:32:52 +0200
• Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references; b=e17Q98mH2xcpCQ/0fJUiuqFx0kBtEzXVpCu4Of46iVDNLU+ivDZjo5I9NP2H4A0Wnf b7514YHBSqbn9CAO1uxXhKptxeK/1JUlNPGm1ZmRVDwTddJ+oM2Z8JkPna3+7kN0xQsA Dpc2EES7MzkHkwl211XCaDmDmrxXj2eNbLXBI=

```On Wed, Aug 27, 2008 at 4:42 PM, Thomas Vaughan <tevaughan@xxxxxxxxx> wrote:
>
> On Wed, Aug 27, 2008 at 4:47 AM, Gael Guennebaud
> <gael.guennebaud@xxxxxxxxx> wrote:
> >
> > For instance if you want to concatenate a scale S to a transformation
> > T you would write:
> >
> > paper:  T' = T * S
> > or
> > paper:  T' =  S * T
> >
> > while in Eigen we currently have to write:
> >
> > eigen:   T = T.scale(Vector3f(sx,sy,sz));
> > or
> > eigen:   T = T.prescale(Vector3f(sx,sy,sz));
>
> I've not yet used scaling in eigen.  I presume that the Vector is used to
> initialize a diagonal matrix that is multiplied in (or perhaps you
> use a more efficient algorithm to scale the transform).

right, .scale(s), essentially does: "linear *= s.asDiagonal();" and
fortunately this product is automatically and fully optimized by
Eigen.

>
> > What about doing something similar to what I did with rotations and
> > overloading the correct *= and * operators such that you could write:
> >
> > eigen:   T = T * Scale3f(sx,sy,sz);
> > eigen:   T *= Scale3f(sx,sy,sz);
> > or
> > eigen:   T = Scale3f(sx,sy,sz) * T;
>
> Presumably, Scale3f(sx,sy,sz) would construct a 3x3 diagonal matrix.
> The scale constructor above seems much prettier to me than initializing
> with a Vector, but I suppose that you would need a Vector initialization
> of Scale for the arbitrary NxN case.  (As you have probably noticed, I
> prefer to instantiate a Vector only if it is really a vector. :^)

in my imagination, Scale and Translation would be new types with
appropriate operator *... Internally they would store a Vector.
An example:
Translation() * v;
will actually be compiled to a single vector addition ! (That means
that Translation really means TranslationTransform and not
TranslationVector)

explicit constructors from vectors will also be part of the game. In
particular I don't want to enforce people to use these classes to
store their translation vectors or non uniform scaling factors (see
the story about Point vs Vector). So one could use these classes only
to "type" their vector/array to create a Transform object:

T = Scale(a_vector_considered_as_a_generic_array) *
Translation(another_vector_which_here_makes_more_sense_to_use_a_vector);

> > then if you want to express:
> >
> > paper: T = S * R * L;
> >
> > (where L is a translation)
> > you could write:
> >
> > eigen:  T = Scale3f(..) * RotationType(....) * Translation3f(...);
> > (with RotationType in {Quaternion, Matrix, AngleAxis, Rotation2D } )
>
> So Translation3f() constructs a 4x4, and the first multiplication
> (between the Scale and the Rotation) is between a pair of 3x3s, right?

to evaluate this expression we have 3 steps:
1 - convert RotationType to a 3x3 matrix if needed (I don't know yet
how and where doing it)
2 - performs a "Scale3 * Matrix3" product which yields to an optimized
"Diagonal * Matrix3" product
3 - performs an optimized "Matrix3 * Translation" product which
returns a Transform (~Matrix4) object.

if I'm right we have to consider 4*4=16 different operator *  from

> > instead of the current:
> >
> > eigen:  T.setIdentity();
> > eigen:  T.scale(...);
> > eigen:  T.rotate(...);
> > eigen:  T.translate(...);
> >
> > ok, actually the rotate, scale and translate methods return a reference to
> > T, so currently you can still write:
> >
> > eigen:  T.setIdentity();
> > eigen:  T.scale(...).rotate(...).translate(...);
> >
> > that is not too bad in that case, but think about "T = R1 * L * T * R2"
> > which involves "pre*" versions of the methods:
> >
> > eigen:  T.pretranslate(L).prerotate(R1).rotate(R2);
>
> Yuck.
>
> > IMHO it's quite confusing because it does not give you the idea of the
> > transformation order: "R1 * L * T * R2".
>
> Right.
>
> > Also, perhaps we can keep both API ?
>
> Why not?

sure !

> > that's all folk, what do you think ?
>
> I think that it is a beautiful idea, at least in terms of the API.

so currently we have 1.75 pts versus 0.25 .... yeah, I count myself
for 0.75 in favor of that idea, 0.25 against because I'm a bit afraid
that will lead to the same unnecessary mess as having a Point type
.....

gael.

> --
> Thomas E. Vaughan
>
> There are only two kinds of people; those who accept dogma and know it,
> and those who accept dogma and don't know it. - G.K. Chesterton
>
>

```

 Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/