]> Git trees. - libqmvoc.git/commitdiff
Benoit, kalziumglwidget.h/cpp grew just to big, that is why I
authorCarsten Niehaus <cniehaus@gmx.de>
Mon, 26 Jun 2006 13:47:58 +0000 (13:47 +0000)
committerCarsten Niehaus <cniehaus@gmx.de>
Mon, 26 Jun 2006 13:47:58 +0000 (13:47 +0000)
moved the code into kalziumglhelperclasses.h/cpp, onle the GLWidget
itself stays in src/kalziumglwidget.cpp.

But for some cpp-magic-reasons I needed to remove two inline-calls,
don't ask me why. Furhtermore,
template<class T> void GLVector3<T>::construct_ortho_basis_given_first_vector
is not longer found when linking, not the slightest idea why... The
other methods of GLVector are found when linking...

CCMAIL:jacob@math.jussieu.fr

svn path=/trunk/KDE/kdeedu/kalzium/src/kalziumglwidget.h; revision=555148

kalzium/kalziumglhelperclasses.cpp [new file with mode: 0644]
kalzium/kalziumglhelperclasses.h [new file with mode: 0644]
kalzium/kalziumglwidget.cpp
kalzium/kalziumglwidget.h
kalzium/widgets/CMakeLists.txt

diff --git a/kalzium/kalziumglhelperclasses.cpp b/kalzium/kalziumglhelperclasses.cpp
new file mode 100644 (file)
index 0000000..425cb5b
--- /dev/null
@@ -0,0 +1,429 @@
+/***************************************************************************
+    copyright            : (C) 2006 by Benoit Jacob
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+#include "kalziumglhelperclasses.h"
+#include <math.h>
+
+#ifdef USE_FPS_COUNTER
+#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 );
+
+       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 )
+{
+       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,
+                  GLfloat alpha )
+{
+       m_red = red;
+       m_green = green;
+       m_blue = blue;
+       m_alpha = alpha;
+}
+
+GLColor& GLColor::operator=( const GLColor& other )
+{
+       m_red = other.m_red;
+       m_green = other.m_green;
+       m_blue = other.m_blue;
+       m_alpha = other.m_alpha;
+
+       return *this;
+}
+
+void GLColor::apply()
+{
+       glColor4fv( reinterpret_cast<GLfloat *>( this ) );
+}
+
+void GLColor::applyAsMaterials()
+{
+       GLfloat ambientColor [] = { m_red / 2, m_green / 2, m_blue / 2,
+                                   m_alpha };
+       GLfloat diffuseColor [] = { m_red, m_green, m_blue, m_alpha };
+       GLfloat specularColor [] = { (2.0 + m_red) / 3, (2.0 + m_green) / 3,
+               (2.0 + m_blue) / 3, m_alpha };
+
+       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);
+}
+
+GLVertexArray::GLVertexArray()
+{
+       allocateId();
+       m_mode = GL_TRIANGLE_STRIP;
+       m_vertexBuffer = 0;
+       m_normalBuffer = 0;
+       m_indexBuffer = 0;
+       m_isInitialized = false;
+}
+
+GLVertexArray::~GLVertexArray()
+{
+       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()
+{
+       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()
+{
+       if( m_vertexCount > 65536 ) return false;
+
+       m_isInitialized = false;
+
+       if( m_indexBuffer )
+       {
+               delete [] m_indexBuffer;
+               m_indexBuffer = 0;
+       }
+       if( m_vertexBuffer )
+       {
+               delete [] m_vertexBuffer;
+               m_vertexBuffer = 0;
+       }
+       if( m_normalBuffer ) 
+       {
+               delete [] m_normalBuffer;
+               m_normalBuffer = 0;
+       }
+
+       m_vertexBuffer = new GLVector3<GLfloat>[m_vertexCount];
+       if( ! m_vertexBuffer ) return false;
+       m_normalBuffer = new GLVector3<GLfloat>[m_vertexCount];
+       if( ! m_normalBuffer ) return false;
+       m_indexBuffer = new unsigned short[m_indexCount];
+       if( ! m_indexBuffer ) return false;
+
+       return true;
+}
+
+GLSphere::GLSphere()
+       : GLVertexArray()
+{
+       m_detail = 0;
+       m_radius = -1.0;
+}
+
+unsigned short GLSphere::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)
+{
+       strip %= 5;
+       int next_strip = (strip + 1) % 5;
+
+       GLVector3<GLfloat> *vertex =
+               &m_vertexBuffer[ indexOfVertex( strip, column, row ) ];
+
+       GLVector3<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 GLVector3<GLfloat> southPole( 0, -1, -phi );
+
+       const GLVector3<GLfloat> *v0, *v1, *v2;
+       int  c1, c2;
+
+       if( row >= 2 * m_detail && column == 0 )
+       {
+               strip--;
+               if( strip < 0 ) strip += 5;
+               next_strip--;
+               if( next_strip < 0 ) next_strip += 5;
+               column = m_detail;
+       }
+
+       if( row  <= m_detail )
+       {
+               v0 = &northVertex[strip];
+               v1 = &northPole;
+               v2 = &northVertex[next_strip];
+               c1 = m_detail - row;
+               c2 = column;
+       }
+       else if( row >= 2 * m_detail )
+       {
+               v0 = &southVertex[next_strip];
+               v1 = &southPole;
+               v2 = &southVertex[strip];
+               c1 = row - 2 * m_detail;
+               c2 = m_detail - column;
+       }
+       else if( row <= m_detail + column )
+       {
+               v0 = &northVertex[next_strip];
+               v1 = &southVertex[next_strip];
+               v2 = &northVertex[strip];
+               c1 = row - m_detail;
+               c2 = m_detail - column;
+       }
+       else
+       {
+               v0 = &southVertex[strip];
+               v1 = &southVertex[next_strip];
+               v2 = &northVertex[strip];
+               c1 = column;
+               c2 = 2 * m_detail - row;
+       }
+
+       GLfloat u1 = GLfloat(c1) / m_detail;
+       GLfloat u2 = GLfloat(c2) / m_detail;
+
+       vertex->x = v0->x + u1 * (v1->x - v0->x) + u2 * (v2->x - v0->x);
+       vertex->y = v0->y + u1 * (v1->y - v0->y) + u2 * (v2->y - v0->y);
+       vertex->z = v0->z + u1 * (v1->z - v0->z) + u2 * (v2->z - v0->z);
+
+       vertex->normalize();
+
+       *normal = *vertex;
+
+       vertex->x *= m_radius;
+       vertex->y *= m_radius;
+       vertex->z *= m_radius;
+}
+
+
+void GLSphere::initialize()
+{
+       if( m_detail < 1 ) return;
+       m_vertexCount = ( 3 * m_detail + 1 ) * ( 5 * m_detail + 1 );
+       m_indexCount = (2 * ( 2 * m_detail + 1 ) + 2 ) * 5 * m_detail;
+
+       if( ! allocateBuffers() ) return;
+
+       for( int strip = 0; strip < 5; strip++ )
+       for( int column = 1; column < m_detail; column++ )
+       for( int row = column; row <= 2 * m_detail + column; row++ )
+               computeVertex( strip, column, row );
+
+       for( int strip = 1; strip < 5; strip++ )
+       for( int row = 0; row <= 3 * m_detail; row++ )
+               computeVertex( strip, 0, row );
+
+       for( int row = 0; row <= 2 * m_detail; row++ )
+               computeVertex( 0, 0, row );
+
+       for( int row = m_detail; row <= 3 * m_detail; row++ )
+               computeVertex( 4, m_detail, row );
+
+       unsigned int i = 0;
+       for( int strip = 0; strip < 5; strip++ )
+       for( int column = 0; column < m_detail; column++ )
+       {
+               int row = column;
+               m_indexBuffer[i++] = indexOfVertex( strip, column, row );
+               for( ; row <= 2 * m_detail + column; row++ )
+               {
+                       m_indexBuffer[i++] =
+                               indexOfVertex( strip, column, row );
+                       m_indexBuffer[i++] =
+                               indexOfVertex( strip, column + 1, row + 1 );
+               }
+               m_indexBuffer[i++] = indexOfVertex( strip, column + 1,
+                       2 * m_detail + column + 1);
+       }
+
+       m_isInitialized = true;
+}
+
+void GLSphere::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 )
+{
+       const GLfloat precision = 0.001;
+
+       if( GLVector3<GLfloat>::approx_equal( radius, m_radius, precision ) )
+       {
+               draw();
+               return;
+       }
+
+       GLfloat factor = radius / m_radius;
+       glEnable( GL_NORMALIZE );
+       glPushMatrix();
+       glScalef( factor, factor, factor );
+       draw();
+       glPopMatrix();
+       glDisable( GL_NORMALIZE );
+}
+
+GLCylinder::GLCylinder()
+       : GLVertexArray()
+{
+       m_mode = GL_QUAD_STRIP;
+       m_faces = 0;
+       m_radius = -1.0;
+}
+
+void GLCylinder::setup( int faces, GLfloat radius )
+{
+       if( faces == m_faces && radius == m_radius ) return;
+       m_faces = faces;
+       m_radius = radius;
+       allocateId();
+       initialize();
+}
+
+void GLCylinder::initialize()
+{
+       if( m_faces < 3 ) return;
+
+       m_vertexCount = 2 * m_faces + 2; // we will use a redundant vertex array
+       m_indexCount = 0; // we won't use it.
+
+       if( ! allocateBuffers() ) return;
+
+       for( int i = 0; i <= m_faces; i++)
+       {
+               float angle = 2 * M_PI * i / m_faces;
+               float x = cosf( angle );
+               float y = sinf( angle );
+
+               m_normalBuffer[ 2 * i ].x = x;
+               m_normalBuffer[ 2 * i ].y = y;
+               m_normalBuffer[ 2 * i ].z = 0.0;
+
+               m_vertexBuffer[ 2 * i ].x = x * m_radius ;
+               m_vertexBuffer[ 2 * i ].y = y * m_radius;
+               m_vertexBuffer[ 2 * i ].z = 1.0;
+
+               m_normalBuffer[ 2 * i + 1].x = x;
+               m_normalBuffer[ 2 * i + 1].y = y;
+               m_normalBuffer[ 2 * i + 1].z = 0.0;
+
+               m_vertexBuffer[ 2 * i + 1].x = x * m_radius;
+               m_vertexBuffer[ 2 * i + 1].y = y * m_radius ;
+               m_vertexBuffer[ 2 * i + 1].z = 0.0;
+       }
+
+       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
new file mode 100644 (file)
index 0000000..4c47568
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef KALZIUMGLHELPERCLASSES_H
+#define KALZIUMGLHELPERCLASSES_H
+/***************************************************************************
+    copyright            : (C) 2006 by Benoit Jacob
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+#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
+ */
+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();
+};
+
+/**
+ * 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 GLVector3
+{
+       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 ); }
+
+               /**
+                * 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;
+               }
+               
+               /**
+                * 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;
+
+               virtual void initialize();
+
+       public:
+               GLSphere();
+               virtual ~GLSphere() {}
+               virtual void setup( int detail, GLfloat radius );
+               virtual void drawScaled( GLfloat radius );
+};
+
+/**
+ * This class represents and draws a cylinder
+ *
+ * @author Benoit Jacob
+ */
+class GLCylinder : public GLVertexArray
+{
+       protected:
+               int m_faces;
+               GLfloat m_radius;
+
+               virtual void initialize();
+
+       public:
+               GLCylinder();
+               virtual ~GLCylinder() {}
+               virtual void setup( int detail, GLfloat radius );
+               virtual inline void draw();
+};
+
+#endif // KALZIUMGLHELPERCLASSES_H
+
index 15543d5571fad4be6ba770047ed284e812f0fd5f..52ea5d95126b8ad5d28d3c39bea6ccf418d39d1d 100644 (file)
@@ -12,6 +12,7 @@
  *                                                                         *
  ***************************************************************************/
 #include "kalziumglwidget.h"
+#include "kalziumglhelperclasses.h"
 
 #include <math.h>
 
@@ -376,7 +377,7 @@ void KalziumGLWidget::drawBond( FLOAT x1, FLOAT y1, FLOAT 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 );
+//     axis.construct_ortho_basis_given_first_vector( v, w );
 
        // normalize v and w. We DON'T want to normalize axis
        v.normalize();
@@ -529,88 +530,6 @@ void KalziumGLWidget::slotSetDetail( int detail )
        updateGL();
 }
 
-template<class T> bool GLVector3<T>::approx_equal(
-       FLOAT a, FLOAT b, FLOAT precision )
-{
-       FLOAT abs_a = GLFABS( a );
-       FLOAT abs_b = GLFABS( b );
-
-       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 )
-{
-       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,
-                  GLfloat alpha )
-{
-       m_red = red;
-       m_green = green;
-       m_blue = blue;
-       m_alpha = alpha;
-}
-
-GLColor& GLColor::operator=( const GLColor& other )
-{
-       m_red = other.m_red;
-       m_green = other.m_green;
-       m_blue = other.m_blue;
-       m_alpha = other.m_alpha;
-
-       return *this;
-}
-
 GLColor& KalziumGLWidget::getAtomColor( OpenBabel::OBAtom* atom )
 {
        static GLColor c;
@@ -655,6 +574,10 @@ GLColor& KalziumGLWidget::getAtomColor( OpenBabel::OBAtom* atom )
        return c;
 }
 
+void KalziumGLWidget::slotAtomsSelected( QList<OpenBabel::OBAtom*> atoms )
+{
+
+}
 
 void KalziumGLWidget::slotAtomSelected( OpenBabel::OBAtom* atom )
 {
@@ -663,333 +586,4 @@ void KalziumGLWidget::slotAtomSelected( OpenBabel::OBAtom* atom )
        updateGL();
 }
 
-inline void GLColor::apply()
-{
-       glColor4fv( reinterpret_cast<GLfloat *>( this ) );
-}
-
-void GLColor::applyAsMaterials()
-{
-       GLfloat ambientColor [] = { m_red / 2, m_green / 2, m_blue / 2,
-                                   m_alpha };
-       GLfloat diffuseColor [] = { m_red, m_green, m_blue, m_alpha };
-       GLfloat specularColor [] = { (2.0 + m_red) / 3, (2.0 + m_green) / 3,
-               (2.0 + m_blue) / 3, m_alpha };
-
-       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);
-}
-
-GLVertexArray::GLVertexArray()
-{
-       allocateId();
-       m_mode = GL_TRIANGLE_STRIP;
-       m_vertexBuffer = 0;
-       m_normalBuffer = 0;
-       m_indexBuffer = 0;
-       m_isInitialized = false;
-}
-
-GLVertexArray::~GLVertexArray()
-{
-       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()
-{
-       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()
-{
-       if( m_vertexCount > 65536 ) return false;
-
-       m_isInitialized = false;
-
-       if( m_indexBuffer )
-       {
-               delete [] m_indexBuffer;
-               m_indexBuffer = 0;
-       }
-       if( m_vertexBuffer )
-       {
-               delete [] m_vertexBuffer;
-               m_vertexBuffer = 0;
-       }
-       if( m_normalBuffer ) 
-       {
-               delete [] m_normalBuffer;
-               m_normalBuffer = 0;
-       }
-
-       m_vertexBuffer = new GLVector3<GLfloat>[m_vertexCount];
-       if( ! m_vertexBuffer ) return false;
-       m_normalBuffer = new GLVector3<GLfloat>[m_vertexCount];
-       if( ! m_normalBuffer ) return false;
-       m_indexBuffer = new unsigned short[m_indexCount];
-       if( ! m_indexBuffer ) return false;
-
-       return true;
-}
-
-GLSphere::GLSphere()
-       : GLVertexArray()
-{
-       m_detail = 0;
-       m_radius = -1.0;
-}
-
-unsigned short GLSphere::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)
-{
-       strip %= 5;
-       int next_strip = (strip + 1) % 5;
-
-       GLVector3<GLfloat> *vertex =
-               &m_vertexBuffer[ indexOfVertex( strip, column, row ) ];
-
-       GLVector3<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 GLVector3<GLfloat> southPole( 0, -1, -phi );
-
-       const GLVector3<GLfloat> *v0, *v1, *v2;
-       int  c1, c2;
-
-       if( row >= 2 * m_detail && column == 0 )
-       {
-               strip--;
-               if( strip < 0 ) strip += 5;
-               next_strip--;
-               if( next_strip < 0 ) next_strip += 5;
-               column = m_detail;
-       }
-
-       if( row  <= m_detail )
-       {
-               v0 = &northVertex[strip];
-               v1 = &northPole;
-               v2 = &northVertex[next_strip];
-               c1 = m_detail - row;
-               c2 = column;
-       }
-       else if( row >= 2 * m_detail )
-       {
-               v0 = &southVertex[next_strip];
-               v1 = &southPole;
-               v2 = &southVertex[strip];
-               c1 = row - 2 * m_detail;
-               c2 = m_detail - column;
-       }
-       else if( row <= m_detail + column )
-       {
-               v0 = &northVertex[next_strip];
-               v1 = &southVertex[next_strip];
-               v2 = &northVertex[strip];
-               c1 = row - m_detail;
-               c2 = m_detail - column;
-       }
-       else
-       {
-               v0 = &southVertex[strip];
-               v1 = &southVertex[next_strip];
-               v2 = &northVertex[strip];
-               c1 = column;
-               c2 = 2 * m_detail - row;
-       }
-
-       GLfloat u1 = GLfloat(c1) / m_detail;
-       GLfloat u2 = GLfloat(c2) / m_detail;
-
-       vertex->x = v0->x + u1 * (v1->x - v0->x) + u2 * (v2->x - v0->x);
-       vertex->y = v0->y + u1 * (v1->y - v0->y) + u2 * (v2->y - v0->y);
-       vertex->z = v0->z + u1 * (v1->z - v0->z) + u2 * (v2->z - v0->z);
-
-       vertex->normalize();
-
-       *normal = *vertex;
-
-       vertex->x *= m_radius;
-       vertex->y *= m_radius;
-       vertex->z *= m_radius;
-}
-
-
-void GLSphere::initialize()
-{
-       if( m_detail < 1 ) return;
-       m_vertexCount = ( 3 * m_detail + 1 ) * ( 5 * m_detail + 1 );
-       m_indexCount = (2 * ( 2 * m_detail + 1 ) + 2 ) * 5 * m_detail;
-
-       if( ! allocateBuffers() ) return;
-
-       for( int strip = 0; strip < 5; strip++ )
-       for( int column = 1; column < m_detail; column++ )
-       for( int row = column; row <= 2 * m_detail + column; row++ )
-               computeVertex( strip, column, row );
-
-       for( int strip = 1; strip < 5; strip++ )
-       for( int row = 0; row <= 3 * m_detail; row++ )
-               computeVertex( strip, 0, row );
-
-       for( int row = 0; row <= 2 * m_detail; row++ )
-               computeVertex( 0, 0, row );
-
-       for( int row = m_detail; row <= 3 * m_detail; row++ )
-               computeVertex( 4, m_detail, row );
-
-       unsigned int i = 0;
-       for( int strip = 0; strip < 5; strip++ )
-       for( int column = 0; column < m_detail; column++ )
-       {
-               int row = column;
-               m_indexBuffer[i++] = indexOfVertex( strip, column, row );
-               for( ; row <= 2 * m_detail + column; row++ )
-               {
-                       m_indexBuffer[i++] =
-                               indexOfVertex( strip, column, row );
-                       m_indexBuffer[i++] =
-                               indexOfVertex( strip, column + 1, row + 1 );
-               }
-               m_indexBuffer[i++] = indexOfVertex( strip, column + 1,
-                       2 * m_detail + column + 1);
-       }
-
-       m_isInitialized = true;
-}
-
-void GLSphere::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 )
-{
-       const GLfloat precision = 0.001;
-
-       if( GLVector3<GLfloat>::approx_equal( radius, m_radius, precision ) )
-       {
-               draw();
-               return;
-       }
-
-       GLfloat factor = radius / m_radius;
-       glEnable( GL_NORMALIZE );
-       glPushMatrix();
-       glScalef( factor, factor, factor );
-       draw();
-       glPopMatrix();
-       glDisable( GL_NORMALIZE );
-}
-
-GLCylinder::GLCylinder()
-       : GLVertexArray()
-{
-       m_mode = GL_QUAD_STRIP;
-       m_faces = 0;
-       m_radius = -1.0;
-}
-
-void GLCylinder::setup( int faces, GLfloat radius )
-{
-       if( faces == m_faces && radius == m_radius ) return;
-       m_faces = faces;
-       m_radius = radius;
-       allocateId();
-       initialize();
-}
-
-void GLCylinder::initialize()
-{
-       if( m_faces < 3 ) return;
-
-       m_vertexCount = 2 * m_faces + 2; // we will use a redundant vertex array
-       m_indexCount = 0; // we won't use it.
-
-       if( ! allocateBuffers() ) return;
-
-       for( int i = 0; i <= m_faces; i++)
-       {
-               float angle = 2 * M_PI * i / m_faces;
-               float x = cosf( angle );
-               float y = sinf( angle );
-
-               m_normalBuffer[ 2 * i ].x = x;
-               m_normalBuffer[ 2 * i ].y = y;
-               m_normalBuffer[ 2 * i ].z = 0.0;
-
-               m_vertexBuffer[ 2 * i ].x = x * m_radius ;
-               m_vertexBuffer[ 2 * i ].y = y * m_radius;
-               m_vertexBuffer[ 2 * i ].z = 1.0;
-
-               m_normalBuffer[ 2 * i + 1].x = x;
-               m_normalBuffer[ 2 * i + 1].y = y;
-               m_normalBuffer[ 2 * i + 1].z = 0.0;
-
-               m_vertexBuffer[ 2 * i + 1].x = x * m_radius;
-               m_vertexBuffer[ 2 * i + 1].y = y * m_radius ;
-               m_vertexBuffer[ 2 * i + 1].z = 0.0;
-       }
-
-       m_isInitialized = true;
-}
-
-void GLCylinder::draw()
-{
-       if ( ! m_isInitialized ) return;
-       select();
-       glDrawArrays( m_mode, 0, m_vertexCount );
-}
-
 #include "kalziumglwidget.moc"
index 3e046a699c0c700a919346cf45bc457b8cede9cf..a42075519be869195c480d5e95ce58c9f06e55ec 100644 (file)
@@ -2,7 +2,6 @@
 #define KALZIUMGLWIDGET_H
 /***************************************************************************
     copyright            : (C) 2006 by Benoit Jacob
-    email                : cniehaus@kde.org
  ***************************************************************************/
 
 /***************************************************************************
  *                                                                         *
  ***************************************************************************/
 
+#include "kalziumglhelperclasses.h"
+
 #include <QGLWidget>
+#include <QList>
 #include <openbabel/mol.h>
 
-#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
- */
-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.
-        */
-       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();
-};
-
-/**
- * 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 GLVector3
-{
-       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 ); }
-
-               /**
-                * 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;
-               }
-               
-               /**
-                * 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();
-               virtual inline 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;
-
-               virtual void initialize();
-
-       public:
-               GLSphere();
-               virtual ~GLSphere() {}
-               virtual void setup( int detail, GLfloat radius );
-               virtual void drawScaled( GLfloat radius );
-};
-
-/**
- * This class represents and draws a cylinder
- *
- * @author Benoit Jacob
- */
-class GLCylinder : public GLVertexArray
-{
-       protected:
-               int m_faces;
-               GLfloat m_radius;
-
-               virtual void initialize();
-
-       public:
-               GLCylinder();
-               virtual ~GLCylinder() {}
-               virtual void setup( int detail, GLfloat radius );
-               virtual inline void draw();
-};
-
 /**
  * This class displays the 3D-view of a molecule
  * 
@@ -374,6 +185,8 @@ class KalziumGLWidget : public QGLWidget
                 * The atom @p atom was selected by the user
                 */
                void slotAtomSelected( OpenBabel::OBAtom* atom );
+               
+               void slotAtomsSelected( QList<OpenBabel::OBAtom*> atoms );
 
        protected:
                /**
@@ -402,16 +215,6 @@ class KalziumGLWidget : public QGLWidget
                 */
                void prepareMoleculeData();
                
-               /**
-                * This method draws a sphere
-                * @param x
-                * @param y
-                * @param z
-                * @param red
-                * @param green
-                * @param blue
-                */
-
                virtual void drawSphere( 
                                GLFLOAT x, 
                                GLFLOAT y, 
@@ -421,15 +224,14 @@ class KalziumGLWidget : public QGLWidget
 
                /**
                 * This method draws a bond
-                * @param x
-                * @param y
-                * @param z
-                * @param radius
-                * @param red
-                * @param green
-                * @param blue
+                * @param x1
+                * @param y1
+                * @param z1
+                * @param x2
+                * @param y2
+                * @param z2
+                * @param color
                 */
-
                virtual void drawBond( GLFLOAT x1, GLFLOAT y1, GLFLOAT z1,
                        GLFLOAT x2, GLFLOAT y2, GLFLOAT z2,
                        GLColor &color );
@@ -465,6 +267,5 @@ class KalziumGLWidget : public QGLWidget
                 */
                virtual void setupObjects();
 };
-
-
 #endif // KALZIUMGLWIDGET_H
+
index a58fceb1021ac232626133bd7196234fd87533b3..fdefbfa3e8cb335ed853e780bedece69b7158890 100644 (file)
@@ -7,6 +7,7 @@ if(OPENBABEL2_FOUND)
 endif(OPENBABEL2_FOUND)
 
 set(kalziumui_PART_SRCS 
+   ${CMAKE_SOURCE_DIR}/kalzium/src/kalziumglhelperclasses.cpp
    ${CMAKE_SOURCE_DIR}/kalzium/src/kalziumglwidget.cpp
    )