Hi List,

Avogadro is ported to Eigen 2, as of r1568.

You’ll need to check out Eigen2 from kdesupport, at the same place as

usual except that ‘eigen’ becomes ‘eigen2’ :

svn co svn:://anonsvn.kde.org/home/kde/trunk/kdesupport/eigen2

To install Eigen2, do:

mkdir eigen2-build

cd eigen2-build

cmake -DCMAKE_INSTALL_PREFIX=/your/prefix …/eigen2

make install

Now you should be able to build Avogadro. If cmake ever fails to find

Eigen2, use -DEIGEN2_INCLUDE_DIR=/path/to/eigen2 (the directory

containing the Eigen subdirectory).

There now is a WITH_SSE2 cmake option, which is explained in the

top-level CMakeLists.

Let me know if you have trouble with any aspect of Eigen2. If you

build the docs from SVN (cmake -DBUILD_DOC=ON, make), you’ll see the

beginning of a “Quick Start Guide”. Even without building docs

yourself, you can see the API docs of alpha7 there:

http://eigen.tuxfamily.org/api

I’d like to show you one of the places that benefited dramatically from

the move from Eigen 1 to Eigen 2. I hope this helps you take full

advantage of Eigen 2.

Let’s go to libavogadro/src/cylinder.cpp:

Here is the old Cylinder::draw() using Eigen 1:

{

Vector3d axis = end2 - end1;

```
Vector3d axisNormalized = axis.normalized();
Vector3d ortho1, ortho2;
ortho1.loadOrtho(axisNormalized);
ortho1 *= radius;
axisNormalized.cross( ortho1, &ortho2 );
// construct the 4D transformation matrix
Matrix4d matrix;
matrix(0, 0) = ortho1(0);
matrix(1, 0) = ortho1(1);
matrix(2, 0) = ortho1(2);
matrix(3, 0) = 0.0;
matrix(0, 1) = ortho2(0);
matrix(1, 1) = ortho2(1);
matrix(2, 1) = ortho2(2);
matrix(3, 1) = 0.0;
matrix(0, 2) = axis(0);
matrix(1, 2) = axis(1);
matrix(2, 2) = axis(2);
matrix(3, 2) = 0.0;
matrix(0, 3) = end1(0);
matrix(1, 3) = end1(1);
matrix(2, 3) = end1(2);
matrix(3, 3) = 1.0;
//now we can do the actual drawing !
glPushMatrix();
glMultMatrixd( matrix.array() );
glCallList( d->displayList );
glPopMatrix();
}
```

Here is the new Cylinder::draw() using Eigen 2. Notice how expression

templates allow to perform all vector operations in place, directly on

the blocks of the matrix, removing the need to first construct these

vectors and then copy them to blocks of the matrix.

{

// construct the 4D transformation matrix

Eigen::Matrix4d matrix;

matrix.row(3) << 0, 0, 0, 1;

matrix.block<3,1>(0,2) = end2 - end1; // the axis

```
Vector3d axisNormalized = matrix.block<3,1>(0,2).normalized();
matrix.block<3,1>(0,0) = axisNormalized.unitOrthogonal() * radius;
matrix.block<3,1>(0,1) = axisNormalized.cross(matrix.block<3,1>(0,0));
matrix.block<3,1>(0,3) = end1;
//now we can do the actual drawing !
glPushMatrix();
glMultMatrixd( matrix.data() );
glCallList( d->displayList );
glPopMatrix();
}
```

OK, finally, I’d like to take this occasion to draw your attention on

a couple of misc things that I fixed.

a) in Color, we were using glColor4fv in the apply() method but the

components were not stored as an array, hence there was no guarantee

that they would be adjacent in memory. My fault really, I wrote that

code a long time ago.

b) in GLPainter, you often used the gl methods like glVertex3d()

instead of glVertex3dv(). Remember, the ‘v’ variants are faster! Since

our data is generally stored as vectors, they’re also easier to call

and less error-prone.

By the way, i also made GLPainter use more Color::apply() instead of

glColor4f(r,g,b,a).

c) In order to apply a translation to a vector, you *don’t* need to

construct a 4x4 transformation matrix and multiply your vector by it.

I saw a lot of that in our source code. Applying a translation is just

adding two vectors. If you have a vector Position and want to apply to

it a translation by vector Displacement, the result is just Position +

Displacement. That’s just 3 FLOPs instead of about 30.

Cheers,

Benoit

This message was sent using IMP, the Internet Messaging Program.