/* * ShapeGraphicsItem.h * * (c) 2015 Sofian Audry -- info(@)sofianaudry(.)com * * 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 3 of the License, or * (at your option) any later version. * * This program 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, see . */ #ifndef SHAPE_GRAPHICS_ITEM_H_ #define SHAPE_GRAPHICS_ITEM_H_ #include #if __APPLE__ #include #else #include #endif #include #include #include "Shapes.h" #include "Paint.h" #include "Mapping.h" #include "MapperGLCanvas.h" MM_BEGIN_NAMESPACE class MapperGLCanvas; class ShapeControlPainter; /** * Represents a shape as part of a scene graph in one of the GL canvas. * A ShapeGraphicsItem contains a Mapping and is identified as either an * input (source) or an output (destination). */ class ShapeGraphicsItem : public QGraphicsItem { Q_DECLARE_TR_FUNCTIONS(ShapeGraphicsItem) public: typedef QSharedPointer ptr; protected: ShapeGraphicsItem(Mapping::ptr mapping, bool output=true); public: virtual ~ShapeGraphicsItem() {} public: /// Returns the MShape (depends on mapping and whether this is an input or output). MShape::ptr getShape() const { return _shape.toStrongRef(); } /// Returns the mapping. Mapping::ptr getMapping() const { return _mapping.toStrongRef(); } /// Returns the control painter (see below). QSharedPointer getControlPainter() { return _controlPainter; } /// Return whether the item is in the destination/output (true) or source/input (false). bool isOutput() const { return _output; } /// Returns pointer to GL canvas. MapperGLCanvas* getCanvas() const; /// Returns whether the mapping this shape is associated with is currently selected. bool isMappingCurrent() const; /// Returns whether the mapping this shape is associated should be visible. bool isMappingVisible() const; /// Returns the bounding rectangle of this item. virtual QRectF boundingRect() const { return shape().boundingRect(); } // virtual QPainterPath shape() const; // virtual void paint(QPainter *painter, // const QStyleOptionGraphicsItem *option, QWidget *widget); // virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); /// Built-in function: paints the shape. virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); protected: /// Main paint function that needs to be overriden (called by paint()). virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option) = 0; /// Can be overriden to perform operations *before* _doPaint() is called. virtual void _prePaint(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(painter); Q_UNUSED(option); } /// Can be overriden to perform operations *after* _doPaint() is called. virtual void _postPaint(QPainter *painter, const QStyleOptionGraphicsItem *option) { Q_UNUSED(painter); Q_UNUSED(option); } protected: QWeakPointer _mapping; QWeakPointer _shape; QSharedPointer _controlPainter; bool _output; }; class ColorGraphicsItem : public ShapeGraphicsItem { protected: ColorGraphicsItem(Mapping::ptr mapping, bool output=true) : ShapeGraphicsItem(mapping, output) {} public: virtual ~ColorGraphicsItem() {} protected: virtual void _prePaint(QPainter *painter, const QStyleOptionGraphicsItem *option); }; /// Graphics item for colored polygons (eg. quad, triangle). class PolygonColorGraphicsItem : public ColorGraphicsItem { public: PolygonColorGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~PolygonColorGraphicsItem() {} virtual QPainterPath shape() const; protected: virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option); }; /// Graphics item for colored polygons (eg. quad, triangle). class EllipseColorGraphicsItem : public ColorGraphicsItem { public: EllipseColorGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~EllipseColorGraphicsItem() {} virtual QPainterPath shape() const; protected: virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option); }; /// Abstract class for texture graphics items. class TextureGraphicsItem : public ShapeGraphicsItem { public: TextureGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~TextureGraphicsItem() {} protected: virtual void _doPaint(QPainter *painter, const QStyleOptionGraphicsItem *option); void _prePaint(QPainter* painter, const QStyleOptionGraphicsItem *option); void _postPaint(QPainter* painter, const QStyleOptionGraphicsItem *option); virtual void _doDrawOutput(QPainter* painter) = 0; virtual void _doDrawInput(QPainter* painter); protected: QWeakPointer _textureMapping; QWeakPointer _texture; QWeakPointer _inputShape; }; /// Graphics item for textured polygons (eg. triangles). class PolygonTextureGraphicsItem : public TextureGraphicsItem { public: PolygonTextureGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~PolygonTextureGraphicsItem(){} public: virtual QPainterPath shape() const; virtual QRectF boundingRect() const; }; /// Graphics item for textured triangles. class TriangleTextureGraphicsItem : public PolygonTextureGraphicsItem { public: TriangleTextureGraphicsItem(Mapping::ptr mapping, bool output=true) : PolygonTextureGraphicsItem(mapping, output) {} virtual ~TriangleTextureGraphicsItem(){} virtual void _doDrawOutput(QPainter* painter); }; /** * Graphics item for textured mesh. * The drawing technique recursively subdivides the quad to approximate projective mapping and thus * avoiding artifacts on the diagonals. Subdivided structure is cached to increase performance. * Source: Oliveira, M. "Correcting Texture Mapping Errors Introduced by Graphics Hardware" */ class MeshTextureGraphicsItem : public PolygonTextureGraphicsItem { // Internal use (cache). A structure consisting of the input and output quads of mapping. struct CacheQuadMapping { Quad::ptr input; Quad::ptr output; }; // Internal use (cache). Contains a parent mapping and all its sub-mappings. struct CacheQuadItem { CacheQuadMapping parent; QList subQuads; }; public: MeshTextureGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~MeshTextureGraphicsItem(){} virtual void _doDrawOutput(QPainter* painter); private: /** * Builds cache item recursively using the technique described in * Oliveira, M. "Correcting Texture Mapping Errors Introduced by Graphics Hardware" */ void _buildCacheQuadItem(CacheQuadItem& item, const Quad::ptr& inputQuad, const Quad::ptr& outputQuad, float outputArea, float inputThreshold = 0.0001f, float outputThreshold = 0.001f, int minArea=MM::MESH_SUBDIVISION_MIN_AREA, int maxDepth=-1); // Help function that returns four equal-size sub-quads from a quad. QList _split(const Quad& quad); // Contains the current cache. QVector > _cachedQuadItems; int _nHorizontalQuads; int _nVerticalQuads; // True iff shape was being grabbed last time _buildCacheQuadItem() was called. bool _wasGrabbing; }; /// Graphics item for textured mesh. class EllipseTextureGraphicsItem : public TextureGraphicsItem { static const int N_QUARTERS = 4; class DrawingData { public: QPointF center; QPointF controlCenter; float horizontalRadius; float verticalRadius; float rotation; float quarterAngles[N_QUARTERS]; DrawingData(const QSharedPointer& ellipse); float getSpanInQuarter(int quarter) const; void setPointOfEllipseAtAngle(QPointF& point, float circularAngle); }; public: EllipseTextureGraphicsItem(Mapping::ptr mapping, bool output=true); virtual ~EllipseTextureGraphicsItem(){} virtual QPainterPath shape() const; virtual QRectF boundingRect() const; virtual void _doDrawOutput(QPainter* painter); static void _setPointOfEllipseAtAngle(QPointF& point, const QPointF& center, float hRadius, float vRadius, float rotation, float circularAngle); }; MM_END_NAMESPACE #endif