]> Git trees. - libqmvoc.git/commitdiff
Big reorganization in kalziumglhelperclasses
authorBenoît Jacob <jacob.benoit.1@gmail.com>
Mon, 26 Jun 2006 22:01:09 +0000 (22:01 +0000)
committerBenoît Jacob <jacob.benoit.1@gmail.com>
Mon, 26 Jun 2006 22:01:09 +0000 (22:01 +0000)
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

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

index 425cb5bafbb10e7b488312fb9d317135201a0fd8..49f9f7d377c8c14407a16ff4afa74433ea9bc0d7 100644 (file)
 #include <QTime>
 #endif
 
-template<class T> bool GLVector3<T>::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<class T> void GLVector3<T>::construct_ortho_basis_given_first_vector(
-       GLVector3<T> &v, GLVector3<T> &w )
+Color::Color()
 {
-       if( norm() == 0 ) return;
-       
-       // let us first make a normalized copy of *this
-       GLVector3<T> 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<T>( 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<GLfloat *>( 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<GLfloat>[m_vertexCount];
+       m_vertexBuffer = new Vector3<GLfloat>[m_vertexCount];
        if( ! m_vertexBuffer ) return false;
-       m_normalBuffer = new GLVector3<GLfloat>[m_vertexCount];
+       m_normalBuffer = new Vector3<GLfloat>[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<GLfloat> *vertex =
+       Vector3<GLfloat> *vertex =
                &m_vertexBuffer[ indexOfVertex( strip, column, row ) ];
 
-       GLVector3<GLfloat> *normal =
+       Vector3<GLfloat> *normal =
                &m_normalBuffer[ indexOfVertex( strip, column, row ) ];
 
        const GLfloat phi = ( 1 + sqrt(5) ) / 2;
 
-       const GLVector3<GLfloat> northPole( 0, 1, phi );
-       const GLVector3<GLfloat> northVertex[5] = {
-               GLVector3<GLfloat>( 0, -1, phi ),
-               GLVector3<GLfloat>( phi, 0, 1 ),
-               GLVector3<GLfloat>( 1, phi, 0 ),
-               GLVector3<GLfloat>( -1, phi, 0 ),
-               GLVector3<GLfloat>( -phi, 0, 1 ) };
-       const GLVector3<GLfloat> southVertex[5] = {
-               GLVector3<GLfloat>( -1, -phi, 0 ),
-               GLVector3<GLfloat>( 1, -phi, 0 ),
-               GLVector3<GLfloat>( phi, 0, -1 ),
-               GLVector3<GLfloat>( 0, 1, -phi ),
-               GLVector3<GLfloat>( -phi, 0, -1 )
+       const Vector3<GLfloat> northPole( 0, 1, phi );
+       const Vector3<GLfloat> northVertex[5] = {
+               Vector3<GLfloat>( 0, -1, phi ),
+               Vector3<GLfloat>( phi, 0, 1 ),
+               Vector3<GLfloat>( 1, phi, 0 ),
+               Vector3<GLfloat>( -1, phi, 0 ),
+               Vector3<GLfloat>( -phi, 0, 1 ) };
+       const Vector3<GLfloat> southVertex[5] = {
+               Vector3<GLfloat>( -1, -phi, 0 ),
+               Vector3<GLfloat>( 1, -phi, 0 ),
+               Vector3<GLfloat>( phi, 0, -1 ),
+               Vector3<GLfloat>( 0, 1, -phi ),
+               Vector3<GLfloat>( -phi, 0, -1 )
                 };
-       const GLVector3<GLfloat> southPole( 0, -1, -phi );
+       const Vector3<GLfloat> southPole( 0, -1, -phi );
 
-       const GLVector3<GLfloat> *v0, *v1, *v2;
+       const Vector3<GLfloat> *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<GLfloat>::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 );
-}
index 4c475689dca676751645f3460f49b21d9497bca0..56986162a27aa2a16296a22298552728eb42dfe3 100644 (file)
 #include <math.h>
 #include <QGLWidget>
 
-#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 T> 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<T>& operator= ( const GLVector3<T>& 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<GLfloat *>( 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<T> & v, GLVector3<T> & 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<GLfloat> *m_vertexBuffer;
-               GLVector3<GLfloat> *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<class T> 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 T> class Vector3
+       {
+               public:
+                       T x, y, z;
+                       Vector3() {}
+                       Vector3( T _x, T _y, T _z)
+                       { x = _x; y = _y; z = _z; }
+       
+                       Vector3<T>& operator= ( const Vector3<T>& 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<class T> void construct_ortho_basis_given_first_vector(
+               const Vector3<T> &U, Vector3<T> & v, Vector3<T> & 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<T> 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<T>( 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<GLfloat> *m_vertexBuffer;
+                       Vector3<GLfloat> *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
 
index 52ea5d95126b8ad5d28d3c39bea6ccf418d39d1d..c856c6ec6debe6831abaf19cdb96659b837ce4bb 100644 (file)
@@ -17,6 +17,7 @@
 #include <math.h>
 
 #include <kdebug.h>
+#include <klocale.h>
 
 #include <QMouseEvent>
 #include <QListWidget>
@@ -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<OBAtom*>(bond->GetBgn())->GetX();
-               GLFLOAT y1 = (GLFLOAT)
-                       static_cast<OBAtom*>(bond->GetBgn())->GetY();
-               GLFLOAT z1 = (GLFLOAT)
-                       static_cast<OBAtom*>(bond->GetBgn())->GetZ();
-               GLFLOAT x2 = (GLFLOAT)
-                       static_cast<OBAtom*>(bond->GetEnd())->GetX();
-               GLFLOAT y2 = (GLFLOAT)
-                       static_cast<OBAtom*>(bond->GetEnd())->GetY();
-               GLFLOAT z2 = (GLFLOAT)
-                       static_cast<OBAtom*>(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<OBAtom*>(bond->GetBgn()) );
-               c2 = getAtomColor( static_cast<OBAtom*>(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<OBAtom*>(bond->GetBgn())->GetX();
+                       GLFLOAT y1 = (GLFLOAT)
+                               static_cast<OBAtom*>(bond->GetBgn())->GetY();
+                       GLFLOAT z1 = (GLFLOAT)
+                               static_cast<OBAtom*>(bond->GetBgn())->GetZ();
+                       GLFLOAT x2 = (GLFLOAT)
+                               static_cast<OBAtom*>(bond->GetEnd())->GetX();
+                       GLFLOAT y2 = (GLFLOAT)
+                               static_cast<OBAtom*>(bond->GetEnd())->GetY();
+                       GLFLOAT z2 = (GLFLOAT)
+                               static_cast<OBAtom*>(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<OBAtom*>(bond->GetBgn()) );
+                       c2 = getAtomColor( static_cast<OBAtom*>(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<FLOAT> axis( x2 - x1, y2 - y1, z2 - z1 );
+       Vector3<FLOAT> axis( x2 - x1, y2 - y1, z2 - z1 );
        
        // find two vectors v, w such that (axis,v,w) is an orthogonal basis.
-       GLVector3<FLOAT> v, w;
-//     axis.construct_ortho_basis_given_first_vector( v, w );
+       Vector3<FLOAT> 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<OBAtom*>(b->GetEnd())->GetX();
                FLOAT y2 = (FLOAT) static_cast<OBAtom*>(b->GetEnd())->GetY();
                FLOAT z2 = (FLOAT) static_cast<OBAtom*>(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
index a42075519be869195c480d5e95ce58c9f06e55ec..97dd670838cf343270a5801cf6866646ebe6205a 100644 (file)
 
 #include <QGLWidget>
 #include <QList>
+#include <QFont>
 #include <openbabel/mol.h>
 
+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,