From de66462ad12c76feb993df3f561d8e42c795b0cc Mon Sep 17 00:00:00 2001 From: Carsten Niehaus Date: Wed, 14 Jun 2006 13:56:32 +0000 Subject: [PATCH] * Many OpenGL-Improvements svn path=/trunk/KDE/kdeedu/kalzium/src/kalziumglwidget.h; revision=551372 --- kalzium/kalziumglwidget.cpp | 482 +++++++++++++++++++++++++++++------- kalzium/kalziumglwidget.h | 124 ++++++++-- 2 files changed, 502 insertions(+), 104 deletions(-) diff --git a/kalzium/kalziumglwidget.cpp b/kalzium/kalziumglwidget.cpp index f5c0f5c..2296741 100644 --- a/kalzium/kalziumglwidget.cpp +++ b/kalzium/kalziumglwidget.cpp @@ -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 +#include +#include #include #include @@ -25,36 +26,82 @@ 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(bond->GetBgn())->GetX(); + FLOAT y1 = (FLOAT) static_cast(bond->GetBgn())->GetY(); + FLOAT z1 = (FLOAT) static_cast(bond->GetBgn())->GetZ(); + FLOAT x2 = (FLOAT) static_cast(bond->GetEnd())->GetX(); + FLOAT y2 = (FLOAT) static_cast(bond->GetEnd())->GetY(); + FLOAT z2 = (FLOAT) static_cast(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(bond->GetBgn()), r, g, b ); + drawBond( x1, y1, z1, x3, y3, z3, r, g, b ); + // getColor( *static_cast(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(b->GetBgn())->GetX(); + FLOAT y1 = (FLOAT) static_cast(b->GetBgn())->GetY(); + FLOAT z1 = (FLOAT) static_cast(b->GetBgn())->GetZ(); + FLOAT x2 = (FLOAT) static_cast(b->GetEnd())->GetX(); + FLOAT y2 = (FLOAT) static_cast(b->GetEnd())->GetY(); + FLOAT z2 = (FLOAT) static_cast(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" diff --git a/kalzium/kalziumglwidget.h b/kalzium/kalziumglwidget.h index d189757..fc640dd 100644 --- a/kalzium/kalziumglwidget.h +++ b/kalzium/kalziumglwidget.h @@ -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 ***************************************************************************/ @@ -15,33 +15,80 @@ ***************************************************************************/ #include +#include -#define SPHERE_TESSELATE_SLICES 30 -#define SPHERE_TESSELATE_STACKS 30 +#define FLOAT double -#include +#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 -- 2.47.3