From: BenoƮt Jacob Date: Mon, 26 Jun 2006 22:01:09 +0000 (+0000) Subject: Big reorganization in kalziumglhelperclasses X-Git-Tag: v3.80.3~103^2~40 X-Git-Url: https://git.rmz.fi/?a=commitdiff_plain;h=8f94cd97c23adac9b41df5a0bd0b85f1090b7e98;p=libqmvoc.git Big reorganization in kalziumglhelperclasses By the way, maybe we shoud rename these files kalziumglhelpers, because there's not only classes there, but also functions (all within a namespace I called KalziumGLHelpers). Another change is, I removed support for caching with GL display lists. The reason is, it was getting more and more complicated, and it would really have been a pain to handle atoms with different radii. (The main problem is that in principle, GL display lists are incompatible with glVertexPointer). Carsten, I tried to do as you asked, display "Please load a molecule" at KalziumGLWidget startup, but I hit the weirdness of QGLWidget::renderText(), and I had to give up. Googling for that showed me that many people had the same problems, but I couldn't find a solution. I'll ask kde-devel, I think. Benoit M kalzium/src/kalziumglwidget.h M kalzium/src/kalziumglhelperclasses.h M kalzium/src/kalziumglwidget.cpp M kalzium/src/kalziumglhelperclasses.cpp svn path=/trunk/KDE/kdeedu/kalzium/src/kalziumglwidget.h; revision=555287 --- diff --git a/kalzium/kalziumglhelperclasses.cpp b/kalzium/kalziumglhelperclasses.cpp index 425cb5b..49f9f7d 100644 --- a/kalzium/kalziumglhelperclasses.cpp +++ b/kalzium/kalziumglhelperclasses.cpp @@ -17,70 +17,13 @@ #include #endif -template bool GLVector3::approx_equal( - FLOAT a, FLOAT b, FLOAT precision ) -{ - FLOAT abs_a = GLFABS( a ); - FLOAT abs_b = GLFABS( b ); +using namespace KalziumGLHelpers; - FLOAT max_abs; - if( abs_a < abs_b ) - max_abs = abs_b; - else - max_abs = abs_a; - return( GLFABS( a - b ) <= precision * max_abs ); -} - -template void GLVector3::construct_ortho_basis_given_first_vector( - GLVector3 &v, GLVector3 &w ) +Color::Color() { - if( norm() == 0 ) return; - - // let us first make a normalized copy of *this - GLVector3 u = *this; - u.normalize(); - - // first we want to set v to be non-colinear to u - - v = u; - - if( ! approx_equal( v.x, v.y, 0.1 ) ) - { - FLOAT tmp = v.x; - v.x = v.y; - v.y = tmp; - } - else if( ! approx_equal( v.y, v.z, 0.1 ) ) - { - FLOAT tmp = v.z; - v.z = v.y; - v.y = tmp; - } - else // the 3 coords of v are approximately equal - { // which implies that v is not colinear to (0,0,1) - v = GLVector3( 0, 0, 1 ); - } - - // now, v is not colinear to u. We compute its dot product with u - FLOAT u_dot_v = u.x * v.x + u.y * v.y + u.z * v.z; - - // now we change v so that it becomes orthogonal to u - v.x -= u.x * u_dot_v; - v.y -= u.y * u_dot_v; - v.z -= u.z * u_dot_v; - - // now that u and v are orthogonal, w can be constructed as - // their crossed product - w.x = u.y * v.z - u.z * v.y; - w.y = u.z * v.x - u.x * v.z; - w.z = u.x * v.y - u.y * v.x; } -GLColor::GLColor() -{ -} - -GLColor::GLColor( GLfloat red, GLfloat green, GLfloat blue, +Color::Color( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) { m_red = red; @@ -89,7 +32,7 @@ GLColor::GLColor( GLfloat red, GLfloat green, GLfloat blue, m_alpha = alpha; } -GLColor& GLColor::operator=( const GLColor& other ) +Color& Color::operator=( const Color& other ) { m_red = other.m_red; m_green = other.m_green; @@ -99,12 +42,7 @@ GLColor& GLColor::operator=( const GLColor& other ) return *this; } -void GLColor::apply() -{ - glColor4fv( reinterpret_cast( this ) ); -} - -void GLColor::applyAsMaterials() +void Color::applyAsMaterials() { GLfloat ambientColor [] = { m_red / 2, m_green / 2, m_blue / 2, m_alpha }; @@ -118,9 +56,8 @@ void GLColor::applyAsMaterials() glMaterialf(GL_FRONT, GL_SHININESS, 50.0); } -GLVertexArray::GLVertexArray() +VertexArray::VertexArray() { - allocateId(); m_mode = GL_TRIANGLE_STRIP; m_vertexBuffer = 0; m_normalBuffer = 0; @@ -128,42 +65,22 @@ GLVertexArray::GLVertexArray() m_isInitialized = false; } -GLVertexArray::~GLVertexArray() +VertexArray::~VertexArray() { if( m_indexBuffer ) delete [] m_indexBuffer; if( m_vertexBuffer ) delete [] m_vertexBuffer; if( m_normalBuffer ) delete [] m_normalBuffer; } -void GLVertexArray::allocateId() -{ - static int counter = 0; - m_id = counter++; -} - - -void GLVertexArray::select() +void VertexArray::select() { - static int selected_id = -1; - - if( selected_id == m_id ) return; - glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glVertexPointer( 3, GL_FLOAT, 0, m_vertexBuffer ); glNormalPointer( GL_FLOAT, 0, m_normalBuffer ); - selected_id = m_id; -} - -void GLVertexArray::draw() -{ - if( ! m_isInitialized ) return; - select(); - glDrawElements( m_mode, m_indexCount, - GL_UNSIGNED_SHORT, m_indexBuffer ); } -bool GLVertexArray::allocateBuffers() +bool VertexArray::allocateBuffers() { if( m_vertexCount > 65536 ) return false; @@ -185,9 +102,9 @@ bool GLVertexArray::allocateBuffers() m_normalBuffer = 0; } - m_vertexBuffer = new GLVector3[m_vertexCount]; + m_vertexBuffer = new Vector3[m_vertexCount]; if( ! m_vertexBuffer ) return false; - m_normalBuffer = new GLVector3[m_vertexCount]; + m_normalBuffer = new Vector3[m_vertexCount]; if( ! m_normalBuffer ) return false; m_indexBuffer = new unsigned short[m_indexCount]; if( ! m_indexBuffer ) return false; @@ -195,48 +112,48 @@ bool GLVertexArray::allocateBuffers() return true; } -GLSphere::GLSphere() - : GLVertexArray() +Sphere::Sphere() + : VertexArray() { m_detail = 0; m_radius = -1.0; } -unsigned short GLSphere::indexOfVertex( int strip, int column, int row) +unsigned short Sphere::indexOfVertex( int strip, int column, int row) { return ( row + ( 3 * m_detail + 1 ) * ( column + m_detail * strip ) ); } -void GLSphere::computeVertex( int strip, int column, int row) +void Sphere::computeVertex( int strip, int column, int row) { strip %= 5; int next_strip = (strip + 1) % 5; - GLVector3 *vertex = + Vector3 *vertex = &m_vertexBuffer[ indexOfVertex( strip, column, row ) ]; - GLVector3 *normal = + Vector3 *normal = &m_normalBuffer[ indexOfVertex( strip, column, row ) ]; const GLfloat phi = ( 1 + sqrt(5) ) / 2; - const GLVector3 northPole( 0, 1, phi ); - const GLVector3 northVertex[5] = { - GLVector3( 0, -1, phi ), - GLVector3( phi, 0, 1 ), - GLVector3( 1, phi, 0 ), - GLVector3( -1, phi, 0 ), - GLVector3( -phi, 0, 1 ) }; - const GLVector3 southVertex[5] = { - GLVector3( -1, -phi, 0 ), - GLVector3( 1, -phi, 0 ), - GLVector3( phi, 0, -1 ), - GLVector3( 0, 1, -phi ), - GLVector3( -phi, 0, -1 ) + const Vector3 northPole( 0, 1, phi ); + const Vector3 northVertex[5] = { + Vector3( 0, -1, phi ), + Vector3( phi, 0, 1 ), + Vector3( 1, phi, 0 ), + Vector3( -1, phi, 0 ), + Vector3( -phi, 0, 1 ) }; + const Vector3 southVertex[5] = { + Vector3( -1, -phi, 0 ), + Vector3( 1, -phi, 0 ), + Vector3( phi, 0, -1 ), + Vector3( 0, 1, -phi ), + Vector3( -phi, 0, -1 ) }; - const GLVector3 southPole( 0, -1, -phi ); + const Vector3 southPole( 0, -1, -phi ); - const GLVector3 *v0, *v1, *v2; + const Vector3 *v0, *v1, *v2; int c1, c2; if( row >= 2 * m_detail && column == 0 ) @@ -298,7 +215,7 @@ void GLSphere::computeVertex( int strip, int column, int row) } -void GLSphere::initialize() +void Sphere::initialize() { if( m_detail < 1 ) return; m_vertexCount = ( 3 * m_detail + 1 ) * ( 5 * m_detail + 1 ); @@ -341,20 +258,19 @@ void GLSphere::initialize() m_isInitialized = true; } -void GLSphere::setup( int detail, GLfloat radius ) +void Sphere::setup( int detail, GLfloat radius ) { if( detail == m_detail && radius == m_radius ) return; m_detail = detail; m_radius = radius; - allocateId(); initialize(); } -void GLSphere::drawScaled( GLfloat radius ) +void Sphere::drawScaled( GLfloat radius ) { const GLfloat precision = 0.001; - if( GLVector3::approx_equal( radius, m_radius, precision ) ) + if( approx_equal( radius, m_radius, precision ) ) { draw(); return; @@ -369,24 +285,23 @@ void GLSphere::drawScaled( GLfloat radius ) glDisable( GL_NORMALIZE ); } -GLCylinder::GLCylinder() - : GLVertexArray() +Cylinder::Cylinder() + : VertexArray() { m_mode = GL_QUAD_STRIP; m_faces = 0; m_radius = -1.0; } -void GLCylinder::setup( int faces, GLfloat radius ) +void Cylinder::setup( int faces, GLfloat radius ) { if( faces == m_faces && radius == m_radius ) return; m_faces = faces; m_radius = radius; - allocateId(); initialize(); } -void GLCylinder::initialize() +void Cylinder::initialize() { if( m_faces < 3 ) return; @@ -420,10 +335,3 @@ void GLCylinder::initialize() m_isInitialized = true; } - -void GLCylinder::draw() -{ - if ( ! m_isInitialized ) return; - select(); - glDrawArrays( m_mode, 0, m_vertexCount ); -} diff --git a/kalzium/kalziumglhelperclasses.h b/kalzium/kalziumglhelperclasses.h index 4c47568..5698616 100644 --- a/kalzium/kalziumglhelperclasses.h +++ b/kalzium/kalziumglhelperclasses.h @@ -15,198 +15,270 @@ #include #include -#define USE_DOUBLE_PRECISION -#define USE_DISPLAY_LIST -#define USE_FPS_COUNTER - -#ifdef USE_DOUBLE_PRECISION -#define FLOAT double -#define GLFLOAT GLdouble -#else -#define FLOAT float -#define GLFLOAT GLfloat -#endif - -inline float GLSQRT( float x ) { return sqrtf( x ); } -inline double GLSQRT( double x ) { return sqrt( x ); } -inline float GLSIN( float x ) { return sinf( x ); } -inline double GLSIN( double x ) { return sin( x ); } -inline float GLCOS( float x ) { return cosf( x ); } -inline double GLCOS( double x ) { return cos( x ); } -inline float GLFABS( float x ) { return fabsf( x ); } -inline double GLFABS( double x ) { return fabs( x ); } -inline void GLMULTMATRIX( const GLfloat *m ) { glMultMatrixf(m); } -inline void GLMULTMATRIX( const GLdouble *m ) { glMultMatrixd(m); } -inline void GLTRANSLATE( GLfloat x, GLfloat y, GLfloat z ) \ - { glTranslatef( x, y, z ); } -inline void GLTRANSLATE( GLdouble x, GLdouble y, GLdouble z ) \ - { glTranslated( x, y, z ); } - -/** - * This class represents a color in OpenGL float red-green-blue format. - * - * @author Benoit Jacob +/** USE_DOUBLE_PRECISION: if defined, use doubles instead of floats for + * handling the model's geometric data. This does not seem to impact + * significantly the performance. The vertex arrays are unaffected: they + * always use floats. */ -struct GLColor -{ - GLfloat m_red, m_green, m_blue, m_alpha; - - GLColor(); - GLColor( GLfloat red, GLfloat green, GLfloat blue, - GLfloat alpha = 1.0 ); - GLColor& operator=( const GLColor& other ); - - /** - * Sets this color to be the one used by OpenGL for rendering - * when lighting is disabled. It just calls glColor4fv. - */ - //TODO inline? - void apply(); - - /** - * Applies nice OpenGL materials using this color as the - * diffuse color while using different shades for the ambient and - * specular colors. This is only useful if GL lighting is enabled. - */ - void applyAsMaterials(); -}; +#define USE_DOUBLE_PRECISION -/** - * This template class represents a vector in 3-space. It is meant to be - * used with T = a floating-point type. - * - * @author Benoit Jacob +/** USE_FPS_COUNTER: if defined, the GL Widgets will show a frames-per-second + * counter. *Use only for testing*: this makes the GL Widget constantly + * redraw, which under normal circumstances is a waste of CPU power. */ +#define USE_FPS_COUNTER -template class GLVector3 +namespace KalziumGLHelpers { - public: - T x, y, z; - GLVector3() {} - GLVector3( T _x, T _y, T _z) - { x = _x; y = _y; z = _z; } - - /** - * Tests whether two FLOATs are approximately equal. - * Recall that operator == between floating-point types - * is broken. - * returns true if abs( a - b ) <= c * precision - * where c = max( abs( a ), abs( b ) ) - */ - static bool approx_equal( FLOAT a, FLOAT b, FLOAT precision ); - - GLVector3& operator= ( const GLVector3& other ) - { - x = other.x; - y = other.y; - z = other.z; - return *this; - } - - /** - * returns the norm of the vector, that is, its length - */ - inline T norm() { return GLSQRT( x * x + y * y + z * z ); } + #ifdef USE_DOUBLE_PRECISION + typedef double FLOAT; + typedef GLdouble GLFLOAT; + #else + typedef float FLOAT; + typedef GLfloat GLFLOAT; + #endif + inline float SQRT( float x ) { return sqrtf( x ); } + inline double SQRT( double x ) { return sqrt( x ); } + inline float SIN( float x ) { return sinf( x ); } + inline double SIN( double x ) { return sin( x ); } + inline float COS( float x ) { return cosf( x ); } + inline double COS( double x ) { return cos( x ); } + inline float FABS( float x ) { return fabsf( x ); } + inline double FABS( double x ) { return fabs( x ); } + inline void GLMULTMATRIX( const GLfloat *m ) { glMultMatrixf(m); } + inline void GLMULTMATRIX( const GLdouble *m ) { glMultMatrixd(m); } + inline void GLTRANSLATE( GLfloat x, GLfloat y, GLfloat z ) \ + { glTranslatef( x, y, z ); } + inline void GLTRANSLATE( GLdouble x, GLdouble y, GLdouble z ) \ + { glTranslated( x, y, z ); } + + /** + * This class represents a color in OpenGL float red-green-blue format. + * + * @author Benoit Jacob + */ + struct Color + { + GLfloat m_red, m_green, m_blue, m_alpha; + + Color(); + Color( GLfloat red, GLfloat green, GLfloat blue, + GLfloat alpha = 1.0 ); + + Color& operator=( const Color& other ); + /** - * normalizes the vector, that is, scales it so that its norm - * becomes 1. - */ - void normalize() + * Sets this color to be the one used by OpenGL for rendering + * when lighting is disabled. + */ + inline void apply() { - T n = norm(); - if( n == 0.0 ) return; - x /= n; - y /= n; - z /= n; + glColor4fv( reinterpret_cast( this ) ); } - + /** - * Constructs two vectors v and w - * such that (*this, v, w) is a direct orthogonal basis. - * v and w are not getting normalized. - */ - void construct_ortho_basis_given_first_vector( - GLVector3 & v, GLVector3 & w ); -}; - -/** - * This is an abstract base class for an OpenGL vertex array. - * - * @author Benoit Jacob - */ -class GLVertexArray -{ - private: - int m_id; - - protected: - GLenum m_mode; - GLVector3 *m_vertexBuffer; - GLVector3 *m_normalBuffer; - unsigned int m_vertexCount; - unsigned short *m_indexBuffer; - unsigned int m_indexCount; - - bool m_isInitialized; - - virtual void initialize() = 0; - virtual bool allocateBuffers(); - virtual void allocateId(); - virtual void select(); - - public: - GLVertexArray(); - virtual ~GLVertexArray(); - //inline? - virtual void draw(); -}; - -/** - * This class represents and draws a sphere - * - * @author Benoit Jacob - */ -class GLSphere : public GLVertexArray -{ - private: - inline unsigned short indexOfVertex( - int strip, int column, int row); - void computeVertex( int strip, int column, int row ); - - protected: - int m_detail; - GLfloat m_radius; + * Applies nice OpenGL materials using this color as the + * diffuse color while using different shades for the ambient and + * specular colors. This is only useful if lighting is enabled. + */ + void applyAsMaterials(); + }; + + /** + * Tests whether two Ts are approximately equal. Here T is assumed to be + * a floating-point type. Recall that operator== between floating-point + * types is broken. + * returns true if abs( a - b ) <= c * precision + * where c = max( abs( a ), abs( b ) ) + */ + template static bool approx_equal( T a, T b, T precision ) + { + T abs_a = FABS( a ); + T abs_b = FABS( b ); + + T max_abs; + if( abs_a <= abs_b ) + max_abs = abs_b; + else + max_abs = abs_a; + return( FABS( a - b ) <= precision * max_abs ); + } - virtual void initialize(); + /** + * This template class represents a vector in 3-space. It is meant to be + * used with T = a floating-point type. + * + * @author Benoit Jacob + */ + + template class Vector3 + { + public: + T x, y, z; + Vector3() {} + Vector3( T _x, T _y, T _z) + { x = _x; y = _y; z = _z; } + + Vector3& operator= ( const Vector3& other ) + { + x = other.x; + y = other.y; + z = other.z; + return *this; + } + + /** + * returns the norm of the vector, that is, its length + */ + inline T norm() const { return SQRT( x * x + y * y + z * z ); } + + /** + * normalizes the vector, that is, scales it so that its norm + * becomes 1. + */ + void normalize() + { + T n = norm(); + if( n == 0.0 ) return; + x /= n; + y /= n; + z /= n; + } + }; - public: - GLSphere(); - virtual ~GLSphere() {} - virtual void setup( int detail, GLfloat radius ); - virtual void drawScaled( GLfloat radius ); -}; + /** + * Given a vector U, constructs two vectors v and w + * such that (U, v, w) is a direct orthogonal basis. + * U is not supposed to be normalized. + * v and w are not getting normalized. + */ + template void construct_ortho_basis_given_first_vector( + const Vector3 &U, Vector3 & v, Vector3 & w ) + { + if( U.norm() == 0 ) return; -/** - * This class represents and draws a cylinder - * - * @author Benoit Jacob - */ -class GLCylinder : public GLVertexArray -{ - protected: - int m_faces; - GLfloat m_radius; + // let us first make a normalized copy of U + Vector3 u = U; + u.normalize(); + + // first we want to set v to be non-colinear to u + v = u; + + if( ! approx_equal( v.x, v.y, 0.1 ) ) + { + T tmp = v.x; + v.x = v.y; + v.y = tmp; + } + else if( ! approx_equal( v.y, v.z, 0.1 ) ) + { + T tmp = v.z; + v.z = v.y; + v.y = tmp; + } + else // the 3 coords of v are approximately equal + { // which implies that v is not colinear to (0,0,1) + v = Vector3( 0, 0, 1 ); + } + + // now, v is not colinear to u. We compute its dot product with u + T u_dot_v = u.x * v.x + u.y * v.y + u.z * v.z; + + // now we change v so that it becomes orthogonal to u + v.x -= u.x * u_dot_v; + v.y -= u.y * u_dot_v; + v.z -= u.z * u_dot_v; + + // now that u and v are orthogonal, w can be constructed as + // their crossed product + w.x = u.y * v.z - u.z * v.y; + w.y = u.z * v.x - u.x * v.z; + w.z = u.x * v.y - u.y * v.x; + } - virtual void initialize(); + /** + * This is an abstract base class for an OpenGL vertex array. + * + * @author Benoit Jacob + */ + class VertexArray + { + + protected: + GLenum m_mode; + Vector3 *m_vertexBuffer; + Vector3 *m_normalBuffer; + unsigned int m_vertexCount; + unsigned short *m_indexBuffer; + unsigned int m_indexCount; + + bool m_isInitialized; + + virtual void initialize() = 0; + virtual bool allocateBuffers(); + + public: + VertexArray(); + virtual ~VertexArray(); + virtual void select(); + virtual inline void draw() + { + glDrawElements( m_mode, m_indexCount, + GL_UNSIGNED_SHORT, m_indexBuffer ); + } + }; + + /** + * This class represents and draws a sphere + * + * @author Benoit Jacob + */ + class Sphere : public VertexArray + { + private: + inline unsigned short indexOfVertex( + int strip, int column, int row); + void computeVertex( int strip, int column, int row ); + + protected: + int m_detail; + GLfloat m_radius; + + virtual void initialize(); + + public: + Sphere(); + virtual ~Sphere() {} + virtual void setup( int detail, GLfloat radius ); + virtual void drawScaled( GLfloat radius ); + }; + + /** + * This class represents and draws a cylinder + * + * @author Benoit Jacob + */ + class Cylinder : public VertexArray + { + protected: + int m_faces; + GLfloat m_radius; + + virtual void initialize(); + + public: + Cylinder(); + virtual ~Cylinder() {} + virtual void setup( int detail, GLfloat radius ); + virtual inline void draw() + { + glDrawArrays( m_mode, 0, m_vertexCount ); + } + }; - public: - GLCylinder(); - virtual ~GLCylinder() {} - virtual void setup( int detail, GLfloat radius ); - virtual inline void draw(); -}; +} // namespace KalziumGL #endif // KALZIUMGLHELPERCLASSES_H diff --git a/kalzium/kalziumglwidget.cpp b/kalzium/kalziumglwidget.cpp index 52ea5d9..c856c6e 100644 --- a/kalzium/kalziumglwidget.cpp +++ b/kalzium/kalziumglwidget.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -33,7 +34,6 @@ using namespace OpenBabel; KalziumGLWidget::KalziumGLWidget( QWidget * parent ) : QGLWidget( parent ) { - m_displayList = 0; m_isDragging = false; m_molecule = 0; m_detail = 0; @@ -49,14 +49,6 @@ KalziumGLWidget::~KalziumGLWidget() { } -void KalziumGLWidget::deleteDisplayList() -{ -#ifdef USE_DISPLAY_LIST - if( m_displayList) glDeleteLists( m_displayList, 1 ); - m_displayList = 0; -#endif -} - void KalziumGLWidget::initializeGL() { glClearColor( 0.0, 0.0, 0.0, 1.0 ); @@ -105,14 +97,16 @@ void KalziumGLWidget::initializeGL() void KalziumGLWidget::paintGL() { + if( ! m_molecule ) + { + return; + } + glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 40.0, float( width() ) / height(), m_molRadius, 5.0 * (m_molRadius + atomRadius ())); glMatrixMode( GL_MODELVIEW ); - if( !m_molecule ) - return; - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // set up the camera @@ -133,30 +127,32 @@ void KalziumGLWidget::paintGL() } else glDisable( GL_FOG ); -#ifdef USE_DISPLAY_LIST - if ( ! m_displayList ) - { - m_displayList = glGenLists( 1 ); - glNewList( m_displayList, GL_COMPILE ); -#endif - - // render the atoms + // prepare for rendering the spheres if( m_atomStyle == ATOM_SPHERE ) { + m_sphere.select(); glEnable( GL_LIGHTING ); + } + else glDisable( GL_LIGHTING ); - FOR_ATOMS_OF_MOL( a, m_molecule ) + if( m_atomStyle != ATOM_DISABLED ) + { + // render the atoms + if( m_atomStyle == ATOM_SPHERE ) { - GLFLOAT x = (GLFLOAT) a->GetX(); - GLFLOAT y = (GLFLOAT) a->GetY(); - GLFLOAT z = (GLFLOAT) a->GetZ(); - - GLColor c = getAtomColor( &*a ); - - drawSphere( - x, y, z, - atomRadius(), - c); + FOR_ATOMS_OF_MOL( a, m_molecule ) + { + GLFLOAT x = (GLFLOAT) a->GetX(); + GLFLOAT y = (GLFLOAT) a->GetY(); + GLFLOAT z = (GLFLOAT) a->GetZ(); + + Color c = getAtomColor( &*a ); + + drawSphere( + x, y, z, + atomRadius(), + c); + } } } @@ -169,69 +165,66 @@ void KalziumGLWidget::paintGL() case BOND_CYLINDER_GRAY: case BOND_CYLINDER_BICOLOR: + m_cylinder.select(); glEnable( GL_LIGHTING ); break; case BOND_DISABLED: break; } - // render the bonds - if( BOND_DISABLED != m_bondStyle) FOR_BONDS_OF_MOL( bond, m_molecule ) + if( m_bondStyle != BOND_DISABLED ) { - GLFLOAT x1 = (GLFLOAT) - static_cast(bond->GetBgn())->GetX(); - GLFLOAT y1 = (GLFLOAT) - static_cast(bond->GetBgn())->GetY(); - GLFLOAT z1 = (GLFLOAT) - static_cast(bond->GetBgn())->GetZ(); - GLFLOAT x2 = (GLFLOAT) - static_cast(bond->GetEnd())->GetX(); - GLFLOAT y2 = (GLFLOAT) - static_cast(bond->GetEnd())->GetY(); - GLFLOAT z2 = (GLFLOAT) - static_cast(bond->GetEnd())->GetZ(); - - GLFLOAT x3 = (x1 + x2) / 2; - GLFLOAT y3 = (y1 + y2) / 2; - GLFLOAT z3 = (z1 + z2) / 2; - - GLColor c1, c2; - c1 = getAtomColor( static_cast(bond->GetBgn()) ); - c2 = getAtomColor( static_cast(bond->GetEnd()) ); - GLColor gray( 0.5, 0.5, 0.5 ); - - switch( m_bondStyle ) + // render the bonds + FOR_BONDS_OF_MOL( bond, m_molecule ) { - case BOND_LINE: - glBegin( GL_LINES ); - c1.apply(); - glVertex3f( x1, y1, z1 ); - glVertex3f( x3, y3, z3 ); - c2.apply(); - glVertex3f( x3, y3, z3 ); - glVertex3f( x2, y2, z2 ); - glEnd(); - break; + GLFLOAT x1 = (GLFLOAT) + static_cast(bond->GetBgn())->GetX(); + GLFLOAT y1 = (GLFLOAT) + static_cast(bond->GetBgn())->GetY(); + GLFLOAT z1 = (GLFLOAT) + static_cast(bond->GetBgn())->GetZ(); + GLFLOAT x2 = (GLFLOAT) + static_cast(bond->GetEnd())->GetX(); + GLFLOAT y2 = (GLFLOAT) + static_cast(bond->GetEnd())->GetY(); + GLFLOAT z2 = (GLFLOAT) + static_cast(bond->GetEnd())->GetZ(); - case BOND_CYLINDER_GRAY: - drawBond( x1, y1, z1, x2, y2, z2, gray ); - break; - - case BOND_CYLINDER_BICOLOR: - drawBond( x1, y1, z1, x3, y3, z3, c1 ); - drawBond( x2, y2, z2, x3, y3, z3, c2 ); - break; - - case BOND_DISABLED: break; + GLFLOAT x3 = (x1 + x2) / 2; + GLFLOAT y3 = (y1 + y2) / 2; + GLFLOAT z3 = (z1 + z2) / 2; + + Color c1, c2; + c1 = getAtomColor( static_cast(bond->GetBgn()) ); + c2 = getAtomColor( static_cast(bond->GetEnd()) ); + Color gray( 0.5, 0.5, 0.5 ); + + switch( m_bondStyle ) + { + case BOND_LINE: + glBegin( GL_LINES ); + c1.apply(); + glVertex3f( x1, y1, z1 ); + glVertex3f( x3, y3, z3 ); + c2.apply(); + glVertex3f( x3, y3, z3 ); + glVertex3f( x2, y2, z2 ); + glEnd(); + break; + + case BOND_CYLINDER_GRAY: + drawBond( x1, y1, z1, x2, y2, z2, gray ); + break; + + case BOND_CYLINDER_BICOLOR: + drawBond( x1, y1, z1, x3, y3, z3, c1 ); + drawBond( x2, y2, z2, x3, y3, z3, c2 ); + break; + + case BOND_DISABLED: break; + } } } -#ifdef USE_DISPLAY_LIST - glEndList(); - } - - glCallList( m_displayList ); -#endif - // now, paint a semitransparent sphere around the selected atom if( m_selectedAtom ) @@ -240,7 +233,7 @@ void KalziumGLWidget::paintGL() GLFLOAT y = (GLFLOAT) m_selectedAtom->GetY(); GLFLOAT z = (GLFLOAT) m_selectedAtom->GetZ(); - GLColor c( 0.4, 0.4, 1.0, 0.7 ); + Color c( 0.4, 0.4, 1.0, 0.7 ); GLFLOAT radius = m_molMinBondLength * 0.35; GLFLOAT min_radius = (GLFLOAT) atomRadius () * 1.25; @@ -287,7 +280,9 @@ void KalziumGLWidget::paintGL() old_time = new_time; } - renderText ( 20, 20, s ); + glDisable( GL_LIGHTING ); + glColor3f( 1.0, 1.0, 0.0 ); + renderText ( 20, height() - 20, s ); update(); #endif @@ -352,12 +347,10 @@ void KalziumGLWidget::setupObjects() m_sphere.setup( sphere_detail, atomRadius() ); m_cylinder.setup( cylinder_faces, bondRadius() ); - - deleteDisplayList(); } void KalziumGLWidget::drawSphere( GLdouble x, GLdouble y, GLdouble z, - GLfloat radius, GLColor &color ) + GLfloat radius, Color &color ) { color.applyAsMaterials(); @@ -368,16 +361,16 @@ void KalziumGLWidget::drawSphere( GLdouble x, GLdouble y, GLdouble z, } void KalziumGLWidget::drawBond( FLOAT x1, FLOAT y1, FLOAT z1, - FLOAT x2, FLOAT y2, FLOAT z2, GLColor &color ) + FLOAT x2, FLOAT y2, FLOAT z2, Color &color ) { color.applyAsMaterials(); // the "axis vector" of the cylinder - GLVector3 axis( x2 - x1, y2 - y1, z2 - z1 ); + Vector3 axis( x2 - x1, y2 - y1, z2 - z1 ); // find two vectors v, w such that (axis,v,w) is an orthogonal basis. - GLVector3 v, w; -// axis.construct_ortho_basis_given_first_vector( v, w ); + Vector3 v, w; + construct_ortho_basis_given_first_vector( axis, v, w ); // normalize v and w. We DON'T want to normalize axis v.normalize(); @@ -495,7 +488,7 @@ void KalziumGLWidget::prepareMoleculeData() FLOAT x = (FLOAT) a->GetX(); FLOAT y = (FLOAT) a->GetY(); FLOAT z = (FLOAT) a->GetZ(); - FLOAT rad = GLSQRT(x*x + y*y + z*z); + FLOAT rad = SQRT(x*x + y*y + z*z); if( rad > m_molRadius ) m_molRadius = rad; } @@ -511,7 +504,7 @@ void KalziumGLWidget::prepareMoleculeData() 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 = GLSQRT ( (x1 - x2) * (x1 - x2) + FLOAT len = SQRT ( (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2) ); if( len > m_molMaxBondLength ) @@ -530,9 +523,9 @@ void KalziumGLWidget::slotSetDetail( int detail ) updateGL(); } -GLColor& KalziumGLWidget::getAtomColor( OpenBabel::OBAtom* atom ) +Color& KalziumGLWidget::getAtomColor( OpenBabel::OBAtom* atom ) { - static GLColor c; + static Color c; if ( atom->IsHydrogen() ) {//white diff --git a/kalzium/kalziumglwidget.h b/kalzium/kalziumglwidget.h index a420755..97dd670 100644 --- a/kalzium/kalziumglwidget.h +++ b/kalzium/kalziumglwidget.h @@ -17,8 +17,11 @@ #include #include +#include #include +using namespace KalziumGLHelpers; + /** * This class displays the 3D-view of a molecule * @@ -29,19 +32,15 @@ class KalziumGLWidget : public QGLWidget Q_OBJECT protected: - - GLuint m_displayList; - void deleteDisplayList(); - /** * The geometric model of the sphere (used for atoms). */ - GLSphere m_sphere; + Sphere m_sphere; /** * The geometric model of the cylinder (used for bonds). */ - GLCylinder m_cylinder; + Cylinder m_cylinder; /** * equals true if the user is currently dragging (rotating) @@ -220,7 +219,7 @@ class KalziumGLWidget : public QGLWidget GLFLOAT y, GLFLOAT z, GLfloat radius, - GLColor &color ); + Color &color ); /** * This method draws a bond @@ -234,7 +233,7 @@ class KalziumGLWidget : public QGLWidget */ virtual void drawBond( GLFLOAT x1, GLFLOAT y1, GLFLOAT z1, GLFLOAT x2, GLFLOAT y2, GLFLOAT z2, - GLColor &color ); + Color &color ); /** * returns the radius ( = half-thickness ) with which the @@ -259,7 +258,7 @@ class KalziumGLWidget : public QGLWidget /** * returns the color which a given atom should be painted */ - GLColor& getAtomColor( OpenBabel::OBAtom* atom ); + Color& getAtomColor( OpenBabel::OBAtom* atom ); /** * recomputes the geometry of the geometric objects ( sphere,