]> Git trees. - libqmvoc.git/commitdiff
* Many OpenGL-Improvements
authorCarsten Niehaus <cniehaus@gmx.de>
Wed, 14 Jun 2006 13:56:32 +0000 (13:56 +0000)
committerCarsten Niehaus <cniehaus@gmx.de>
Wed, 14 Jun 2006 13:56:32 +0000 (13:56 +0000)
svn path=/trunk/KDE/kdeedu/kalzium/src/kalziumglwidget.h; revision=551372

kalzium/kalziumglwidget.cpp
kalzium/kalziumglwidget.h

index f5c0f5cb03dddf76550ba6ed0ab3ad0b8e8ca1f9..229674117125e68ab01e0da838dd3da79992def3 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
-    copyright            : (C) 2006 by Carsten Niehaus
+    copyright            : (C) 2006 by Benoit Jacob
     email                : cniehaus@kde.org
  ***************************************************************************/
 
@@ -13,8 +13,9 @@
  ***************************************************************************/
 #include "kalziumglwidget.h"
 
-#include <kdebug.h>
+#include <math.h>
 
+#include <kdebug.h>
 
 #include <QMouseEvent>
 #include <QListWidget>
 
 using namespace OpenBabel;
 
+GLVertexArray::GLVertexArray()
+{
+       m_vertices = 0;
+       m_indices = 0;
+}
+
+GLVertexArray::~GLVertexArray()
+{
+       if( m_vertices ) delete []m_vertices;
+       if( m_indices ) delete []m_indices;
+}
+
+void GLVertexArray::draw()
+{
+       if( ! m_vertices ) return;
+       if( ! m_indices ) return;
+       glInterleavedArrays( GL_N3F_V3F, 0,  m_vertices );
+       glDrawElements( GL_TRIANGLE_STRIP, m_nbIndices, GL_UNSIGNED_SHORT, m_indices );
+}
+
+SphereVertexArray::SphereVertexArray( unsigned int strips,
+       unsigned int lozangesPerStrip ) : GLVertexArray()
+{
+       regenerate( strips, lozangesPerStrip );
+}
+
+SphereVertexArray::~SphereVertexArray()
+{
+}
+
+void SphereVertexArray::regenerate( unsigned int strips,
+       unsigned int lozangesPerStrip )
+{
+       m_strips = strips;
+       m_lozangesPerStrip = lozangesPerStrip;
+       if( m_vertices ) delete []m_vertices;
+       if( m_indices ) delete []m_indices;
+       generate();
+}
+
+void SphereVertexArray::generate()
+{
+
+}
+
 KalziumGLWidget::KalziumGLWidget( QWidget * parent )
        : QGLWidget( parent )
 {
-       sphereDisplayList = 0;
+       m_sphereDisplayList = 0;
+       m_bondDisplayList = 0;
+       m_isDragging = false;
        m_molecule = 0;
-       m_detail = 2;
-       isDragging = false;
+       m_detail = 0;
+       m_atomsRadiusCoeff = 0.0;
        
        setMinimumSize( 100,100 );
 }
 
 KalziumGLWidget::~KalziumGLWidget()
 {
-       if( sphereDisplayList )
-               glDeleteLists( sphereDisplayList, 1 );
+       if( m_sphereDisplayList )
+               glDeleteLists( m_sphereDisplayList, 1 );
 }
 
 void KalziumGLWidget::initializeGL()
 {
-       glClearColor( 0.0, 0.0, 0.0, 1.0);
+       glClearColor( 0.0, 0.0, 0.0, 1.0 );
        glShadeModel( GL_SMOOTH );
        glEnable( GL_DEPTH_TEST );
-       glEnable( GL_CULL_FACE );
-       glEnable( GL_NORMALIZE );
+       glDisable( GL_CULL_FACE );
        glDisable( GL_BLEND );
 
        glMatrixMode( GL_MODELVIEW );
        glPushMatrix();
        glLoadIdentity();
-       glGetDoublev( GL_MODELVIEW_MATRIX, RotationMatrix );
+       glGetDoublev( GL_MODELVIEW_MATRIX, m_RotationMatrix );
        glPopMatrix();
 
        glEnable(GL_LIGHTING);
@@ -63,82 +110,117 @@ void KalziumGLWidget::initializeGL()
        GLfloat ambientLight[] = { 0.4, 0.4, 0.4, 1.0 };
        GLfloat diffuseLight[] = { 0.8, 0.8, 0.8, 1.0 };
        GLfloat specularLight[] = { 1.0, 1.0, 1.0, 1.0 };
-       GLfloat position[] = { 0.6, 0.5, 1.0, 0.0 };
+       GLfloat position[] = { 0.8, 0.7, 1.0, 0.0 };
 
        glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
        glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
        glLightfv(GL_LIGHT0, GL_POSITION, position);
 
-       glEnable(GL_FOG);
+//     glEnable(GL_FOG);
        GLfloat fogColor[] = { 0.0, 0.0, 0.0, 1.0 };
-       glFogfv(GL_FOG_COLOR, fogColor);
-       glFogi(GL_FOG_MODE, GL_LINEAR);
-       glFogf(GL_FOG_DENSITY, 0.4);
-       glFogf(GL_FOG_START, 11.0);
-       glFogf(GL_FOG_END, 17.0);
+       glFogfv( GL_FOG_COLOR, fogColor );
+       glFogi( GL_FOG_MODE, GL_LINEAR );
+       glFogf( GL_FOG_DENSITY, 0.45 );
+       glFogf( GL_FOG_START, 2.7 * m_molRadius );
+       glFogf( GL_FOG_END, 5.0 * m_molRadius );
 
-       glEnable (GL_COLOR_SUM_EXT);
-       glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL_EXT, GL_SEPARATE_SPECULAR_COLOR_EXT);
+       glEnable( GL_COLOR_SUM_EXT );
+       glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT,
+               GL_SEPARATE_SPECULAR_COLOR_EXT );
+}
+
+void KalziumGLWidget::getColor( const OBAtom &a, GLfloat &r, GLfloat &g, GLfloat &b )
+{
+//X    if ( a.IsOxygen() )
+//X    {//red
+//X            r = 1.0;
+//X            g = 0.0;
+//X            b = 0.0;
+//X    }
+//X    else if ( a.IsSulfur() )
+//X    {//yellow
+//X            r = 1.0;
+//X            g = 1.0;
+//X            b = 0.0;
+//X    }
+//X    else if ( a.IsCarbon() )
+//X    {//almost black
+//X            r = 0.25;
+//X            g = 0.25;
+//X            b = 0.25;
+//X    }
+//X    else if ( a.IsNitrogen() )
+//X    {
+//X            r = 1.0;
+//X            g = 0.9;
+//X            b = 0.5;
+//X    }
+//X    else if ( a.IsHydrogen() )
+//X    {//white
+//X            r = 1.0;
+//X            g = 1.0;
+//X            b = 1.0;
+//X    }
+//X    else
+//X    {
+//X            r = 0.5;
+//X            g = 0.5;
+//X            b = 0.5;
+//X    }
 }
 
 void KalziumGLWidget::paintGL()
 {
-       if ( !m_molecule )
+       if( !m_molecule )
                return;
+
+       float bondsRadius = m_molMinBondLength / 8;
+       float atomsRadius = (1 - m_atomsRadiusCoeff) * bondsRadius
+                         + m_atomsRadiusCoeff * m_molMinBondLength / 2;
        
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
        glLoadIdentity();
-       glTranslated( 0.0, 0.0, -12.0);
-       glMultMatrixd( RotationMatrix );
+//X    glTranslate##GLSUFFIX( 0.0, 0.0, -3.0 * m_molRadius);
+//X    glMultMatrix##GLSUFFIX( m_RotationMatrix );
 
+       glEnable( GL_NORMALIZE );
        FOR_ATOMS_OF_MOL( a, m_molecule )
        {
-               GLdouble x = ( GLdouble )a->GetX();
-               GLdouble y = ( GLdouble )a->GetY();
-               GLdouble z = ( GLdouble )a->GetZ();
-
-               double r = 0.5;
-               double g = 0.5;
-               double b = 0.5;
-
-               if ( a->IsOxygen() )
-               {//red
-                       r = 1.0;
-                       g = 0.0;
-                       b = 0.0;
-               }
-               else if ( a->IsSulfur() )
-               {//yellow
-                       r = 1.0;
-                       g = 1.0;
-                       b = 0.0;
-               }
-               else if ( a->IsCarbon() )
-               {//almost black
-                       r = 0.19;
-                       g = 0.19;
-                       b = 0.19;
-               }
-               else if ( a->IsNitrogen() )
-               {
-                       r = 1.0;
-                       g = 0.9;
-                       b = 0.5;
-               }
-               else if ( a->IsHydrogen() )
-               {//white
-                       r = 1.0;
-                       g = 1.0;
-                       b = 1.0;
-               }
+               FLOAT x = ( FLOAT )a->GetX();
+               FLOAT y = ( FLOAT )a->GetY();
+               FLOAT z = ( FLOAT )a->GetZ();
+
+               GLfloat r, g, b;
+
+               getColor( *a, r, g, b );
                
-               double radius = 1.0;
                drawSphere(
                                x, y, z,
-                               radius, 
+                               atomsRadius,
                                r, g, b);
        }
+
+       glDisable( GL_NORMALIZE );
+       FOR_BONDS_OF_MOL( bond, m_molecule )
+       {
+               FLOAT x1 = (FLOAT) static_cast<OBAtom*>(bond->GetBgn())->GetX();
+               FLOAT y1 = (FLOAT) static_cast<OBAtom*>(bond->GetBgn())->GetY();
+               FLOAT z1 = (FLOAT) static_cast<OBAtom*>(bond->GetBgn())->GetZ();
+               FLOAT x2 = (FLOAT) static_cast<OBAtom*>(bond->GetEnd())->GetX();
+               FLOAT y2 = (FLOAT) static_cast<OBAtom*>(bond->GetEnd())->GetY();
+               FLOAT z2 = (FLOAT) static_cast<OBAtom*>(bond->GetEnd())->GetZ();
+               
+               FLOAT x3 = (x1 + x2) / 2;
+               FLOAT y3 = (y1 + y2) / 2;
+               FLOAT z3 = (z1 + z2) / 2;
+               
+               GLfloat r, g, b;
+       //      getColor( *static_cast<OBAtom*>(bond->GetBgn()), r, g, b );
+               drawBond( x1, y1, z1, x3, y3, z3, r, g, b );
+       //      getColor( *static_cast<OBAtom*>(bond->GetEnd()), r, g, b );
+               drawBond( x2, y2, z2, x3, y3, z3, r, g, b );
+       }
 }
 
 void KalziumGLWidget::resizeGL( int width, int height )
@@ -146,40 +228,41 @@ void KalziumGLWidget::resizeGL( int width, int height )
        glViewport( 0, 0, width, height );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
-       gluPerspective( 60.0, float(width) / height, 0.5, 50.0 );
+       gluPerspective( 40.0, float(width) / height, m_molRadius, 5.0 * m_molRadius );
        glMatrixMode( GL_MODELVIEW );
 }
 
 void KalziumGLWidget::mousePressEvent( QMouseEvent * event )
 {
-       if( event->buttons () & Qt::LeftButton )
+       if( event->buttons() & Qt::LeftButton )
        {       
-               isDragging = true;
-               lastDraggingPosition = event->pos ();
+               m_isDragging = true;
+               m_lastDraggingPosition = event->pos ();
        }
 }
 
 void KalziumGLWidget::mouseReleaseEvent( QMouseEvent * event )
 {
-       if( !( event->buttons () & Qt::LeftButton ) )
+       if( !( event->buttons() & Qt::LeftButton ) )
        {
-               isDragging = false;
+               m_isDragging = false;
+               updateGL();
        }
 }
 
 void KalziumGLWidget::mouseMoveEvent( QMouseEvent * event )
 {
-       if( isDragging )
+       if( m_isDragging )
        {
-               deltaDragging = event->pos() - lastDraggingPosition;
-               lastDraggingPosition = event->pos();
+               QPoint deltaDragging = event->pos() - m_lastDraggingPosition;
+               m_lastDraggingPosition = event->pos();
 
                glPushMatrix();
                glLoadIdentity();
                glRotated( deltaDragging.x(), 0.0, 1.0, 0.0 );
                glRotated( deltaDragging.y(), 1.0, 0.0, 0.0 );
-               glMultMatrixd( RotationMatrix );
-               glGetDoublev( GL_MODELVIEW_MATRIX, RotationMatrix );
+               glMultMatrixd( m_RotationMatrix );
+               glGetDoublev( GL_MODELVIEW_MATRIX, m_RotationMatrix );
                glPopMatrix();
                updateGL();
        }
@@ -187,29 +270,86 @@ void KalziumGLWidget::mouseMoveEvent( QMouseEvent * event )
 
 void KalziumGLWidget::drawGenericSphere()
 {
-       if( 0 == sphereDisplayList )
+       static int lastDetail = -1;
+       if( 0 == m_sphereDisplayList || lastDetail != m_detail)
        {
-               sphereDisplayList = glGenLists( 1 );
-               if( 0 == sphereDisplayList ) return;
+               if( m_sphereDisplayList )
+                       glDeleteLists( m_sphereDisplayList, 1 );
+               m_sphereDisplayList = glGenLists( 1 );
+               if( 0 == m_sphereDisplayList ) return;
                GLUquadricObj *q = gluNewQuadric();
                if( 0 == q) return;
-               glNewList( sphereDisplayList, GL_COMPILE );
-               gluSphere( q, 1.0, SPHERE_TESSELATE_SLICES,  SPHERE_TESSELATE_STACKS );
+               glNewList( m_sphereDisplayList, GL_COMPILE );
+               switch( m_detail)
+               {
+                       case 0:
+                               gluSphere( q, 1.0, 10, 10 );
+                               break;
+                       case 1:
+                               gluSphere( q, 1.0, 20, 20 );
+                               break;
+                       case 2:
+                               gluSphere( q, 1.0, 40, 40 );
+                               break;
+               }       
                glEndList();
                gluDeleteQuadric( q );
+               lastDetail = m_detail;
        }
-       else
+       
+       glCallList( m_sphereDisplayList );
+}
+
+void KalziumGLWidget::drawGenericBond()
+{
+       const double pi = 3.1415927;
+       int slices;
+       static int lastDetail = -1;
+       if( 0 == m_bondDisplayList  || lastDetail != m_detail)
        {
-               glCallList( sphereDisplayList );
+               m_bondDisplayList = glGenLists( 1 );
+               if( 0 == m_bondDisplayList ) return;
+               switch( m_detail)
+               {
+                       case 0:
+                               slices = 10;
+                               break;
+                       case 1:
+                               slices = 10;
+                               break;
+                       case 2:
+                               slices = 20;
+                               break;
+               }       
+               glNewList( m_bondDisplayList, GL_COMPILE );
+               glBegin( GL_QUADS );
+               for (double i = 0.0; i < slices; i++)
+               {       
+                       glNormal3f( cos(2*pi * i/slices), sin(2*pi * i/slices), 0.0 );
+                       glVertex3f( cos(2*pi * i/slices) * m_bondsRadius, sin(2*pi * i/slices) * m_bondsRadius, 1.0 );
+                       glNormal3f( cos(2*pi * i/slices), sin(2*pi * i/slices), 0.0 );
+                       glVertex3f( cos(2*pi * i/slices) * m_bondsRadius, sin(2*pi * i/slices) * m_bondsRadius, 0.0 );
+                       glNormal3f( cos(2*pi * (i+1)/slices), sin(2*pi * (i+1)/slices), 0.0 );
+                       glVertex3f( cos(2*pi * (i+1)/slices) * m_bondsRadius, sin(2*pi * (i+1)/slices) * m_bondsRadius, 0.0 );
+                       glNormal3f( cos(2*pi * (i+1)/slices), sin(2*pi * (i+1)/slices), 0.0 );
+                       glVertex3f( cos(2*pi * (i+1)/slices) * m_bondsRadius, sin(2*pi * (i+1)/slices) * m_bondsRadius, 1.0 );
+               }
+               glEnd();
+               glEndList();
+               lastDetail = m_detail;
        }
+       
+       glCallList( m_bondDisplayList );
+
 }
 
-void KalziumGLWidget::drawSphere( GLdouble x, GLdouble y, GLdouble z, GLdouble radius,
-       GLfloat red, GLfloat green, GLfloat blue )
+void KalziumGLWidget::drawSphere( GLdouble x, GLdouble y, GLdouble z,
+       GLdouble radius, GLfloat red, GLfloat green, GLfloat blue )
 {
        GLfloat ambientColor [] = { red / 2, green / 2, blue / 2, 1.0 };
        GLfloat diffuseColor [] = { red, green, blue, 1.0 };
-       GLfloat specularColor [] = { (2.0 + red) / 3, (2.0 + green) / 3, (2.0 + blue) / 3, 1.0 };
+       GLfloat specularColor [] = { (2.0 + red) / 3, (2.0 + green) / 3,
+               (2.0 + blue) / 3, 1.0 };
        glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
        glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
@@ -222,14 +362,188 @@ void KalziumGLWidget::drawSphere( GLdouble x, GLdouble y, GLdouble z, GLdouble r
        glPopMatrix();
 }
 
+void KalziumGLWidget::drawBond( GLdouble x1, GLdouble y1, GLdouble z1,
+       GLdouble x2, GLdouble y2, GLdouble z2,
+       GLfloat red, GLfloat green, GLfloat blue )
+{
+       GLfloat ambientColor [] = { red / 2, green / 2, blue / 2, 1.0 };
+       GLfloat diffuseColor [] = { red, green, blue, 1.0 };
+       GLfloat specularColor [] = { (2.0 + red) / 3, (2.0 + green) / 3,
+               (2.0 + blue) / 3, 1.0 };
+       glMaterialfv(GL_FRONT, GL_AMBIENT, ambientColor);
+       glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuseColor);
+       glMaterialfv(GL_FRONT, GL_SPECULAR, specularColor);
+       glMaterialf(GL_FRONT, GL_SHININESS, 50.0);
+
+       // the "axis vector" of the cylinder
+       GLdouble axis[3] = { x2 - x1, y2 - y1, z2 - z1 };
+       
+       // find two vectors v, w such that (axis,v,w) is an orthogonal basis.
+       GLdouble v[3], w[3];
+       construct_ortho_3D_basis_given_first_vector3( axis, v, w );
+
+       // normalize v and w. We DON'T want to normalize axis
+       normalize3( v );
+       normalize3( w );
+
+       // construct the 4D transformation matrix
+       GLdouble matrix[16];
+
+       // column 1
+       matrix[0] = v[0];
+       matrix[1] = v[1];
+       matrix[2] = v[2];
+       matrix[3] = 0.0;
+
+       // column 2
+       matrix[4] = w[0];
+       matrix[5] = w[1];
+       matrix[6] = w[2];
+       matrix[7] = 0.0;
+
+       // column 3
+       matrix[8] = axis[0];
+       matrix[9] = axis[1];
+       matrix[10] = axis[2];
+       matrix[11] = 0.0;
+
+       // column 4
+       matrix[12] = x1;
+       matrix[13] = y1;
+       matrix[14] = z1;
+       matrix[15] = 1.0;
+
+       //now we can do the actual drawing !
+       glPushMatrix();
+       glMultMatrixd( matrix );
+       drawGenericBond();
+       glPopMatrix();
+}
+
 void KalziumGLWidget::slotSetMolecule( OpenBabel::OBMol* molecule )
 {
        m_molecule = molecule;
+       
+       // translate the molecule so that center has coords 0,0,0
+       m_molecule->Center();
+
+       // calculate the radius of the molecule
+       // that is, the maximal distance between an atom of the molecule
+       // and the center of the molecule
+       m_molRadius = 0.0;
+       FOR_ATOMS_OF_MOL( a, m_molecule )
+       {
+               FLOAT x = (FLOAT) a->GetX();
+               FLOAT y = (FLOAT) a->GetY();
+               FLOAT z = (FLOAT) a->GetZ();
+               FLOAT rad = SQRT(x*x + y*y + z*z);
+               if( rad > m_molRadius )
+                       m_molRadius = rad;
+       }
+
+       // calculate the length of the shortest bond, of the longest bond
+       m_molMinBondLength = 2 * m_molRadius;
+       m_molMaxBondLength = 0.0;
+       FOR_BONDS_OF_MOL( b, m_molecule )
+       {
+               FLOAT x1 = (FLOAT) static_cast<OBAtom*>(b->GetBgn())->GetX();
+               FLOAT y1 = (FLOAT) static_cast<OBAtom*>(b->GetBgn())->GetY();
+               FLOAT z1 = (FLOAT) static_cast<OBAtom*>(b->GetBgn())->GetZ();
+               FLOAT x2 = (FLOAT) static_cast<OBAtom*>(b->GetEnd())->GetX();
+               FLOAT y2 = (FLOAT) static_cast<OBAtom*>(b->GetEnd())->GetY();
+               FLOAT z2 = (FLOAT) static_cast<OBAtom*>(b->GetEnd())->GetZ();
+               FLOAT len = SQRT ( (x1 - x2) * (x1 - x2)
+                                + (y1 - y2) * (y1 - y2)
+                                + (z1 - z2) * (z1 - z2) );
+               if( len > m_molMaxBondLength )
+                       m_molMaxBondLength = len;
+               if( len < m_molMinBondLength )
+                       m_molMinBondLength = len;
+       }
+
+       m_bondsRadius = m_molMinBondLength / 8;
 }
 
 void KalziumGLWidget::slotSetDetail( int detail )
 {
        m_detail = detail;
+       if( 2 <= m_detail ) glEnable( GL_FOG );
+       else glDisable( GL_FOG );
+       updateGL();
+}
+
+bool approx_equal( FLOAT a, FLOAT b )
+{
+       const FLOAT precision = 0.01;
+       FLOAT abs_a = FABS( a );
+       FLOAT abs_b = FABS( b );
+
+       FLOAT max_abs;
+       if( abs_a < abs_b )
+               max_abs = abs_b;
+       else
+               max_abs = abs_a;
+       if( 0.0 == max_abs ) return true;
+       else return( FABS( a - b ) < precision * max_abs );
+}
+
+FLOAT norm3( FLOAT *u )
+{
+       return SQRT( u[0] * u[0] + u[1] * u[1] + u[2] * u[2] );
+}
+
+void normalize3( FLOAT *u )
+{
+       FLOAT n = norm3( u );
+       if( 0 == n ) return;
+       u[0] /= n;
+       u[1] /= n;
+       u[2] /= n;
+}
+
+void construct_ortho_3D_basis_given_first_vector3(
+       const FLOAT *U, FLOAT *v, FLOAT *w)
+{
+       // let us first make a normalized copy of U
+       FLOAT u[3];
+       u[0] = U[0]; u[1] = U[1]; u[2] = U[2];
+       if( 0 == norm3( u ) ) return;
+       normalize3( u );
+
+       // initially we set v = u
+       v[0] = u[0]; v[1] = u[1]; v[2] = u[2];
+
+       // next we want to change v so that it becomes not colinear to u
+       if( ! approx_equal( v[0], v[1] ) )
+       {
+               GLFLOAT tmp = v[0];
+               v[0] = v[1];
+               v[1] = tmp;
+       }
+       else if( ! approx_equal( v[1], v[2] ) )
+       {
+               GLFLOAT tmp = v[2];
+               v[2] = v[1];
+               v[1] = tmp;
+       }
+       else // the 3 coords of v are approximately equal
+       {    // which implies that v is not colinear to (0,0,1)
+               v[0] = 0.0; v[1] = 0.0; v[2] = 1.0;
+       }
+
+       // now, v is not colinear to u. We compute its dot product with u
+       FLOAT u_dot_v = u[0] * v[0] + u[1] * v[1] + u[2] * v[2];
+
+       // now we change v so that it becomes orthogonal to u
+       v[0] -= u[0] * u_dot_v;
+       v[1] -= u[1] * u_dot_v;
+       v[2] -= u[2] * u_dot_v;
+
+       // now that u and v are orthogonal, w can be constructed as
+       // their crossed product
+       w[0] = u[1] * v[2] - u[2] * v[1];
+       w[1] = u[2] * v[0] - u[0] * v[2];
+       w[2] = u[0] * v[1] - u[1] * v[0];
 }
 
 #include "kalziumglwidget.moc"
index d189757a76172f9369795564d816dc4c61eb6228..fc640dd6e226b1a6607b64217ec18091cc598ad4 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef KALZIUMGLWIDGET_H
 #define KALZIUMGLWIDGET_H
 /***************************************************************************
-    copyright            : (C) 2006 by Carsten Niehaus
+    copyright            : (C) 2006 by Benoit Jacob
     email                : cniehaus@kde.org
  ***************************************************************************/
 
  ***************************************************************************/
 
 #include <QGLWidget>
+#include <openbabel/mol.h>
 
-#define SPHERE_TESSELATE_SLICES        30
-#define SPHERE_TESSELATE_STACKS        30
+#define FLOAT  double
 
-#include <openbabel/mol.h>
+#if(FLOAT==double)
+#define GLFLOAT                GLdouble
+#define GLSUFFIX       d
+#define SQRT           sqrt
+#define COS            cos
+#define SIN            sin
+#define FABS           fabs
+#elif(FLOAT==float)
+#define GLFLOAT                GLfloat
+#define GLSUFFIX       f
+#define SQRT           sqrtf
+#define COS            cosf
+#define SIN            sinf
+#define FABS           fabsf
+#endif
+
+/**
+ * @autor Benoit Jacob
+ */
+class GLVertexArray
+{
+       protected:
+               struct Vertex {
+                       float nx, ny, nz;
+                       float vx, vy, vz;
+               };
+
+               Vertex *m_vertices;
+               unsigned short *m_indices;
+               unsigned int m_nbVertices;
+               unsigned int  m_nbIndices;
+               
+               virtual void generate() = 0;
+       public:
+               GLVertexArray();
+               virtual ~GLVertexArray();
+               void draw();
+};
+
+/**
+ * @autor Benoit Jacob
+ */
+class SphereVertexArray : public GLVertexArray
+{
+       protected:
+               unsigned int m_strips, m_lozangesPerStrip;
+               virtual void generate();
+
+       public:
+               SphereVertexArray(unsigned int strips, unsigned int lozangesPerStrip);
+               virtual ~SphereVertexArray();
+
+               virtual void regenerate(unsigned int strips, unsigned int lozangesPerStrip);
+};
 
 /**
  * This class displays the 3D-view of a molecule
  * 
- * @autor Benoit Jacobs
+ * @autor Benoit Jacob
  */
 class KalziumGLWidget : public QGLWidget
 {
        Q_OBJECT
 
        protected:
-               GLuint sphereDisplayList;
-       
-/*             struct VertexArrayEntry {
-                       float nx, ny, nz, vx, vy, vz;
-               };
-*/
-
-               bool isDragging;
-               QPoint lastDraggingPosition;
-               QPoint deltaDragging;
-               GLdouble RotationMatrix[16];
+               GLuint m_sphereDisplayList;
+               GLuint m_bondDisplayList;
+               bool m_isDragging;
+               QPoint m_lastDraggingPosition;
+               GLFLOAT m_RotationMatrix[16];
 
        public:
                /**
@@ -54,6 +101,8 @@ class KalziumGLWidget : public QGLWidget
                 */
                virtual ~KalziumGLWidget();
 
+               void getColor( const OpenBabel::OBAtom &a, GLfloat &r, GLfloat &g, GLfloat &b );
+
        public slots:
                /**
                 * sets the molecule which will be displayed
@@ -82,6 +131,7 @@ class KalziumGLWidget : public QGLWidget
                 * This method...
                 */
                virtual void drawGenericSphere();
+               virtual void drawGenericBond();
                
                /**
                 * This method...
@@ -94,22 +144,56 @@ class KalziumGLWidget : public QGLWidget
                 * @param blue
                 */
                virtual void drawSphere( 
-                               GLdouble x, 
-                               GLdouble y, 
-                               GLdouble z, 
-                               GLdouble radius,
+                               GLFLOAT x, 
+                               GLFLOAT y, 
+                               GLFLOAT z, 
+                               GLFLOAT radius,
                                GLfloat red, 
                                GLfloat green, 
                                GLfloat blue );
 
+               virtual void drawBond( GLFLOAT x1, GLFLOAT y1, GLFLOAT z1,
+                       GLFLOAT x2, GLFLOAT y2, GLFLOAT z2,
+                       GLfloat red, GLfloat green, GLfloat blue );
+
                /**
                 * The molecule which is displayed
                 */
                OpenBabel::OBMol* m_molecule;
+               FLOAT m_molRadius;
+               FLOAT m_molMinBondLength;
+               FLOAT m_molMaxBondLength;
+               FLOAT m_bondsRadius;
 
                /**
                 * The detail-grade from 0 to 2
                 */
                int m_detail;
+
+               /**
+                * The coefficient set by the user, determining the
+                * radius of atoms.
+                * 0.0 -> minimum radius -> "sticks-style" rendering
+                * 1.0 -> maximum radius for which bonds are visible
+                * values larger than 1.0 result in atoms so large
+                * that they completely hide the bonds.
+                */
+               float m_atomsRadiusCoeff;
 };
+
+// tests whether two FLOATs are equal
+bool approx_equal( FLOAT a, FLOAT b );
+
+// compute the norm of a vector (dimension 3)
+FLOAT norm3 ( const FLOAT *u );
+
+// normalize a vector (dimension 3)
+void normalize3( FLOAT *u );
+
+// given a first vector U, construct two new vectors v and w such that
+// (U, v, w) is a direct orthogonal basis (dimension 3).
+// U is not supposed to be normalized, and v and w aren't normalized.
+void construct_ortho_3D_basis_given_first_vector3(
+       const FLOAT *U, FLOAT *v, FLOAT *w);
+
 #endif // KALZIUMGLWIDGET_H