opengl_gal.h 12.5 KB
Newer Older
1 2 3 4 5
/*
 * This program source code file is part of KICAD, a free EDA CAD application.
 *
 * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
 * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
6 7
 * Copyright (C) 2013 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * Graphics Abstraction Layer (GAL) for OpenGL
 *
 * 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.
 *
 * 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, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

#ifndef OPENGLGAL_H_
#define OPENGLGAL_H_

// GAL imports
#include <gal/graphics_abstraction_layer.h>
Maciej Suminski's avatar
Maciej Suminski committed
34
#include <gal/opengl/shader.h>
35 36 37
#include <gal/opengl/vertex_manager.h>
#include <gal/opengl/vertex_item.h>
#include <gal/opengl/noncached_container.h>
38
#include <gal/opengl/opengl_compositor.h>
39

40 41 42 43 44 45 46
#include <wx/wx.h>
#include <wx/glcanvas.h>

#include <cmath>
#include <iterator>
#include <vector>
#include <algorithm>
47 48 49
#include <memory>
#include <map>
#include <boost/smart_ptr/shared_ptr.hpp>
50
#include <boost/smart_ptr/shared_array.hpp>
51 52 53 54 55

#include <stdlib.h>
#include <iostream>
#include <fstream>

56 57 58
#ifndef CALLBACK
#define CALLBACK
#endif
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90

namespace KiGfx
{
class SHADER;

/**
 * @brief Class OpenGL_GAL is the OpenGL implementation of the Graphics Abstraction Layer.
 *
 * This is a direct OpenGL-implementation and uses low-level graphics primitives like triangles
 * and quads. The purpuse is to provide a fast graphics interface, that takes advantage of modern
 * graphics card GPUs. All methods here benefit thus from the hardware acceleration.
 */
class OPENGL_GAL : public GAL, public wxGLCanvas
{
public:

    /**
     * @brief Constructor OPENGL_GAL
     *
     * @param aParent is the wxWidgets immediate wxWindow parent of this object.
     *
     * @param aMouseListener is the wxEvtHandler that should receive the mouse events,
     *  this can be can be any wxWindow, but is often a wxFrame container.
     *
     * @param aPaintListener is the wxEvtHandler that should receive the paint
     *  event.  This can be any wxWindow, but is often a derived instance
     *  of this class or a containing wxFrame.  The "paint event" here is
     *  a wxCommandEvent holding EVT_GAL_REDRAW, as sent by PostPaint().
     *
     * @param aName is the name of this window for use by wxWindow::FindWindowByName()
     */
    OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener = NULL,
91
                wxEvtHandler* aPaintListener = NULL, const wxString& aName = wxT( "GLCanvas" ) );
92 93 94 95 96 97 98 99 100 101 102 103 104 105

    virtual ~OPENGL_GAL();

    // ---------------
    // Drawing methods
    // ---------------

    /// @copydoc GAL::BeginDrawing()
    virtual void BeginDrawing();

    /// @copydoc GAL::EndDrawing()
    virtual void EndDrawing();

    /// @copydoc GAL::DrawLine()
106
    virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
107

108 109 110
    /// @copydoc GAL::DrawSegment()
    virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );

111
    /// @copydoc GAL::DrawCircle()
112
    virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius );
113 114

    /// @copydoc GAL::DrawArc()
Maciej Suminski's avatar
Maciej Suminski committed
115 116
    virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
                          double aStartAngle, double aEndAngle );
117 118

    /// @copydoc GAL::DrawRectangle()
119
    virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
120

Maciej Suminski's avatar
Maciej Suminski committed
121 122 123
    /// @copydoc GAL::DrawPolyline()
    virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );

124 125 126 127
    /// @copydoc GAL::DrawPolygon()
    virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList );

    /// @copydoc GAL::DrawCurve()
128 129
    virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
                            const VECTOR2D& controlPointB, const VECTOR2D& endPoint );
130 131 132 133 134

    // --------------
    // Screen methods
    // --------------

135
    /// @brief Resizes the canvas.
Maciej Suminski's avatar
Maciej Suminski committed
136
    virtual void ResizeScreen( int aWidth, int aHeight );
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151

    /// @brief Shows/hides the GAL canvas
    virtual bool Show( bool aShow );

    /// @copydoc GAL::Flush()
    virtual void Flush();

    /// @copydoc GAL::ClearScreen()
    virtual void ClearScreen();

    // -----------------
    // Attribute setting
    // -----------------

    /// @copydoc GAL::SetStrokeColor()
152
    virtual void SetStrokeColor( const COLOR4D& aColor );
153 154 155 156 157 158 159 160 161 162 163 164

    // --------------
    // Transformation
    // --------------

    /// @copydoc GAL::Transform()
    virtual void Transform( MATRIX3x3D aTransformation );

    /// @copydoc GAL::Rotate()
    virtual void Rotate( double aAngle );

    /// @copydoc GAL::Translate()
165
    virtual void Translate( const VECTOR2D& aTranslation );
166 167

    /// @copydoc GAL::Scale()
168
    virtual void Scale( const VECTOR2D& aScale );
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188

    /// @copydoc GAL::Save()
    virtual void Save();

    /// @copydoc GAL::Restore()
    virtual void Restore();

    // --------------------------------------------
    // Group methods
    // ---------------------------------------------

    /// @copydoc GAL::BeginGroup()
    virtual int BeginGroup();

    /// @copydoc GAL::EndGroup()
    virtual void EndGroup();

    /// @copydoc GAL::DrawGroup()
    virtual void DrawGroup( int aGroupNumber );

189 190 191
    /// @copydoc GAL::ChangeGroupColor()
    virtual void ChangeGroupColor( int aGroupNumber, const COLOR4D& aNewColor );

192 193 194
    /// @copydoc GAL::ChangeGroupDepth()
    virtual void ChangeGroupDepth( int aGroupNumber, int aDepth );

195 196 197
    /// @copydoc GAL::DeleteGroup()
    virtual void DeleteGroup( int aGroupNumber );

198 199 200
    /// @copydoc GAL::ClearCache()
    virtual void ClearCache();

201 202 203 204 205 206 207 208 209 210
    // --------------------------------------------------------
    // Handling the world <-> screen transformation
    // --------------------------------------------------------

    /// @copydoc GAL::SaveScreen()
    virtual void SaveScreen();

    /// @copydoc GAL::RestoreScreen()
    virtual void RestoreScreen();

211 212 213
    /// @copydoc GAL::SetTarget()
    virtual void SetTarget( RenderTarget aTarget );

214 215 216
    /// @copydoc GAL::GetTarget()
    virtual RenderTarget GetTarget() const;

217 218 219
    /// @copydoc GAL::ClearTarget()
    virtual void ClearTarget( RenderTarget aTarget );

220 221 222 223 224
    // -------
    // Cursor
    // -------

    /// @copydoc GAL::DrawCursor()
225
    virtual void DrawCursor( const VECTOR2D& aCursorPosition );
226 227 228 229 230 231 232 233 234 235

    /**
     * @brief Function PostPaint
     * posts an event to m_paint_listener.  A post is used so that the actual drawing
     * function can use a device context type that is not specific to the wxEVT_PAINT event.
     */
    void PostPaint()
    {
        if( paintListener )
        {
236
            wxPaintEvent redrawEvent;
237 238 239 240 241 242 243 244 245 246 247 248 249 250
            wxPostEvent( paintListener, redrawEvent );
        }
    }

    void SetMouseListener( wxEvtHandler* aMouseListener )
    {
        mouseListener = aMouseListener;
    }

    void SetPaintListener( wxEvtHandler* aPaintListener )
    {
        paintListener = aPaintListener;
    }

251 252 253
    ///< Parameters passed to the GLU tesselator
    typedef struct
    {
254 255 256 257
        /// Manager used for storing new vertices
        VERTEX_MANAGER* vboManager;
        /// Intersect points, that have to be freed after tessellation
        std::deque< boost::shared_array<GLdouble> >& intersectPoints;
258 259
    } TessParams;

260
protected:
Maciej Suminski's avatar
Maciej Suminski committed
261
    virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
262 263 264 265 266 267 268 269

private:
    /// Super class definition
    typedef GAL super;

    static const int    CIRCLE_POINTS   = 64;   ///< The number of points for circle approximation
    static const int    CURVE_POINTS    = 32;   ///< The number of points for curve approximation

270 271 272 273 274
    wxClientDC*             clientDC;               ///< Drawing context
    wxGLContext*            glContext;              ///< OpenGL context of wxWidgets
    wxWindow*               parentWindow;           ///< Parent window
    wxEvtHandler*           mouseListener;
    wxEvtHandler*           paintListener;
275

276
    // Vertex buffer objects related fields
277
    typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap;
Maciej Suminski's avatar
Maciej Suminski committed
278 279 280 281 282 283
    GroupsMap               groups;                 ///< Stores informations about VBO objects (groups)
    unsigned int            groupCounter;           ///< Counter used for generating keys for groups
    VERTEX_MANAGER*         currentManager;         ///< Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs)
    VERTEX_MANAGER          cachedManager;          ///< Container for storing cached VERTEX_ITEMs
    VERTEX_MANAGER          nonCachedManager;       ///< Container for storing non-cached VERTEX_ITEMs
    VERTEX_MANAGER          overlayManager;         ///< Container for storing overlaid VERTEX_ITEMs
284 285

    // Framebuffer & compositing
Maciej Suminski's avatar
Maciej Suminski committed
286 287 288
    OPENGL_COMPOSITOR       compositor;             ///< Handles multiple rendering targets
    unsigned int            mainBuffer;             ///< Main rendering target
    unsigned int            overlayBuffer;          ///< Auxiliary rendering target (for menus etc.)
289
    RenderTarget            currentTarget;          ///< Current rendering target
290 291

    // Shader
Maciej Suminski's avatar
Maciej Suminski committed
292
    SHADER                  shader;         ///< There is only one shader used for different objects
293 294

    // Internal flags
Maciej Suminski's avatar
Maciej Suminski committed
295 296 297 298 299
    bool                    isGlewInitialized;          ///< Is GLEW initialized?
    bool                    isFramebufferInitialized;   ///< Are the framebuffers initialized?
    bool                    isShaderInitialized;        ///< Was the shader initialized?
    bool                    isGrouping;                 ///< Was a group started?

300 301
    VECTOR2D                cursorPosition;         ///< Current cursor position

Maciej Suminski's avatar
Maciej Suminski committed
302
    // Polygon tesselation
303 304 305 306
    /// The tessellator
    GLUtesselator*          tesselator;
    /// Storage for intersecting points
    std::deque< boost::shared_array<GLdouble> > tessIntersects;
307 308

    /**
Maciej Suminski's avatar
Maciej Suminski committed
309 310 311 312 313 314 315 316 317
     * @brief Draw a quad for the line.
     *
     * @param aStartPoint is the start point of the line.
     * @param aEndPoint is the end point of the line.
     */
    inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );

    /**
     * @brief Draw a semicircle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs
318
     * the proper function (drawStrokedSemiCircle or drawFilledSemiCircle).
319 320
     *
     * @param aCenterPoint is the center point.
Maciej Suminski's avatar
Maciej Suminski committed
321 322
     * @param aRadius is the radius of the semicircle.
     * @param aAngle is the angle of the semicircle.
323 324
     *
     */
Maciej Suminski's avatar
Maciej Suminski committed
325
    void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
326

327
    /**
Maciej Suminski's avatar
Maciej Suminski committed
328
     * @brief Draw a filled semicircle.
329 330
     *
     * @param aCenterPoint is the center point.
Maciej Suminski's avatar
Maciej Suminski committed
331 332
     * @param aRadius is the radius of the semicircle.
     * @param aAngle is the angle of the semicircle.
333 334
     *
     */
335
    void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
336 337

    /**
Maciej Suminski's avatar
Maciej Suminski committed
338
     * @brief Draw a stroked semicircle.
339 340
     *
     * @param aCenterPoint is the center point.
Maciej Suminski's avatar
Maciej Suminski committed
341 342
     * @param aRadius is the radius of the semicircle.
     * @param aAngle is the angle of the semicircle.
343 344
     *
     */
345 346
    void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );

347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
    // Event handling
    /**
     * @brief This is the OnPaint event handler.
     *
     * @param aEvent is the OnPaint event.
     */
    void onPaint( wxPaintEvent& aEvent );

    /**
     * @brief Skip the mouse event to the parent.
     *
     * @param aEvent is the mouse event.
     */
    void skipMouseEvent( wxMouseEvent& aEvent );

Maciej Suminski's avatar
Maciej Suminski committed
362
    /// Initialize GLEW
363 364
    void initGlew();

365 366
    /// @copydoc GAL::initCursor()
    virtual void initCursor( int aCursorSize );
367

368 369 370 371 372
    /**
     * @brief Blits cursor into the current screen.
     */
    void blitCursor();

373
    /**
374
     * @brief Returns a valid key that can be used as a new group number.
375 376 377
     *
     * @return An unique group number that is not used by any other group.
     */
378
    unsigned int getNewGroupNumber();
379 380 381 382
};
} // namespace KiGfx

#endif // OPENGLGAL_H_