]> Git trees. - libqmvoc.git/commitdiff
Port the Kalzium 3D code to the Eigen math template library.
authorBenoît Jacob <jacob.benoit.1@gmail.com>
Sat, 21 Oct 2006 12:15:17 +0000 (12:15 +0000)
committerBenoît Jacob <jacob.benoit.1@gmail.com>
Sat, 21 Oct 2006 12:15:17 +0000 (12:15 +0000)
Now the Kalzium 3D code has a dependency on trunk/kdesupport/eigen.

svn path=/trunk/KDE/kdeedu/kalzium/src/kalziumglhelperclasses.cpp; revision=597706

kalzium/kalziumglhelperclasses.cpp
kalzium/kalziumglhelperclasses.h
kalzium/kalziumglwidget.cpp

index a1e54018caf3742f827c89f6bfc20fbe59eb2282..58347841e161d164d11a9a87f7829fd7a3a4a0c6 100644 (file)
@@ -15,6 +15,7 @@
 
 using namespace KalziumGLHelpers;
 using namespace OpenBabel;
+using namespace Eigen;
 
 MolStyle::MolStyle( BondStyle bondStyle, AtomStyle atomStyle,
        double singleBondRadius,
@@ -131,12 +132,12 @@ bool VertexArray::allocateBuffers()
 
        freeBuffers();
 
-       m_vertexBuffer = new Vector[m_vertexCount];
+       m_vertexBuffer = new Vector3f[m_vertexCount];
        if( ! m_vertexBuffer ) return false;
        
        if( m_hasSeparateNormalBuffer )
        {
-               m_normalBuffer = new Vector[m_vertexCount];
+               m_normalBuffer = new Vector3f[m_vertexCount];
                if( ! m_normalBuffer ) return false;
        }
        else m_normalBuffer = m_vertexBuffer;
@@ -204,29 +205,41 @@ void Sphere::computeVertex( int strip, int column, int row)
        strip %= 5;
        int next_strip = (strip + 1) % 5;
 
+       // the index of the vertex we want to store the result in
        unsigned short index = indexOfVertex( strip, column, row );
 
-       const double phi = ( 1 + sqrt(5) ) / 2;
-
-       const vector3 northPole( 0, 1, phi );
-       const vector3 northVertices[5] = {
-               vector3( 0, -1, phi ),
-               vector3( phi, 0, 1 ),
-               vector3( 1, phi, 0 ),
-               vector3( -1, phi, 0 ),
-               vector3( -phi, 0, 1 ) };
-       const vector3 southVertices[5] = {
-               vector3( -1, -phi, 0 ),
-               vector3( 1, -phi, 0 ),
-               vector3( phi, 0, -1 ),
-               vector3( 0, 1, -phi ),
-               vector3( -phi, 0, -1 )
+       // reference to the vertex we want to store the result in
+       Vector3f & vertex = m_vertexBuffer[ index ];
+
+       // the "golden ratio", useful to construct an icosahedron
+       const float phi = ( 1 + sqrt(5) ) / 2;
+
+       // the 12 vertices of the icosahedron
+       const Vector3f northPole( 0, 1, phi );
+       const Vector3f northVertices[5] = {
+               Vector3f( 0, -1, phi ),
+               Vector3f( phi, 0, 1 ),
+               Vector3f( 1, phi, 0 ),
+               Vector3f( -1, phi, 0 ),
+               Vector3f( -phi, 0, 1 ) };
+       const Vector3f southVertices[5] = {
+               Vector3f( -1, -phi, 0 ),
+               Vector3f( 1, -phi, 0 ),
+               Vector3f( phi, 0, -1 ),
+               Vector3f( 0, 1, -phi ),
+               Vector3f( -phi, 0, -1 )
                 };
-       const vector3 southPole( 0, -1, -phi );
+       const Vector3f southPole( 0, -1, -phi );
 
-       const vector3 *v0, *v1, *v2;
+       // pointers to the 3 vertices of the face of the icosahedron
+       // in which we are
+       const Vector3f *v0, *v1, *v2;
+
+       // coordinates of our position inside this face.
+       // range from 0 to m_detail.
        int  c1, c2;
 
+       // first, normalize the global coords row, column
        if( row >= 2 * m_detail && column == 0 )
        {
                strip--;
@@ -236,6 +249,8 @@ void Sphere::computeVertex( int strip, int column, int row)
                column = m_detail;
        }
 
+       // next, determine in which face we are, and determine the coords
+       // of our position inside this face
        if( row  <= m_detail )
        {
                v0 = &northVertices[strip];
@@ -269,17 +284,13 @@ void Sphere::computeVertex( int strip, int column, int row)
                c2 = 2 * m_detail - row;
        }
 
-       double u1 = double(c1) / m_detail;
-       double u2 = double(c2) / m_detail;
-
-       vector3 v = *v0 + u1 * ( *v1 - *v0 ) + u2 * ( *v2 - *v0 );
-       v.normalize();
+       // now, compute the actual coords of the vertex
+       float u1 = static_cast<float>(c1) / m_detail;
+       float u2 = static_cast<float>(c2) / m_detail;
+       vertex = *v0 + u1 * ( *v1 - *v0 ) + u2 * ( *v2 - *v0 );
 
-       Vector *vertex =
-               &m_vertexBuffer[ index ];
-       vertex->x = v.x();
-       vertex->y = v.y();
-       vertex->z = v.z();
+       // project the vertex onto the sphere
+       vertex.normalize();
 }
 
 int Sphere::getVertexCount()
@@ -336,7 +347,7 @@ void Sphere::setup( int detail )
        initialize();
 }
 
-void Sphere::draw( const vector3 &center, double radius )
+void Sphere::draw( const Vector3d &center, double radius )
 {
        glPushMatrix();
        glTranslated( center.x(), center.y(), center.z() );
@@ -372,66 +383,63 @@ void Cylinder::buildBuffers()
                float x = cosf( angle );
                float y = sinf( angle );
 
-               m_normalBuffer[ 2 * i ].x = x;
-               m_normalBuffer[ 2 * i ].y = y;
-               m_normalBuffer[ 2 * i ].z = 0.0;
+               m_normalBuffer[ 2 * i ].x() = x;
+               m_normalBuffer[ 2 * i ].y() = y;
+               m_normalBuffer[ 2 * i ].z() = 0.0;
 
-               m_vertexBuffer[ 2 * i ].x = x;
-               m_vertexBuffer[ 2 * i ].y = y;
-               m_vertexBuffer[ 2 * i ].z = 1.0;
+               m_vertexBuffer[ 2 * i ].x() = x;
+               m_vertexBuffer[ 2 * i ].y() = y;
+               m_vertexBuffer[ 2 * i ].z() = 1.0;
 
-               m_normalBuffer[ 2 * i + 1 ].x = x;
-               m_normalBuffer[ 2 * i + 1 ].y = y;
-               m_normalBuffer[ 2 * i + 1 ].z = 0.0;
+               m_normalBuffer[ 2 * i + 1 ].x() = x;
+               m_normalBuffer[ 2 * i + 1 ].y() = y;
+               m_normalBuffer[ 2 * i + 1 ].z() = 0.0;
 
-               m_vertexBuffer[ 2 * i + 1 ].x = x;
-               m_vertexBuffer[ 2 * i + 1 ].y = y;
-               m_vertexBuffer[ 2 * i + 1 ].z = 0.0;
+               m_vertexBuffer[ 2 * i + 1 ].x() = x;
+               m_vertexBuffer[ 2 * i + 1 ].y() = y;
+               m_vertexBuffer[ 2 * i + 1 ].z() = 0.0;
        }
 }
 
-void Cylinder::draw( const vector3 &end1, const vector3 &end2,
+void Cylinder::draw( const Vector3d &end1, const Vector3d &end2,
        double radius, int order, double shift )
 {
        // the "axis vector" of the cylinder
-       vector3 axis = end2 - end1;
+       Vector3d axis = end2 - end1;
        
        // find two unit vectors v, w such that
        // (axis,v,w) is an orthogonal basis
-       vector3 v, w;
-       createOrthoBasisGivenFirstVector( axis, v, w );
+       Vector3d v, w;
+       createOrthoBasisGivenFirstVector( axis, &v, &w );
+       v *= radius;
+       w *= radius;
 
        // construct the 4D transformation matrix
-       GLdouble matrix[16];
-
-       // column 1
-       matrix[0] = v.x() * radius;
-       matrix[1] = v.y() * radius;
-       matrix[2] = v.z() * radius;
-       matrix[3] = 0.0;
-
-       // column 2
-       matrix[4] = w.x() * radius;
-       matrix[5] = w.y() * radius;
-       matrix[6] = w.z() * radius;
-       matrix[7] = 0.0;
-
-       // column 3
-       matrix[8] = axis.x();
-       matrix[9] = axis.y();
-       matrix[10] = axis.z();
-       matrix[11] = 0.0;
-
-       // column 4
-       matrix[12] = end1.x();
-       matrix[13] = end1.y();
-       matrix[14] = end1.z();
-       matrix[15] = 1.0;
+       Matrix4d matrix;
+
+       matrix(0, 0) = v(0);
+       matrix(1, 0) = v(1);
+       matrix(2, 0) = v(2);
+       matrix(3, 0) = 0.0;
+
+       matrix(0, 1) = w(0);
+       matrix(1, 1) = w(1);
+       matrix(2, 1) = w(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 );
-
+       glMultMatrixd( matrix.array() );
        if( order == 1 ) VertexArray::draw();
        else for( int i = 0; i < order; i++)
        {
@@ -626,17 +634,17 @@ void TextRenderer::print( int x, int y, const QString &string )
        if( ! m_isBetweenBeginAndEnd ) do_end();
 }
 
-bool KalziumGLHelpers::createOrthoBasisGivenFirstVector
-       ( const vector3 &U, vector3 & v, vector3 & w )
+void KalziumGLHelpers::createOrthoBasisGivenFirstVector
+       ( const Vector3d &U, Vector3d * v, Vector3d * w )
 {
-       if( ! U.createOrthoVector( v ) ) return false;
-       w = cross( U, v );
-       w.normalize();
-       return true;
+       U.makeOrthoVector(v);
+       *w = cross( U, *v );
+       w->normalize();
 }
+
 /*
-void LinearRegression( const std::list<vector3 *> & points,
-       vector3 & ret_plane_base_point, vector3 & ret_plane_normal_vector )
+void LinearRegression( const std::list<Vector3d *> & points,
+       Vector3d & ret_plane_base_point, Vector3d & ret_plane_normal_vector )
 {
        double sum_x = 0.0;
        double sum_y = 0.0;
@@ -648,7 +656,7 @@ void LinearRegression( const std::list<vector3 *> & points,
        double sum_yz = 0.0;
        double sum_zz = 0.0;
 
-       for( std::list<vector3 *>::const_iterator iter = points.begin();
+       for( std::list<Vector3d *>::const_iterator iter = points.begin();
                iter != points.end(); iter++ )
        {
                double x = iter->x();
index 61b7fee66526e642e3f3596f68dc19421670ef69..2783639693c368da2ff3be0ed1a2c89d4cfa1bca 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef KALZIUMGLHELPERCLASSES_H
 #define KALZIUMGLHELPERCLASSES_H
 
-#include <math.h>
+#include <eigen/matrix.h>
 #include <QGLWidget>
 #include <GL/glu.h>
 #include <QPainter>
@@ -157,7 +157,9 @@ struct Color
 *
 * Returns false if something went wrong.
 */
-bool createOrthoBasisGivenFirstVector( const OpenBabel::vector3 &U, OpenBabel::vector3 & v, OpenBabel::vector3 & w );
+void createOrthoBasisGivenFirstVector( const Eigen::Vector3d & U,
+                                             Eigen::Vector3d * v,
+                                             Eigen::Vector3d * w );
 
 /*void LinearRegression( const std::list<vector3 *> & points,
        vector3 & ret_plane_base_point, vector3 & ret_plane_normal_vector );
@@ -173,23 +175,12 @@ bool createOrthoBasisGivenFirstVector( const OpenBabel::vector3 &U, OpenBabel::v
 class VertexArray
 {
        protected:
-
-               /**
-                * This struct represents a vector to be passed to OpenGL as
-                * part of a Vertex Array. Here we don't want to use OpenBabel's
-                * vector3 class, because it uses double-precision coordinates,
-                * which would be a waste of memory here. **/
-               struct Vector
-               {
-                       GLfloat x, y, z;
-               };
-
                /** Pointer to the buffer storing the vertex array */
-               Vector *m_vertexBuffer;
+               Eigen::Vector3f *m_vertexBuffer;
                /** Pointer to the buffer storing the normal array.
                 * If m_hasSeparateNormalBuffer is false, then this is equal
                 * to m_vertexBuffer. */
-               Vector *m_normalBuffer;
+               Eigen::Vector3f *m_normalBuffer;
                /** Pointer to the buffer storing the indices */
                unsigned short *m_indexBuffer;
                /** The mode in which OpenGL should interpred the vertex arrays
@@ -323,7 +314,7 @@ class Sphere : public VertexArray
 
                /** draws the sphere at specifiec position and with
                 * specified radius */
-               void draw( const OpenBabel::vector3 &center, double radius );
+               void draw( const Eigen::Vector3d &center, double radius );
 };
 
 /**
@@ -368,7 +359,7 @@ class Cylinder : public VertexArray
                        this is interpreted as the displacement of the axis
                        of the drawn cylinders from the axis (end1 - end2).
                 */
-               void draw( const OpenBabel::vector3 &end1, const OpenBabel::vector3 &end2,
+               void draw( const Eigen::Vector3d &end1, const Eigen::Vector3d &end2,
                        double radius, int order = 1, double shift = 0.0 );
 };
 
index 3345d273ccda980675e43f5d46c91059bbb5daa4..2073b88afbcf4bf060abc3c378162a91bb5d9a50 100644 (file)
@@ -29,6 +29,7 @@
 
 using namespace KalziumGLHelpers;
 using namespace OpenBabel;
+using namespace Eigen;
 
 KalziumGLWidget::KalziumGLWidget( QWidget * parent )
        : QGLWidget( parent )
@@ -252,7 +253,7 @@ void KalziumGLWidget::renderHighlighting()
        {
                Color( 1.0, 1.0, 1.0, 0.4 ).applyAsMaterials();
                glLoadName( m_clickedAtom->GetIdx() );
-               m_sphere.draw( m_clickedAtom->GetVector(),
+               m_sphere.draw( m_clickedAtom->GetVector().AsArray(),
                        0.18 + m_molStyle.getAtomRadius( m_clickedAtom ) );
        }
 
@@ -265,7 +266,7 @@ void KalziumGLWidget::renderHighlighting()
                        if( atom != m_clickedAtom )
                        {
                                glLoadName( atom->GetIdx() );
-                               m_sphere.draw( atom->GetVector(),
+                               m_sphere.draw( atom->GetVector().AsArray(),
                                        0.18 + m_molStyle.getAtomRadius(
                                                atom ) );
                        }
@@ -431,7 +432,8 @@ void KalziumGLWidget::drawAtom( OBAtom *atom )
 {
        glLoadName( atom->GetIdx() );
        Color( atom ).applyAsMaterials();
-       m_sphere.draw( atom->GetVector(), m_molStyle.getAtomRadius( atom ) );
+       m_sphere.draw( atom->GetVector().AsArray(),
+                      m_molStyle.getAtomRadius( atom ) );
 }
 
 void KalziumGLWidget::drawBond( OBBond *bond )
@@ -439,9 +441,9 @@ void KalziumGLWidget::drawBond( OBBond *bond )
        OBAtom *atom1 = static_cast<OBAtom *>( bond->GetBgn() );
        OBAtom *atom2 = static_cast<OBAtom *>( bond->GetEnd() );
 
-       vector3 v1 = atom1->GetVector();
-       vector3 v2 = atom2->GetVector();
-       vector3 v3 = ( v1 + v2 ) / 2;
+       Vector3d v1 ( atom1->GetVector().AsArray() );
+       Vector3d v2 ( atom2->GetVector().AsArray() );
+       Vector3d v3 = ( v1 + v2 ) / 2;
 
        int order;
        if( m_molStyle.m_renderMultipleBonds == false || bond->IsSingle() )
@@ -556,8 +558,8 @@ void KalziumGLWidget::prepareMoleculeData()
        m_molRadiusWithoutElectrons = 0.0;
        FOR_ATOMS_OF_MOL( a, m_molecule )
        {
-               vector3 v = a->GetVector();
-               double rad = v.length();
+               Vector3d v( a->GetVector().AsArray() );
+               double rad = v.norm();
                if( rad > m_molRadiusWithoutElectrons )
                        m_molRadiusWithoutElectrons = rad;
        }