/**********************************************************************
GLPainter - drawing spheres, cylinders and text in a GLWidget
Copyright (C) 2007 Benoit Jacob
Copyright (C) 2007 Donald Ephraim Curtis
Copyright (C) 2007-2008 Marcus D. Hanwell
This file is part of the Avogadro molecular editor project.
For more information, see
Avogadro 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.
Avogadro is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
**********************************************************************/
#ifndef GLPAINTER_H
#define GLPAINTER_H
#include
#include
namespace Avogadro
{
/**
* @class GLPainter glpainter.h
* @brief Implementation of the Painter class using OpenGL.
* @author Marcus D. Hanwell
*
* This class implements the base Painter class using OpenGL. It is intended
* to be used with the GLWidget to render molecules and other constructs to
* an OpenGL context.
*
* @sa Painter
*/
class GLWidget;
class GLPainterPrivate;
class GLPainter : public Painter
{
friend class GLWidget;
public:
/**
* Constructor.
* @param quality defaults to -1, valid range from 0 to 4.
*/
GLPainter (int quality=-1);
/**
* Destructor.
*/
~GLPainter();
/**
* Sets the global quality setting. This influences the detail level of the
* geometric objects (spheres and cylinders). Values range from 0 to
* PAINTER_GLOBAL_QUALITY_SETTINGS-1.
*/
void setQuality (int quality);
/**
* @return the current global quality setting.
*/
int quality() const;
/**
* Uses the primitive to set the type and name if the Paint Device supports it.
* @param primitive the primitive about to be drawn.
*/
void setName (const Primitive *primitive);
/**
* Sets the primitive type and id.
* @param type the primitive type about to be drawn.
* @param id the primitive id.
*/
void setName (Primitive::Type type, int id);
/**
* Set the color to paint the OpenGL primitives with.
* @param color the color to be used for painting.
*/
void setColor (const Color *color);
/**
* Set the color to paint the OpenGL primitives with.
* @param color the color to be used for painting.
*/
void setColor (const QColor *color);
/**
* Set the color to paint elements with where 0.0 is the minimum and 1.0
* is the maximum.
* @param red component of the color.
* @param green component of the color.
* @param blue component of the color.
* @param alpha component of the color.
*/
void setColor (float red, float green, float blue, float alpha = 1.0);
/**
* Draws a sphere, leaving the Painter choose the appropriate detail level based on the
* apparent radius (ratio of radius over distance) and the global quality setting.
* @param center the position of the center of the sphere.
* @param radius the radius of the sphere.
*/
void drawSphere (const Eigen::Vector3d *center, float radius);
/**
* Draws a cylinder, leaving the Painter choose the appropriate detail level based on the
* apparent radius (ratio of radius over distance) and the global quality setting.
* @param end1 the position of the first end of the cylinder.
* @param end2 the position of the second end of the cylinder.
* @param radius the radius, i.e. half-width of the cylinder.
*/
void drawCylinder (const Eigen::Vector3d &end1, const Eigen::Vector3d &end2,
double radius);
/**
* Draws a multiple cylinder (see below), leaving the Painter choose the appropriate
* detail level based on the apparent radius (ratio of radius over distance) and the
* global quality setting.
*
* What is a "multiple cylinder"? Think bond of order two or more between two atoms.
* This function is here to allow drawing multiple bonds in a single call.
*
* This function takes care of rendering multiple bonds in such a way that the individual
* bonds avoid hiding each other, at least in the defaut viewpoint of a molecule.
* To achieves that, it asks the GLWidget for the the normal vector of the
* molecule's best-fitting plane.
*
* @param end1 the position of the first end of the bond.
* @param end2 the position of the second end of the bond.
* @param radius the radius, i.e. half-width of each cylinder.
* @param order the multiplicity order of the bond, e.g. 2 for a double bond.
* When this parameter equals 1, this function is equivalent to
* drawCylinder().
* @param shift how far away from the central axis the cylinders are shifted.
* In other words this influences the total width of multiple bonds.
*/
void drawMultiCylinder (const Eigen::Vector3d &end1, const Eigen::Vector3d &end2,
double radius, int order, double shift);
/**
* Draws a cone between the tip and the base with the base radius given.
* @param base the position of the base of the cone.
* @param tip the position of the tip of the cone.
* @param radius the radius of the base of the cone.
*/
void drawCone(const Eigen::Vector3d &base, const Eigen::Vector3d &tip,
double radius);
/**
* Draws a GL line between the given points of the given width.
* @param start the position of the start of the line.
* @param end the position of the end of the line.
* @param lineWidth the width of the GL line.
*/
void drawLine(const Eigen::Vector3d &start, const Eigen::Vector3d &end,
double lineWidth);
/**
* Draws a multiple GL line between the given points. This function is the
* GL line equivalent to the drawMultiCylinder function and performs the
* same basic operations using simpler and quicker GL lines.
* @param start the position of the start of the line.
* @param end the position of the end of the line.
* @param lineWidth the width of the GL line.
* @param order the order of the bond, e.g. 2 for a double bond.
* @param stipple The GL stipple parameter for the bond, can be used to
* draw aromatic bonds etc.
* sa drawMultiCylinder
*/
void drawMultiLine(const Eigen::Vector3d &start, const Eigen::Vector3d &end,
double lineWidth, int order, short stipple);
/**
* Draws a triangle with vertives on the three given points. This function
* calculates the normal of the triangle and corrects the winding order to
* ensure the front face is facing the camera.
* @param p1 first triangle vertex.
* @param p2 second triangle vertex.
* @param p3 third triangle vertex.
*/
void drawTriangle(const Eigen::Vector3d &p1, const Eigen::Vector3d &p2,
const Eigen::Vector3d &p3);
/**
* Draws a triangle with vertives on the three given points using the
* given normal. This function corrects the triangle's winding order.
* @param p1 first triangle vertex.
* @param p2 second triangle vertex.
* @param p3 third triangle vertex.
* @param n the normal of the triangle.
*/
void drawTriangle(const Eigen::Vector3d &p1, const Eigen::Vector3d &p2,
const Eigen::Vector3d &p3, const Eigen::Vector3d &n);
/**
* Draw a cubic B-spline between the given points using GL NURBS.
* @param pts QVector containing the points to draw the cubic B-spline
* along.
* @param radius the radius of the cubic B-spline.
*/
void drawSpline(const QVector& pts, double radius);
/**
* Draws a shaded sector of a circle. The sector is defined by three vectors,
* the center of the circle, and two vectors that define the lines going out
* from the centre of the circle to the circumference of the circle. The
* actual points on the circumference are found using these two vectors and
* the radius of the circle.
*
* @param origin the center of the circle this sector is a portion of.
* @param direction1 a vector defining the line the first point will lie on.
* @param direction2 a vector defining the line the second point will lie on.
* @param radius the radius of the circle this sector is a portion of.
* @param alternateAngle whether to draw the obtuse angle made by the two vectors
* instead of the acute angle between them.
*/
void drawShadedSector(const Eigen::Vector3d & origin, const Eigen::Vector3d & direction1,
const Eigen::Vector3d & direction2, double radius,
bool alternateAngle = false);
/**
* Draws an arc. The arc is defined by three vectors, the center of the circle,
* and two vectors that define the lines going out from the center of the
* circle to the circumference of the circle. The actual points on the
* circumference are found using these two vectors and the radius of the circle.
*
* @param origin the center of the circle whose circumference this arc is a portion of.
* @param direction1 a vector defining the line the start of the arc will lie on.
* @param direction2 a vector defining the line the end of the arc will lie on.
* @param radius the radius of the circle whose circumference this arc is a portion of.
* @param lineWidth the thickness of the line the arc will be drawn with.
* @param alternateAngle whether to draw the obtuse angle made by the two vectors
* instead of the acute angle between them.
*/
void drawArc(const Eigen::Vector3d & origin, const Eigen::Vector3d &direction1,
const Eigen::Vector3d & direction2,
double radius, double lineWidth, bool alternateAngle = false);
/**
* Draws a solid two dimensional quadrilateral in three dimensional space.
*
* @param point1 the first of the four corners of the quadrilateral.
* @param point2 the second of the four corners of the quadrilateral.
* @param point3 the third of the four corners of the quadrilateral.
* @param point4 the last of the four corners of the quadrilateral.
*/
void drawShadedQuadrilateral(const Eigen::Vector3d & point1, const Eigen::Vector3d & point2,
const Eigen::Vector3d & point3, const Eigen::Vector3d & point4);
/**
* Draws the outline of a two dimensional quadrilateral in three dimensional space.
*
* @param point1 the first of the four corners of the quadrilateral.
* @param point2 the second of the four corners of the quadrilateral.
* @param point3 the third of the four corners of the quadrilateral.
* @param point4 the last of the four corners of the quadrilateral.
* @param lineWidth the thickness of the line the quadrilateral will be drawn with.
*/
void drawQuadrilateral(const Eigen::Vector3d & point1, const Eigen::Vector3d & point2,
const Eigen::Vector3d & point3, const Eigen::Vector3d & point4,
double lineWidth);
/**
* Draws a continuous mesh of triangles.
* @param mesh the mesh to be drawn.
* @param mode the mode to use. 0 = filled, 1 = lines and 2 = points.
*/
void drawMesh(const Mesh & mesh, int mode = 0);
/**
* Draws a continuous mesh of triangles and respects the colors stored.
* @param mesh the mesh to be drawn.
* @param mode the mode to use. 0 = filled, 1 = lines and 2 = points.
*/
void drawColorMesh(const Mesh & mesh, int mode = 0);
/**
* Draws text at a given window position, on top of the scene.
* @note Calls to drawText methods must be enclosed between begin() and end().
* @note Text is rendered as a transparent object, and should therefore be rendered after
* the opaque objects.
* @param x,y the window coordinates of the top-left corner of the text to render,
* (0, 0) is the top-left corner of the window.
* @param string the string to render. All character encodings are allowed but
* superposed characters are not supported yet. For accented letters,
* use a character giving the whole accented letter, not a separate
* character for the accent.
* @sa begin(), drawText(const Eigen::Vector3d &, const QString &) const,
* drawText(const QPoint &, const QString &) const
*/
int drawText (int x, int y, const QString &string) const;
/**
* Draws text at a given window position, on top of the scene.
* @note Calls to drawText methods must be enclosed between begin() and endText().
* @note Text is rendered as a transparent object, and should therefore be rendered after
* the opaque objects.
* @param pos the window coordinates of the top-left corner of the text to render,
* (0, 0) is the top-left corner of the window.
* @param string the string to render. All character encodings are allowed but
* superposed characters are not supported yet. For accented letters,
* use a character giving the whole accented letter, not a separate
* character for the accent.
* @sa begin(), drawText(const Eigen::Vector3d &, const QString &) const,
* drawText(int, int, const QString &) const
*/
int drawText (const QPoint& pos, const QString &string) const;
/**
* Draws text at a given scene position, inside the scene.
* @note Calls to drawText methods must be enclosed between begin() and endText().
* @note Text is rendered as a transparent object, and should therefore be rendered after
* the opaque objects.
* @param pos the scene coordinates of the top-left corner of the text to render.
* @param string The string to render. All character encodings are allowed but
* superposed characters are not supported yet. For accented letters,
* use a character giving the whole accented letter, not a separate
* character for the accent.
* @sa begin(), drawText(const QPoint&, const QString &) const,
* drawText(int, int, const QString &) const
*/
int drawText (const Eigen::Vector3d & pos, const QString &string) const;
/**
* Set the Painter up for painting onto a GLWidget, should be called
* before any painting.
*/
void begin(GLWidget *widget);
/**
* End painting, should be called when all painting is complete.
*/
void end();
/**
* @return true if the Painter is active.
*/
bool isActive();
/**
* @return true if the Painter is being shared between multiple GLWidgets.
*/
bool isShared();
/**
* @return the default quality level of the Painter.
*/
static int defaultQuality();
/**
* @return the maximum quality level of the Painter.
*/
static int maxQuality();
/**
* Set to true to turn dynamic object scaling on, false for off.
*/
void setDynamicScaling(bool scaling);
private:
GLPainterPrivate * const d;
bool m_dynamicScaling;
/**
* Increment the number of widgets the Painter is being shared by.
*/
void incrementShare();
/**
* Decrement the number of widgets the Painter is being shared by.
*/
void decrementShare();
/**
* Push the GL name and type, called internally before GL objects are
* painted on the GLWidget.
*/
void pushName();
/**
* Pop the GL name and type, called internally after GL objects are
* painted on the GLWidget.
*/
void popName();
/**
* Reset the GL name and type, called internally in popName() and also
* whenever frustum culling determines that a GL object must not be
* painted.
*/
void resetName();
};
} // end namespace Avogadro
#endif