~kicad-product-committers/kicad/kicad-gal

« back to all changes in this revision

Viewing changes to gal/opengl/opengl_gal.cpp

  • Committer: torstenhtr at gmx
  • Date: 2012-08-04 14:55:55 UTC
  • Revision ID: torstenhtr@gmx.de-20120804145555-jbm9k193p1tth439
Cleaned up the files.
Repaired and improved the test examples.
Added the wxDC backend.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * This program source code file is part of KICAD, a free EDA CAD application.
3
3
 *
4
 
 * Copyright (C) 2010 Virtenio GmbH, Torsten Hueter, torsten.hueter <at> virtenio.de
5
 
 * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
 
4
 * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
 
5
 * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
6
6
 *
7
7
 * Graphics Abstraction Layer (GAL) for OpenGL
8
8
 *
27
27
#include <gal/opengl/opengl_gal.h>
28
28
#include <gal/opengl/shader.h>
29
29
 
 
30
#include <wx/log.h>
 
31
 
30
32
#ifndef CALLBACK
31
33
#define CALLBACK
32
34
#endif
37
39
// FIXME Checking of attributes
38
40
 
39
41
#if defined(__WXGTK__)
40
 
const int glAttributes[] = { WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0 };
 
42
const int glAttributes[] =
 
43
{   WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0};
41
44
 
42
45
#elif defined(__WXMSW__)
43
46
#define glAttributes NULL
46
49
 
47
50
OPENGL_GAL::OPENGL_GAL( wxWindow *aParent, wxEvtHandler* aMouseListener,
48
51
                        wxEvtHandler* aPaintListener, bool isUseShaders, const wxString& aName ) :
49
 
                        wxGLCanvas( aParent, wxID_ANY, (int*) glAttributes, wxDefaultPosition,
50
 
                        wxDefaultSize, wxEXPAND, aName )
 
52
        wxGLCanvas( aParent, wxID_ANY, (int*)glAttributes, wxDefaultPosition, wxDefaultSize,
 
53
                    wxEXPAND, aName )
51
54
{
52
55
    // Create the OpenGL-Context
53
 
    m_glContext = new wxGLContext( this );
54
 
    m_parent = aParent;
55
 
    m_mouse_listener = aMouseListener;
56
 
    m_paint_listener = aPaintListener;
 
56
    glContext = new wxGLContext( this );
 
57
    parentWindow = aParent;
 
58
    mouseListener = aMouseListener;
 
59
    paintListener = aPaintListener;
57
60
 
58
61
    // Set the cursor size
59
62
    initCursor( 20 );
 
63
    SetCursorColor(COLOR4D(1.0, 1.0, 1.0, 1.0));
60
64
 
61
65
    // Initialize the flags
62
 
    m_isCreated = false;
63
 
    m_isDeleteSavedPixels = true;
64
 
    m_isGlewInitialized = false;
65
 
    m_isFrameBufferInitialized = false;
66
 
    m_isUseShaders = isUseShaders;
 
66
    isCreated = false;
 
67
    isDeleteSavedPixels = true;
 
68
    isGlewInitialized = false;
 
69
    isFrameBufferInitialized = false;
 
70
    isUseShader = isUseShaders;
 
71
    isGroupStarted = false;
 
72
 
 
73
    // Set grid defaults
 
74
    SetGridColor( COLOR4D( 0.3, 0.3, 0.3, 0.3 ) );
 
75
    SetCoarseGrid( 10 );
 
76
    SetGridLineWidth( 1.0 );
67
77
 
68
78
    // Connecting the event handlers.
69
79
    this->Connect( wxEVT_PAINT, wxPaintEventHandler( OPENGL_GAL::onPaint ) );
70
 
    this->Connect( wxEVT_SIZE,  wxSizeEventHandler( OPENGL_GAL::onSize ) );
 
80
    this->Connect( wxEVT_SIZE, wxSizeEventHandler( OPENGL_GAL::onSize ) );
71
81
 
72
82
#if 1
73
83
    // Mouse events are skipped to the parent
87
97
    SwapBuffers();
88
98
 
89
99
    // Delete the stored display lists
90
 
    for( std::deque<GLuint>::iterator group = m_displayListsGroup.begin();
91
 
         group != m_displayListsGroup.end(); group++ )
 
100
    for( std::deque<GLuint>::iterator group = displayListsGroup.begin();
 
101
            group != displayListsGroup.end(); group++ )
92
102
    {
93
103
        glDeleteLists( *group, 1 );
94
104
    }
95
105
 
96
 
    glDeleteFramebuffersEXT( 1, &m_mainFrameBufferObject );
97
 
    glDeleteRenderbuffersEXT( 1, &m_mainDepthBuffer );
98
 
    glDeleteTextures( 1, &m_mainTexture );
 
106
    // Delete the buffers
 
107
    if( isFrameBufferInitialized )
 
108
    {
 
109
        deleteFrameBuffer( &frameBuffer, &depthBuffer, &texture );
 
110
        deleteFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup );
 
111
    }
99
112
 
100
 
    delete m_glContext;
 
113
    delete glContext;
101
114
}
102
115
 
103
116
 
112
125
void OPENGL_GAL::onSize( wxSizeEvent& aEvent )
113
126
{
114
127
    // Get the new screen size
115
 
    m_screenSize = aEvent.GetSize();
 
128
    screenSize = VECTOR2D( aEvent.GetSize().x, aEvent.GetSize().y );
116
129
 
117
130
    // Delete old buffers for resizing
118
 
    if( m_isFrameBufferInitialized )
 
131
    if( isFrameBufferInitialized )
119
132
    {
120
 
        glDeleteFramebuffersEXT( 1, &m_mainFrameBufferObject );
121
 
        glDeleteRenderbuffersEXT( 1, &m_mainDepthBuffer );
122
 
        glDeleteTextures( 1, &m_mainTexture );
 
133
        deleteFrameBuffer( &frameBuffer, &depthBuffer, &texture );
 
134
        deleteFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup );
123
135
 
124
 
        m_isFrameBufferInitialized = false;
 
136
        // This flag is used for recreating the buffers
 
137
        isFrameBufferInitialized = false;
125
138
    }
126
139
 
127
140
    PostPaint();
131
144
void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent )
132
145
{
133
146
    // Post the mouse event to the event listener registered in constructor, if any
134
 
    if( m_mouse_listener )
135
 
        wxPostEvent( m_mouse_listener, aEvent );
 
147
    if( mouseListener )
 
148
        wxPostEvent( mouseListener, aEvent );
136
149
}
137
150
 
138
151
 
139
 
void OPENGL_GAL::initFrameBuffer()
 
152
void OPENGL_GAL::generateFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer,
 
153
                                      GLuint* aTexture )
140
154
{
141
 
    // We need frame buffer objects
142
 
    // One frame buffer is used for drawing the main window contents
 
155
    // We need frame buffer objects for drawing the screen contents
143
156
 
144
 
    // Generate frame buffer, depth buffer
145
 
    glGenFramebuffersEXT( 1, &m_mainFrameBufferObject );
146
 
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_mainFrameBufferObject );
 
157
    // Generate frame buffer and a depth buffer
 
158
    glGenFramebuffersEXT( 1, aFrameBuffer );
 
159
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, *aFrameBuffer );
147
160
 
148
161
    // Allocate memory for the depth buffer
149
162
    // Attach the depth buffer to the frame buffer
150
 
    glGenRenderbuffersEXT( 1, &m_mainDepthBuffer );
151
 
    glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_mainDepthBuffer );
 
163
    glGenRenderbuffersEXT( 1, aDepthBuffer );
 
164
    glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, *aDepthBuffer );
152
165
 
153
166
    // Use here a size of 24 bits for the depth buffer, 8 bits for the stencil buffer
154
167
    // this is required later for anti-aliasing
155
 
    glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_screenSize.x,
156
 
            m_screenSize.y );
157
 
 
 
168
    glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, screenSize.x,
 
169
                              screenSize.y );
158
170
    glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
159
 
            m_mainDepthBuffer );
160
 
    glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
161
 
                m_mainDepthBuffer );
 
171
                                  *aDepthBuffer );
 
172
    glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
 
173
                                  GL_RENDERBUFFER_EXT, *aDepthBuffer );
162
174
 
163
175
    // Generate the texture for the pixel storage
164
176
    // Attach the texture to the frame buffer
165
 
    glGenTextures( 1, &m_mainTexture );
166
 
    glBindTexture( GL_TEXTURE_2D, m_mainTexture );
167
 
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_screenSize.x, m_screenSize.y, 0, GL_RGBA,
168
 
            GL_UNSIGNED_BYTE, NULL );
169
 
 
 
177
    glGenTextures( 1, aTexture );
 
178
    glBindTexture( GL_TEXTURE_2D, *aTexture );
 
179
    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, screenSize.x, screenSize.y, 0, GL_RGBA,
 
180
                  GL_UNSIGNED_BYTE, NULL );
170
181
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
171
182
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
172
183
    glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D,
173
 
            m_mainTexture, 0 );
 
184
                               *aTexture, 0 );
174
185
 
175
186
    // Check the status, exit if the frame buffer can't be created
176
187
    GLenum status = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
177
 
    if( status != GL_FRAMEBUFFER_COMPLETE_EXT)
 
188
    if( status != GL_FRAMEBUFFER_COMPLETE_EXT )
178
189
    {
179
190
        cerr << "Can't create the frame buffer." << endl;
180
191
        exit( 1 );
181
192
    }
182
193
 
183
 
    m_isFrameBufferInitialized = true;
 
194
    isFrameBufferInitialized = true;
 
195
}
 
196
 
 
197
 
 
198
void OPENGL_GAL::deleteFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture )
 
199
{
 
200
    glDeleteFramebuffers( 1, aFrameBuffer );
 
201
    glDeleteRenderbuffers( 1, aDepthBuffer );
 
202
    glDeleteTextures( 1, aTexture );
 
203
}
 
204
 
 
205
 
 
206
void OPENGL_GAL::initFrameBuffers()
 
207
{
 
208
    generateFrameBuffer( &frameBuffer, &depthBuffer, &texture );
 
209
    generateFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup );
 
210
}
 
211
 
 
212
 
 
213
void OPENGL_GAL::SaveScreen()
 
214
{
 
215
    glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBufferBackup );
 
216
    glBindFramebuffer( GL_READ_FRAMEBUFFER, frameBuffer );
 
217
    glBlitFramebuffer( 0, 0, screenSize.x, screenSize.y, 0, 0, screenSize.x, screenSize.y,
 
218
                       GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
 
219
                       GL_NEAREST );
 
220
    glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer );
 
221
}
 
222
 
 
223
 
 
224
void OPENGL_GAL::RestoreScreen()
 
225
{
 
226
    glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer );
 
227
    glBindFramebuffer( GL_READ_FRAMEBUFFER, frameBufferBackup );
 
228
    glBlitFramebuffer( 0, 0, screenSize.x, screenSize.y, 0, 0, screenSize.x, screenSize.y,
 
229
                       GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
 
230
                       GL_NEAREST );
184
231
}
185
232
 
186
233
 
188
235
{
189
236
    // Initialize GLEW library
190
237
    GLenum err = glewInit();
191
 
    if( GLEW_OK != err)
 
238
    if( GLEW_OK != err )
192
239
    {
193
240
        cerr << "Error!!: " << glewGetErrorString( err ) << endl;
194
241
        exit( 1 );
195
 
    } else
 
242
    }
 
243
    else
196
244
    {
197
245
        cout << "Status: Using GLEW" << glewGetString( GLEW_VERSION ) << endl;
198
246
    }
199
247
 
200
248
    // Check the OpenGL version (minimum 2.1 is required)
201
 
    if( GLEW_VERSION_2_1)
 
249
    if( GLEW_VERSION_2_1 )
202
250
    {
203
251
        cout << "OpenGL Version 2.1 supported." << endl;
204
 
    } else
 
252
    }
 
253
    else
205
254
    {
206
255
        cerr << "OpenGL Version 2.1 is not supported!";
207
256
        exit( 1 );
208
257
    }
209
258
 
210
259
    // Frame buffers have to be supported
211
 
    if( !GLEW_ARB_framebuffer_object)
 
260
    if( !GLEW_ARB_framebuffer_object )
212
261
    {
213
262
        cerr << "Framebuffer objects are not supported!";
214
263
        exit( 1 );
219
268
    computeUnitSemiCircle();
220
269
    computeUnitArcs();
221
270
 
222
 
    m_isGlewInitialized = true;
 
271
    isGlewInitialized = true;
223
272
}
224
273
 
225
274
 
226
275
void OPENGL_GAL::BeginDrawing()
227
276
{
228
 
    SetCurrent( *m_glContext );
 
277
    SetCurrent( *glContext );
229
278
 
230
 
    m_clientDC = new wxClientDC( this );
 
279
    clientDC = new wxClientDC( this );
231
280
 
232
281
    // Initialize GLEW & FBOs
233
 
    if( !m_isGlewInitialized )
 
282
    if( !isGlewInitialized )
234
283
    {
235
284
        initGlew();
236
285
    }
237
286
 
238
 
    if( !m_isFrameBufferInitialized )
 
287
    if( !isFrameBufferInitialized )
239
288
    {
240
 
        initFrameBuffer();
 
289
        initFrameBuffers();
241
290
    }
242
291
 
243
292
    // Compile the shaders
244
 
    if (!m_isShaderInitialized && m_isUseShaders){
245
 
        string shaderNames[SHADER_NUMBER] = { string("circle"), string("line") };
246
 
        string prefix = string("../../../gal/opengl/shader/");
247
 
        for( int i = 0; i < 1; i++ ){
248
 
                m_shaderList.push_back(SHADER());
249
 
                        if( i == 0 ){
250
 
                                m_shaderList[i].ConfigureGeometryShader(256, GL_LINES, GL_QUAD_STRIP);
251
 
                        }
252
 
                        else {
253
 
                                m_shaderList[i].ConfigureGeometryShader(256, GL_TRIANGLES, GL_QUADS);
254
 
                        }
255
 
                        m_shaderList[i].AddSource(      prefix + shaderNames[i] + string(".frag"),
256
 
                                                                                SHADER_TYPE_FRAGMENT);
257
 
                        m_shaderList[i].AddSource(      prefix + shaderNames[i] + string(".vert"),
258
 
                                                                                SHADER_TYPE_VERTEX);
259
 
                        m_shaderList[i].AddSource(      prefix + shaderNames[i] + string(".geom"),
260
 
                                                                                SHADER_TYPE_GEOMETRY);
261
 
                        m_shaderList[i].Link();
262
 
                        m_shaderList[i].AddParameter(string("viewPortX2"));
263
 
                        m_shaderList[i].AddParameter(string("viewPortY2"));
264
 
        }
265
 
        m_isShaderInitialized = true;
 
293
    if( !isShaderInitialized && isUseShader )
 
294
    {
 
295
        string shaderNames[SHADER_NUMBER] = { string( "circle" ), string( "line" ) };
 
296
        string prefix = string( "../../../gal/opengl/shader/" );
 
297
        for( int i = 0; i < 2; i++ )
 
298
        {
 
299
            shaderList.push_back( SHADER() );
 
300
            if( i == 0 )
 
301
            {
 
302
                shaderList[i].ConfigureGeometryShader( 256, GL_LINES, GL_QUAD_STRIP );
 
303
            }
 
304
            else
 
305
            {
 
306
                shaderList[i].ConfigureGeometryShader( 256, GL_LINES, GL_QUADS );
 
307
            }
 
308
            shaderList[i].AddSource( prefix + shaderNames[i] + string( ".frag" ),
 
309
                                     SHADER_TYPE_FRAGMENT );
 
310
            shaderList[i].AddSource( prefix + shaderNames[i] + string( ".vert" ),
 
311
                                     SHADER_TYPE_VERTEX );
 
312
            shaderList[i].AddSource( prefix + shaderNames[i] + string( ".geom" ),
 
313
                                     SHADER_TYPE_GEOMETRY );
 
314
            shaderList[i].Link();
 
315
            shaderList[i].AddParameter( string( "viewPortX2" ) );
 
316
            shaderList[i].AddParameter( string( "viewPortY2" ) );
 
317
        }
 
318
 
 
319
        isShaderInitialized = true;
266
320
    }
267
321
 
268
322
    // Bind the main frame buffer object - all contents are drawn there
269
 
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_mainFrameBufferObject );
 
323
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, frameBuffer );
270
324
 
271
325
    // Disable 2D Textures
272
326
    glDisable( GL_TEXTURE_2D );
284
338
    // Set up the view port
285
339
    glMatrixMode( GL_PROJECTION );
286
340
    glLoadIdentity();
287
 
    glViewport( 0, 0, (GLsizei) m_screenSize.x, (GLsizei) m_screenSize.y );
 
341
    glViewport( 0, 0, (GLsizei)screenSize.x, (GLsizei)screenSize.y );
288
342
 
289
 
    // FIXME Better calculation of the clipping planes
290
 
    glOrtho( 0, (GLint) m_screenSize.x, 0, (GLsizei) m_screenSize.y,
291
 
            -1 / m_worldUnitLength,
292
 
             1 / m_worldUnitLength );
 
343
    // Create the screen transformation
 
344
    glOrtho( 0, (GLint)screenSize.x, 0, (GLsizei)screenSize.y, -depthRange.x, -depthRange.y );
293
345
 
294
346
    glMatrixMode( GL_MODELVIEW );
295
347
 
296
348
    // Set up the world <-> screen transformation
297
349
    ComputeWorldScreenMatrix();
298
 
    GLdouble matrixData[16] =
299
 
    { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
300
 
    matrixData[0] = m_worldScreenMatrix.m_data[0][0];
301
 
    matrixData[1] = m_worldScreenMatrix.m_data[1][0];
302
 
    matrixData[2] = m_worldScreenMatrix.m_data[2][0];
303
 
    matrixData[4] = m_worldScreenMatrix.m_data[0][1];
304
 
    matrixData[5] = m_worldScreenMatrix.m_data[1][1];
305
 
    matrixData[6] = m_worldScreenMatrix.m_data[2][1];
306
 
    matrixData[12] = m_worldScreenMatrix.m_data[0][2];
307
 
    matrixData[13] = m_worldScreenMatrix.m_data[1][2];
308
 
    matrixData[14] = m_worldScreenMatrix.m_data[2][2];
 
350
    GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
 
351
    matrixData[0] = worldScreenMatrix.m_data[0][0];
 
352
    matrixData[1] = worldScreenMatrix.m_data[1][0];
 
353
    matrixData[2] = worldScreenMatrix.m_data[2][0];
 
354
    matrixData[4] = worldScreenMatrix.m_data[0][1];
 
355
    matrixData[5] = worldScreenMatrix.m_data[1][1];
 
356
    matrixData[6] = worldScreenMatrix.m_data[2][1];
 
357
    matrixData[12] = worldScreenMatrix.m_data[0][2];
 
358
    matrixData[13] = worldScreenMatrix.m_data[1][2];
 
359
    matrixData[14] = worldScreenMatrix.m_data[2][2];
309
360
    glLoadMatrixd( matrixData );
310
361
 
311
362
    // Set defaults
312
 
    SetFillColor( m_fillColor );
313
 
    SetStrokeColor( m_strokeColor );
314
 
    m_isDeleteSavedPixels = true;
 
363
    SetFillColor( fillColor );
 
364
    SetStrokeColor( strokeColor );
 
365
    isDeleteSavedPixels = true;
315
366
}
316
367
 
317
368
 
320
371
    // Don't use blending for the final blitting
321
372
    glDisable( GL_BLEND );
322
373
 
323
 
    glColor4d(1.0, 1.0, 1.0, 1.0);
 
374
    glColor4d( 1.0, 1.0, 1.0, 1.0 );
324
375
 
325
376
    // Switch to the main frame buffer and blit the scene
326
377
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
327
378
 
328
 
    if( aIsClearFrameBuffer)
329
 
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
379
    if( aIsClearFrameBuffer )
 
380
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
330
381
 
331
382
    // Enable texturing and bind the main texture
332
383
    glEnable( GL_TEXTURE_2D );
333
 
    glBindTexture( GL_TEXTURE_2D, m_mainTexture );
 
384
    glBindTexture( GL_TEXTURE_2D, texture );
334
385
 
335
386
    // Draw a full screen quad with the texture
336
387
    glMatrixMode( GL_MODELVIEW );
362
413
    blitMainTexture( true );
363
414
    SwapBuffers();
364
415
 
365
 
    delete m_clientDC;
 
416
    delete clientDC;
 
417
}
 
418
 
 
419
 
 
420
inline void OPENGL_GAL::drawLineQuad( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
 
421
{
 
422
    VECTOR2D startEndVector = aEndPoint - aStartPoint;
 
423
    double lineLength = startEndVector.EuclideanNorm();
 
424
 
 
425
    // Limit the width of the line to a minimum of one pixel
 
426
    // this looks best without anti-aliasing
 
427
    // XXX Should be improved later.
 
428
    double scale = 0.5 * lineWidth / lineLength;
 
429
    double scale1pix = 0.5001 / worldScale / lineLength;
 
430
    if( lineWidth * worldScale < 1.0002 && !isGroupStarted )
 
431
    {
 
432
        scale = scale1pix;
 
433
    }
 
434
 
 
435
    VECTOR2D perpendicularVector( -startEndVector.y * scale, startEndVector.x * scale );
 
436
 
 
437
    // Compute the edge points of the line
 
438
    VECTOR2D point1 = aStartPoint + perpendicularVector;
 
439
    VECTOR2D point2 = aStartPoint - perpendicularVector;
 
440
    VECTOR2D point3 = aEndPoint + perpendicularVector;
 
441
    VECTOR2D point4 = aEndPoint - perpendicularVector;
 
442
 
 
443
    glBegin( GL_QUADS );
 
444
    glVertex3d( point1.x, point1.y, layerDepth );
 
445
    glVertex3d( point2.x, point2.y, layerDepth );
 
446
    glVertex3d( point4.x, point4.y, layerDepth );
 
447
    glVertex3d( point3.x, point3.y, layerDepth );
 
448
    glEnd();
 
449
}
 
450
 
 
451
 
 
452
inline void OPENGL_GAL::drawLineCap( POINT2D aStartPoint, POINT2D aEndPoint, double aDepthOffset )
 
453
{
 
454
    VECTOR2D startEndVector = aEndPoint - aStartPoint;
 
455
    double lineLength = startEndVector.EuclideanNorm();
 
456
    double lineAngle = atan2( startEndVector.y, startEndVector.x );
 
457
 
 
458
    switch( lineCap )
 
459
    {
 
460
    case LINE_CAP_BUTT:
 
461
        // TODO
 
462
        break;
 
463
    case LINE_CAP_ROUND:
 
464
    {
 
465
        // Add a semicircle at the line end
 
466
        drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2, aDepthOffset );
 
467
        break;
 
468
    }
 
469
    case LINE_CAP_SQUARED:
 
470
    {
 
471
        VECTOR2D offset;
 
472
        offset = startEndVector * ( lineWidth / lineLength / 2.0 );
 
473
        aStartPoint = aStartPoint - offset;
 
474
        aEndPoint = aEndPoint + offset;
 
475
        break;
 
476
    }
 
477
    }
 
478
 
366
479
}
367
480
 
368
481
 
369
482
void OPENGL_GAL::DrawLine( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
370
483
{
371
 
    if ( false ) //m_isUseShaders )
 
484
    if( isUseShader )
372
485
    {
373
 
        // FIXME This is work in progress ..
374
 
        glBlendFunc( GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR );
375
 
        glBlendColor( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
376
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
377
 
        m_shaderList[1].Use();
378
 
        m_shaderList[1].SetParameter( 0, m_screenSize.x / 2 );
379
 
        m_shaderList[1].SetParameter( 1, m_screenSize.y / 2 );
380
 
        glBegin( GL_TRIANGLES );
381
 
        glVertex3d( aStartPoint.x, aStartPoint.y, m_layerDepth );
382
 
        glVertex3d( aEndPoint.x, aEndPoint.y, m_layerDepth );
383
 
        glVertex3d( m_lineWidth, m_lineWidth, m_lineWidth );
 
486
        shaderList[1].Use();
 
487
        shaderList[1].SetParameter( 0, screenSize.x / 2 );
 
488
        shaderList[1].SetParameter( 1, screenSize.y / 2 );
 
489
        glBegin( GL_LINES );
 
490
        glVertex3d( aStartPoint.x, aStartPoint.y, layerDepth );
 
491
        glVertex3d( aEndPoint.x, aEndPoint.y, lineWidth );
384
492
        glEnd();
385
 
        m_shaderList[1].Deactivate();
 
493
        shaderList[1].Deactivate();
 
494
        bool saved = isFillEnabled;
 
495
        COLOR4D savedColor = fillColor;
 
496
        fillColor = strokeColor;
 
497
        SetIsFill( true );
 
498
        DrawCircle( aStartPoint, lineWidth / 2 );
 
499
        DrawCircle( aEndPoint, lineWidth / 2 );
 
500
        SetIsFill( saved );
 
501
        fillColor = savedColor;
386
502
    }
387
 
 
388
 
    VECTOR2D startEndVector = aEndPoint - aStartPoint;
389
 
    double lineLength = startEndVector.EuclideanNorm();
390
 
    if ( lineLength > 0.0 )
 
503
    else
391
504
    {
392
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
393
 
 
394
 
        if ( m_lineCap == LINE_CAP_SIMPLE )
395
 
        {
396
 
            // Use glLines for simple line drawing
397
 
            glDepthMask( GL_FALSE );
398
 
            glLineWidth( m_lineWidth );
399
 
            glBegin( GL_LINES );
400
 
            glVertex3d( aStartPoint.x, aStartPoint.y, m_layerDepth );
401
 
            glVertex3d( aEndPoint.x, aEndPoint.y, m_layerDepth );
402
 
            glEnd();
403
 
            glDepthMask( GL_TRUE );
404
 
        }
405
 
        else
406
 
        {
407
 
            // In this mode use a quad for drawing of the line
408
 
            // For this purpose compute the edge points of the line
409
 
            // TODO optimize
410
 
            double scale = 0.5 * m_lineWidth / lineLength;
411
 
            VECTOR2D perpendicularVector( -startEndVector.y * scale, startEndVector.x * scale );
412
 
            VECTOR2D point1 = aStartPoint + perpendicularVector;
413
 
            VECTOR2D point2 = aStartPoint - perpendicularVector;
414
 
            VECTOR2D point3 = aEndPoint + perpendicularVector;
415
 
            VECTOR2D point4 = aEndPoint - perpendicularVector;
416
 
 
417
 
            glBegin( GL_QUADS );
418
 
            glVertex3d( point1.x, point1.y, m_layerDepth );
419
 
            glVertex3d( point2.x, point2.y, m_layerDepth );
420
 
            glVertex3d( point4.x, point4.y, m_layerDepth );
421
 
            glVertex3d( point3.x, point3.y, m_layerDepth );
422
 
            glEnd();
423
 
 
424
 
            switch ( m_lineCap )
425
 
            {
426
 
            case LINE_CAP_SIMPLE:
427
 
                // TODO
428
 
                break;
429
 
            case LINE_CAP_BUTT:
430
 
                // TODO
431
 
                break;
432
 
            case LINE_CAP_ROUND:
433
 
            {
434
 
                // Add a circle at the line ends
435
 
                double lineAngle = atan2( startEndVector.y, startEndVector.x );
436
 
                drawSemiCircle( aStartPoint, m_lineWidth / 2, lineAngle + M_PI / 2 );
437
 
                drawSemiCircle( aEndPoint, m_lineWidth / 2, lineAngle - M_PI / 2 );
438
 
                break;
439
 
            }
440
 
            case LINE_CAP_SQUARED:
441
 
            {
442
 
                VECTOR2D offset;
443
 
                offset = startEndVector * ( m_lineWidth / lineLength / 2.0 );
444
 
                aStartPoint = aStartPoint - offset;
445
 
                aEndPoint = aEndPoint + offset;
446
 
                break;
447
 
            }
448
 
            }
 
505
        VECTOR2D startEndVector = aEndPoint - aStartPoint;
 
506
        double lineLength = startEndVector.EuclideanNorm();
 
507
        if( lineLength > 0.0 )
 
508
        {
 
509
            glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
510
            double lineAngle = atan2( startEndVector.y, startEndVector.x );
 
511
            drawLineCap( aStartPoint, aEndPoint, layerDepth );
 
512
            drawLineCap( aEndPoint, aStartPoint, layerDepth );
 
513
            drawLineQuad( aStartPoint, aEndPoint );
449
514
        }
450
515
    }
451
516
}
452
517
 
453
518
 
454
 
void OPENGL_GAL::DrawPolyline( POINTS& aPointList )
 
519
void OPENGL_GAL::DrawPolyline( POINTS2D& aPointList )
455
520
{
456
 
    LineCap savedLineCap = m_lineCap;
 
521
    LineCap savedLineCap = lineCap;
457
522
 
458
523
    bool isFirstPoint = true;
459
524
    bool isFirstLine = true;
460
 
 
461
 
    VECTOR2D startPoint;
 
525
    VECTOR2D startEndVector;
 
526
    VECTOR2D lastStartEndVector;
 
527
    VECTOR2D lastPoint;
462
528
 
463
529
    unsigned int i = 0;
464
530
 
465
531
    // Draw for each segment a line
466
 
    for( POINTS::const_iterator it = aPointList.begin(); it != aPointList.end(); it++)
 
532
    for( POINTS2D::const_iterator it = aPointList.begin(); it != aPointList.end(); it++ )
467
533
    {
468
 
        if( isFirstPoint)
 
534
        // First point
 
535
        if( it == aPointList.begin() )
469
536
        {
470
537
            isFirstPoint = false;
471
 
            startPoint = *it;
 
538
            lastPoint = *it;
472
539
        }
473
540
        else
474
541
        {
475
 
            if( !isFirstLine && ( i != aPointList.size() - 1 ))
476
 
            {
477
 
                switch (m_lineJoin)
 
542
            POINT2D actualPoint = *it;
 
543
            startEndVector = actualPoint - lastPoint;
 
544
 
 
545
            if( isFirstLine )
 
546
            {
 
547
                drawLineCap( lastPoint, actualPoint, layerDepth );
 
548
                isFirstLine = false;
 
549
            }
 
550
            else
 
551
            {
 
552
                // Compute some variables for the joints
 
553
                double lineLengthA = lastStartEndVector.EuclideanNorm();
 
554
                double scale = 0.5 * lineWidth / lineLengthA;
 
555
                VECTOR2D perpendicularVector1( -lastStartEndVector.y * scale,
 
556
                                               lastStartEndVector.x * scale );
 
557
                double lineLengthB = startEndVector.EuclideanNorm();
 
558
                scale = 0.5 * lineWidth / lineLengthB;
 
559
                VECTOR2D perpendicularVector2( -startEndVector.y * scale,
 
560
                                               startEndVector.x * scale );
 
561
 
 
562
                switch( lineJoin )
478
563
                {
479
 
                case LINE_JOIN_NONE:
480
 
                    break;
481
564
                case LINE_JOIN_ROUND:
482
 
                    m_lineCap = LINE_CAP_ROUND;
483
 
                    break;
 
565
                {
 
566
                    // Insert a triangle fan at the line joint
 
567
                    // Compute the start and end angle for the triangle fan
 
568
                    double angle1 = startEndVector.Angle();
 
569
                    double angle2 = lastStartEndVector.Angle();
 
570
                    double angleDiff = angle1 - angle2;
 
571
                    // Determines the side of the triangle fan
 
572
                    double adjust = angleDiff < 0 ? -0.5 * lineWidth : 0.5 * lineWidth;
 
573
 
 
574
                    // Angle correction for some special cases
 
575
                    if( angleDiff < -M_PI )
 
576
                    {
 
577
                        if( angle1 < 0 )
 
578
                        {
 
579
                            angle1 += 2 * M_PI;
 
580
                        }
 
581
                        if( angle2 < 0 )
 
582
                        {
 
583
                            angle2 += 2 * M_PI;
 
584
                        }
 
585
                        adjust = -adjust;
 
586
                    }
 
587
                    else if( angleDiff > M_PI )
 
588
                    {
 
589
                        if( angle1 > 0 )
 
590
                        {
 
591
                            angle1 -= 2 * M_PI;
 
592
 
 
593
                        }
 
594
                        if( angle2 > 0 )
 
595
                        {
 
596
                            angle2 -= 2 * M_PI;
 
597
                        }
 
598
                        adjust = -adjust;
 
599
                    }
 
600
 
 
601
                    // Now draw the fan
 
602
                    glBegin( GL_TRIANGLE_FAN );
 
603
                    glVertex3d( lastPoint.x, lastPoint.y, layerDepth );
 
604
 
 
605
                    SWAP( angle1, >, angle2 );
 
606
 
 
607
                    glVertex3d( lastPoint.x + adjust * sin( angle1 ),
 
608
                                lastPoint.y - adjust * cos( angle1 ), layerDepth );
 
609
                    for( double a = angle1 + M_PI / 32; a < angle2; a += M_PI / 32 )
 
610
                    {
 
611
                        glVertex3d( lastPoint.x + adjust * sin( a ),
 
612
                                    lastPoint.y - adjust * cos( a ), layerDepth );
 
613
                    }
 
614
                    glVertex3d( lastPoint.x + adjust * sin( angle2 ),
 
615
                                lastPoint.y - adjust * cos( angle2 ), layerDepth );
 
616
 
 
617
                    glEnd();
 
618
                    break;
 
619
                }
 
620
                case LINE_JOIN_BEVEL:
 
621
                {
 
622
                    // We compute the edge points of the line segments at the joint
 
623
                    POINT2D edgePoint1;
 
624
                    POINT2D edgePoint2;
 
625
                    // Determine the correct side
 
626
                    if( lastStartEndVector.x * startEndVector.y
 
627
                        - lastStartEndVector.y * startEndVector.x
 
628
                        < 0 )
 
629
                    {
 
630
                        edgePoint1 = lastPoint + perpendicularVector1;
 
631
                        edgePoint2 = lastPoint + perpendicularVector2;
 
632
                    }
 
633
                    else
 
634
                    {
 
635
                        edgePoint1 = lastPoint - perpendicularVector1;
 
636
                        edgePoint2 = lastPoint - perpendicularVector2;
 
637
                    }
 
638
 
 
639
                    // Insert a triangle at the joint to close the gap
 
640
                    glBegin( GL_TRIANGLES );
 
641
                    glVertex3d( edgePoint1.x, edgePoint1.y, layerDepth );
 
642
                    glVertex3d( edgePoint2.x, edgePoint2.y, layerDepth );
 
643
                    glVertex3d( lastPoint.x, lastPoint.y, layerDepth );
 
644
                    glEnd();
 
645
 
 
646
                    break;
 
647
                }
484
648
                case LINE_JOIN_MITER:
485
 
                    // TODO
486
 
                    break;
487
 
                case LINE_JOIN_BEVEL:
488
 
                    // TODO
489
 
                    break;
 
649
                {
 
650
                    // Compute points of the outer edges
 
651
                    POINT2D point1 = lastPoint - perpendicularVector1;
 
652
                    POINT2D point3 = lastPoint - perpendicularVector2;
 
653
                    if( lastStartEndVector.x * startEndVector.y
 
654
                        - lastStartEndVector.y * startEndVector.x
 
655
                        < 0 )
 
656
                    {
 
657
                        point1 = lastPoint + perpendicularVector1;
 
658
                        point3 = lastPoint + perpendicularVector2;
 
659
 
 
660
                    }
 
661
 
 
662
                    POINT2D point2 = point1 - lastStartEndVector;
 
663
                    POINT2D point4 = point3 + startEndVector;
 
664
 
 
665
                    // Now compute the intersection point of the edges
 
666
                    double c1 = point1 ^ point2;
 
667
                    double c2 = point3 ^ point4;
 
668
                    double quot = startEndVector ^ lastStartEndVector;
 
669
 
 
670
                    POINT2D miterPoint( -c1 * startEndVector.x - c2 * lastStartEndVector.x,
 
671
                                        -c1 * startEndVector.y - c2 * lastStartEndVector.y );
 
672
 
 
673
                    miterPoint = ( 1 / quot ) * miterPoint;
 
674
 
 
675
                    // Check if the point is outside the limit
 
676
                    if( ( lastPoint - miterPoint ).EuclideanNorm() > 2 * lineWidth )
 
677
                    {
 
678
                        // if it's outside cut the edge and insert three triangles
 
679
                        double limit = MITER_LIMIT * lineWidth;
 
680
                        POINT2D mp1 = point1 + ( limit / lineLengthA ) * lastStartEndVector;
 
681
                        POINT2D mp2 = point3 - ( limit / lineLengthB ) * startEndVector;
 
682
                        glBegin( GL_TRIANGLE_FAN );
 
683
                        glVertex3d( lastPoint.x, lastPoint.y, layerDepth );
 
684
                        glVertex3d( point1.x, point1.y, layerDepth );
 
685
                        glVertex3d( mp1.x, mp1.y, layerDepth );
 
686
                        glVertex3d( mp2.x, mp2.y, layerDepth );
 
687
                        glVertex3d( point3.x, point3.y, layerDepth );
 
688
                        glEnd();
 
689
                    }
 
690
                    else
 
691
                    {
 
692
                        // Insert two triangles for the mitered edge
 
693
                        glBegin( GL_TRIANGLE_FAN );
 
694
                        glVertex3d( lastPoint.x, lastPoint.y, layerDepth );
 
695
                        glVertex3d( point1.x, point1.y, layerDepth );
 
696
                        glVertex3d( miterPoint.x, miterPoint.y, layerDepth );
 
697
                        glVertex3d( point3.x, point3.y, layerDepth );
 
698
                        glEnd();
 
699
                    }
 
700
                    break;
 
701
                }
490
702
                }
491
703
            }
492
 
            else
 
704
 
 
705
            if( it == aPointList.end() - 1 )
493
706
            {
494
 
                m_lineCap = savedLineCap;
495
 
                isFirstLine = false;
 
707
                drawLineCap( actualPoint, lastPoint, layerDepth );
496
708
            }
497
709
 
498
 
            DrawLine( startPoint, *it );
499
 
 
500
 
            startPoint = *it;
 
710
            drawLineQuad( lastPoint, *it );
 
711
            lastPoint = *it;
 
712
            lastStartEndVector = startEndVector;
501
713
        }
502
714
 
503
715
        i++;
504
716
    }
505
717
 
506
 
    m_lineCap = savedLineCap;
 
718
    lineCap = savedLineCap;
507
719
}
508
720
 
509
721
 
515
727
 
516
728
    glPushMatrix();
517
729
 
518
 
    glTranslated( 0, 0, m_layerDepth );
 
730
    glTranslated( 0, 0, layerDepth );
519
731
 
520
732
    // Stroke the outline
521
 
    if( m_isStrokeEnabled)
 
733
    if( isStrokeEnabled )
522
734
    {
523
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
524
 
        DrawLine( aStartPoint, diagonalPointA );
525
 
        DrawLine( diagonalPointA, aEndPoint );
526
 
        DrawLine( aEndPoint, diagonalPointB );
527
 
        DrawLine( diagonalPointB, aStartPoint );
 
735
        glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
736
        std::deque<VECTOR2D> pointList;
 
737
        pointList.push_back( aStartPoint );
 
738
        pointList.push_back( diagonalPointA );
 
739
        pointList.push_back( aEndPoint );
 
740
        pointList.push_back( diagonalPointB );
 
741
        pointList.push_back( aStartPoint );
 
742
        DrawPolyline( pointList );
528
743
    }
529
744
 
530
745
    // Fill the rectangle
531
 
    if( m_isFillEnabled)
 
746
    if( isFillEnabled )
532
747
    {
533
 
        glColor4d( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
 
748
        glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
534
749
        glBegin( GL_QUADS );
535
750
        glVertex2d( aStartPoint.x, aStartPoint.y );
536
751
        glVertex2d( diagonalPointA.x, diagonalPointA.y );
542
757
    glPopMatrix();
543
758
 
544
759
    // Restore the stroke color
545
 
    glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
 
760
    glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
546
761
}
547
762
 
548
763
 
549
764
void OPENGL_GAL::DrawCircle( VECTOR2D aCenterPoint, double aRadius )
550
765
{
 
766
    // We need a minimum radius, else simply don't draw the circle
551
767
    if( aRadius <= 0.0 )
552
768
    {
553
769
        return;
554
770
    }
555
771
 
556
 
    if( m_isUseShaders )
557
 
    {
558
 
        glDepthFunc( GL_LEQUAL );
559
 
        glBlendFunc( GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR );
560
 
        glBlendColor( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
561
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
562
 
        // Now we enable the shader program for the circle
563
 
        // the shader requires the screensize as uniform argument
564
 
        m_shaderList[0].Use();
565
 
        m_shaderList[0].SetParameter( 0, m_screenSize.x / 2 );
566
 
        m_shaderList[0].SetParameter( 1, m_screenSize.y / 2 );
567
 
        glBegin( GL_LINES );
568
 
        glVertex3d( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
569
 
        glVertex3d( 0, aRadius, 0 );
570
 
        glEnd();
571
 
        m_shaderList[0].Deactivate();
572
 
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
573
 
        glDepthFunc( GL_LESS );
574
 
    }
575
 
    else
576
 
    {
577
 
        double outerScale = m_lineWidth / aRadius / 2;
 
772
    switch( m_drawMode )
 
773
    {
 
774
    // Draw the middle of the circle (not anti-aliased)
 
775
    case DRAW_MODE_NORMAL:
 
776
    {
 
777
        // Compute the factors for the unit circle
 
778
        double outerScale = lineWidth / aRadius / 2;
578
779
        double innerScale = -outerScale;
579
780
        outerScale += 1.0;
580
781
        innerScale += 1.0;
581
 
 
582
 
        if( m_isStrokeEnabled )
583
 
        {
584
 
            // Draw the outline
585
 
 
586
 
            glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
587
 
 
588
 
            glPushMatrix();
589
 
 
590
 
            glTranslated( aCenterPoint.x, aCenterPoint.y, 0.0 );
591
 
            glScaled( aRadius, aRadius, 1.0 );
592
 
 
593
 
            glBegin( GL_QUAD_STRIP );
594
 
            for( POINTS::const_iterator it = m_unitCirclePoints.begin();
595
 
                 it != m_unitCirclePoints.end(); it++ )
 
782
        if( isUseShader )
 
783
        {
 
784
            innerScale *= 1.0 / cos( M_PI / CIRCLE_POINTS );
 
785
        }
 
786
        if( isStrokeEnabled )
 
787
        {
 
788
            if( innerScale < outerScale )
596
789
            {
597
 
                glVertex2d( it->x * innerScale, it->y * innerScale );
598
 
                glVertex2d( it->x * outerScale, it->y * outerScale );
 
790
                // Draw the outline
 
791
                glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
792
 
 
793
                glPushMatrix();
 
794
 
 
795
                glTranslated( aCenterPoint.x, aCenterPoint.y, 0.0 );
 
796
                glScaled( aRadius, aRadius, 1.0 );
 
797
 
 
798
                glBegin( GL_QUAD_STRIP );
 
799
                for( POINTS2D::const_iterator it = unitCirclePoints.begin();
 
800
                        it != unitCirclePoints.end(); it++ )
 
801
                {
 
802
                    glVertex3d( it->x * innerScale, it->y * innerScale, layerDepth );
 
803
                    glVertex3d( it->x * outerScale, it->y * outerScale, layerDepth );
 
804
                }
 
805
                glEnd();
 
806
 
 
807
                glPopMatrix();
599
808
            }
600
 
            glEnd();
601
 
 
602
 
            glPopMatrix();
603
809
        }
604
810
 
605
811
        // Filled circles are easy to draw by using the stored display list, scaling and translating
606
 
        if( m_isFillEnabled )
 
812
        if( isFillEnabled )
607
813
        {
608
 
            glColor4d( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
 
814
            glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
609
815
 
610
816
            glPushMatrix();
611
817
 
612
 
            glTranslated( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
 
818
            glTranslated( aCenterPoint.x, aCenterPoint.y, layerDepth );
613
819
            glScaled( aRadius, aRadius, 1.0 );
614
820
 
615
821
            glBegin( GL_TRIANGLE_FAN );
616
 
            glVertex2d( 0, 0 );
617
 
            glCallList( m_displayListCircle );
 
822
            glVertex3d( 0, 0, 0 );
 
823
            glCallList( displayListCircle );
618
824
            glEnd();
619
825
 
620
826
            glPopMatrix();
621
827
        }
622
828
 
623
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
 
829
        glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
830
    }
 
831
        break;
 
832
 
 
833
        // Prepare / draw anti-aliased edges
 
834
    case DRAW_MODE_PREPARE_EDGES:
 
835
    case DRAW_MODE_DRAW_EDGES:
 
836
        if( isUseShader )
 
837
        {
 
838
            // Set the color
 
839
            // Now we enable the shader program for the circle
 
840
            // the shader requires the screen size as uniform argument
 
841
            shaderList[0].Use();
 
842
            shaderList[0].SetParameter( 0, screenSize.x / 2 );
 
843
            shaderList[0].SetParameter( 1, screenSize.y / 2 );
 
844
            glBegin( GL_LINES );
 
845
            if( isStrokeEnabled )
 
846
            {
 
847
                glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
848
                glVertex3d( aCenterPoint.x, aCenterPoint.y, layerDepth );
 
849
                glVertex3d( aRadius - lineWidth / 2, aRadius + lineWidth / 2, 0 );
 
850
            }
 
851
            else
 
852
            {
 
853
                glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
 
854
                glVertex3d( aCenterPoint.x, aCenterPoint.y, layerDepth );
 
855
                glVertex3d( 0, aRadius, 0 );
 
856
            }
 
857
            glEnd();
 
858
            shaderList[0].Deactivate();
 
859
        }
 
860
        break;
 
861
    default:
 
862
        break;
624
863
    }
625
864
}
626
865
 
627
866
 
628
867
// This method is used for round line caps
629
 
void OPENGL_GAL::drawSemiCircle( VECTOR2D aCenterPoint, double aRadius, double aAngle )
 
868
void OPENGL_GAL::drawSemiCircle( VECTOR2D aCenterPoint, double aRadius, double aAngle,
 
869
                                 double aDepthOffset )
630
870
{
631
 
        glPushMatrix();
632
 
        glTranslated(aCenterPoint.x, aCenterPoint.y, m_layerDepth);
633
 
        glScaled(aRadius, aRadius, 1.0);
634
 
        glRotated(aAngle * 360.0 / (2 * M_PI), 0, 0, 1);
635
 
 
636
 
        glBegin(GL_TRIANGLE_FAN);
637
 
        glVertex2d(0, 0);
638
 
        glCallList(m_displayListSemiCircle);
639
 
        glEnd();
640
 
 
641
 
        glPopMatrix();
 
871
    // XXX Depth seems to be buggy
 
872
    glPushMatrix();
 
873
    glTranslated( aCenterPoint.x, aCenterPoint.y, aDepthOffset );
 
874
    glScaled( aRadius, aRadius, 1.0 );
 
875
    glRotated( aAngle * 360.0 / ( 2 * M_PI ), 0, 0, 1 );
 
876
 
 
877
    glBegin( GL_TRIANGLE_FAN );
 
878
    glCallList( displayListSemiCircle );
 
879
    glEnd();
 
880
 
 
881
    glPopMatrix();
642
882
}
643
883
 
644
884
 
645
885
// FIXME Optimize
646
886
void OPENGL_GAL::DrawArc( VECTOR2D aCenterPoint, double aRadius, double aStartAngle,
647
 
        double aEndAngle )
 
887
                          double aEndAngle )
648
888
{
649
 
    if( aRadius <= 0)
 
889
    if( aRadius <= 0 )
 
890
    {
650
891
        return;
 
892
    }
651
893
 
652
 
    double outerScale = m_lineWidth / aRadius / 2;
 
894
    double outerScale = lineWidth / aRadius / 2;
653
895
    double innerScale = -outerScale;
654
896
 
655
897
    outerScale += 1.0;
656
898
    innerScale += 1.0;
657
899
 
658
900
    // Swap the angles, if start angle is greater than end angle
659
 
    SWAP(aStartAngle, >, aEndAngle);
660
 
 
661
 
    glPushMatrix();
662
 
 
663
 
    glTranslated( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
664
 
    glScaled( aRadius, aRadius, 1.0 );
 
901
    SWAP( aStartAngle, >, aEndAngle );
665
902
 
666
903
    VECTOR2D startPoint( cos( aStartAngle ), sin( aStartAngle ) );
667
904
    VECTOR2D endPoint( cos( aEndAngle ), sin( aEndAngle ) );
668
905
    VECTOR2D startEndPoint = startPoint + endPoint;
669
906
    VECTOR2D middlePoint = 0.5 * startEndPoint;
670
907
 
671
 
    if( m_isStrokeEnabled)
 
908
    glPushMatrix();
 
909
    glTranslated( aCenterPoint.x, aCenterPoint.y, layerDepth );
 
910
    glScaled( aRadius, aRadius, 1.0 );
 
911
 
 
912
    if( isStrokeEnabled )
672
913
    {
673
 
        glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
 
914
        glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
674
915
 
675
916
        glBegin( GL_QUAD_STRIP );
676
917
 
677
918
        double alphaIncrement = 2 * M_PI / CIRCLE_POINTS;
678
 
        for( double alpha = aStartAngle; alpha < aEndAngle; alpha += alphaIncrement)
 
919
        for( double alpha = aStartAngle; alpha < aEndAngle; alpha += alphaIncrement )
679
920
        {
680
921
            glVertex2d( cos( alpha ) * innerScale, sin( alpha ) * innerScale );
681
922
            glVertex2d( cos( alpha ) * outerScale, sin( alpha ) * outerScale );
686
927
 
687
928
        glEnd();
688
929
 
689
 
        if( m_lineCap == LINE_CAP_ROUND)
 
930
        if( lineCap == LINE_CAP_ROUND )
690
931
        {
691
 
            drawSemiCircle( startPoint, m_lineWidth / aRadius / 2, aStartAngle + M_PI );
692
 
            drawSemiCircle( endPoint, m_lineWidth / aRadius / 2, aEndAngle );
 
932
            drawSemiCircle( startPoint, lineWidth / aRadius / 2, aStartAngle + M_PI, 0 );
 
933
            drawSemiCircle( endPoint, lineWidth / aRadius / 2, aEndAngle, 0 );
693
934
        }
694
935
    }
695
936
 
696
 
    if( m_isFillEnabled)
 
937
    if( isFillEnabled )
697
938
    {
698
 
        glColor4d( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
 
939
        glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
699
940
 
700
941
        glBegin( GL_TRIANGLE_FAN );
701
942
 
702
943
        glVertex2d( middlePoint.x, middlePoint.y );
703
944
 
704
945
        double alphaIncrement = 2 * M_PI / CIRCLE_POINTS;
705
 
        for( double alpha = aStartAngle; alpha < aEndAngle; alpha += alphaIncrement)
 
946
        for( double alpha = aStartAngle; alpha < aEndAngle; alpha += alphaIncrement )
706
947
        {
707
948
            glVertex2d( cos( alpha ), sin( alpha ) );
708
949
        }
710
951
        glVertex2d( endPoint.x, endPoint.y );
711
952
 
712
953
        glEnd();
 
954
 
713
955
    }
714
956
 
715
957
    glPopMatrix();
719
961
struct OGLPOINT
720
962
{
721
963
    OGLPOINT() :
722
 
        x( 0.0 ),
723
 
        y( 0.0 ),
724
 
        z( 0.0 )
725
 
    {}
 
964
            x( 0.0 ), y( 0.0 ), z( 0.0 )
 
965
    {
 
966
    }
726
967
 
727
968
    OGLPOINT( const char* fastest )
728
969
    {
730
971
    }
731
972
 
732
973
    OGLPOINT( const VECTOR2D& aPoint ) :
733
 
        x( aPoint.x ),
734
 
        y( aPoint.y ),
735
 
        z( 0.0 )
 
974
            x( aPoint.x ), y( aPoint.y ), z( 0.0 )
736
975
    {
737
976
    }
738
977
 
744
983
        return *this;
745
984
    }
746
985
 
747
 
    GLdouble    x;
748
 
    GLdouble    y;
749
 
    GLdouble    z;
 
986
    GLdouble x;
 
987
    GLdouble y;
 
988
    GLdouble z;
750
989
};
751
990
 
752
991
 
753
 
void OPENGL_GAL::DrawPolygon( const POINTS& aPointList )
 
992
void OPENGL_GAL::DrawPolygon( const POINTS2D& aPointList )
754
993
{
755
994
    // Any non convex polygon needs to be tesselated
756
995
    // for this purpose the GLU standard functions are used
757
996
 
758
997
    GLUtesselator* tesselator = gluNewTess();
759
998
 
760
 
    typedef std::vector<OGLPOINT>   OGLPOINTS;
 
999
    typedef std::vector<OGLPOINT> OGLPOINTS;
761
1000
 
762
1001
    // Do only one heap allocation, can do because we know size in advance.
763
1002
    // std::vector is then fastest
768
1007
    gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
769
1008
 
770
1009
    glNormal3d( 0.0, 0.0, 1.0 );
771
 
    glColor4d( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
 
1010
    glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
772
1011
 
773
1012
    glShadeModel( GL_FLAT );
774
1013
    gluTessBeginPolygon( tesselator, NULL );
791
1030
}
792
1031
 
793
1032
 
794
 
void OPENGL_GAL::DrawCurve( VECTOR2D startPoint, VECTOR2D controlPointA, VECTOR2D controlPointB,
795
 
        VECTOR2D endPoint )
 
1033
void OPENGL_GAL::DrawCurve( VECTOR2D aStartPoint, VECTOR2D aControlPointA, VECTOR2D aControlPointB,
 
1034
                            VECTOR2D aEndPoint )
796
1035
{
797
1036
    // FIXME The drawing quality needs to be improved
798
1037
    // FIXME Perhaps choose a quad/triangle strip instead?
801
1040
    std::deque<VECTOR2D> pointList;
802
1041
 
803
1042
    double t = 0.0;
804
 
    double dt = 1.0 / (double) CURVE_POINTS;
 
1043
    double dt = 1.0 / (double)CURVE_POINTS;
805
1044
 
806
1045
    for( int i = 0; i <= CURVE_POINTS; i++ )
807
1046
    {
811
1050
        double t2 = t * t;
812
1051
        double t3 = t * t2;
813
1052
 
814
 
        VECTOR2D vertex = omt3 * startPoint + 3.0 * t * omt2 * controlPointA + 3.0 * t2 * omt
815
 
                * controlPointB + t3 * endPoint;
 
1053
        VECTOR2D vertex = omt3 * aStartPoint + 3.0 * t * omt2 * aControlPointA
 
1054
                          + 3.0 * t2 * omt * aControlPointB + t3 * aEndPoint;
816
1055
 
817
 
        pointList.push_back(vertex);
 
1056
        pointList.push_back( vertex );
818
1057
 
819
1058
        t += dt;
820
1059
    }
825
1064
 
826
1065
void OPENGL_GAL::SetStrokeColor( COLOR4D aColor )
827
1066
{
828
 
    if( m_strokeColor != aColor )
 
1067
    if( strokeColor != aColor )
829
1068
    {
830
 
        m_isSetAttributes = true;
831
 
        m_strokeColor = aColor;
 
1069
        isSetAttributes = true;
 
1070
        strokeColor = aColor;
832
1071
 
833
1072
        // This is the default drawing color
834
1073
        glColor4d( aColor.r, aColor.g, aColor.b, aColor.a );
835
1074
    }
836
1075
}
837
1076
 
 
1077
 
838
1078
void OPENGL_GAL::SetFillColor( COLOR4D aColor )
839
1079
{
840
 
    if( m_fillColor != aColor )
 
1080
    if( fillColor != aColor )
841
1081
    {
842
 
        m_isSetAttributes = true;
843
 
        m_fillColor = aColor;
 
1082
        isSetAttributes = true;
 
1083
        fillColor = aColor;
844
1084
    }
845
1085
}
846
1086
 
847
1087
 
848
1088
void OPENGL_GAL::SetBackgroundColor( COLOR4D aColor )
849
1089
{
850
 
    if( m_backgroundColor != aColor )
 
1090
    if( backgroundColor != aColor )
851
1091
    {
852
 
        m_isSetAttributes = true;
853
 
        m_backgroundColor = aColor;
 
1092
        isSetAttributes = true;
 
1093
        backgroundColor = aColor;
854
1094
    }
855
1095
}
856
1096
 
857
1097
 
858
1098
void OPENGL_GAL::SetLineWidth( double aLineWidth )
859
1099
{
860
 
    if( m_lineWidth != aLineWidth )
 
1100
    if( lineWidth != aLineWidth )
861
1101
    {
862
 
        m_isSetAttributes = true;
863
 
        m_lineWidth = aLineWidth;
 
1102
        isSetAttributes = true;
 
1103
        lineWidth = aLineWidth;
864
1104
    }
865
1105
}
866
1106
 
868
1108
void OPENGL_GAL::ClearScreen()
869
1109
{
870
1110
    // Clear screen
871
 
    glClearColor( m_backgroundColor.r, m_backgroundColor.g, m_backgroundColor.b,
872
 
            m_backgroundColor.a );
 
1111
    glClearColor( backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a );
873
1112
 
874
 
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
1113
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
875
1114
}
876
1115
 
877
1116
 
878
1117
void OPENGL_GAL::Transform( MATRIX3x3D aTransformation )
879
1118
{
880
 
    GLdouble matrixData[16] =
881
 
    { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
 
1119
    GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
882
1120
 
883
1121
    matrixData[0] = aTransformation.m_data[0][0];
884
1122
    matrixData[1] = aTransformation.m_data[1][0];
934
1172
// TODO Error handling
935
1173
int OPENGL_GAL::BeginGroup()
936
1174
{
 
1175
    isGroupStarted = true;
937
1176
    GLint displayList = glGenLists( 1 );
938
1177
    glNewList( displayList, GL_COMPILE );
939
 
    m_displayListsGroup.push_back( displayList );
 
1178
    displayListsGroup.push_back( displayList );
940
1179
 
941
 
    return (int) displayList;
 
1180
    return (int)displayList;
942
1181
}
943
1182
 
944
1183
 
945
1184
void OPENGL_GAL::EndGroup()
946
1185
{
 
1186
    isGroupStarted = false;
947
1187
    glEndList();
948
 
    glCallList( m_displayListsGroup.back() );
 
1188
    glCallList( displayListsGroup.back() );
949
1189
}
950
1190
 
951
1191
 
952
1192
void OPENGL_GAL::DeleteGroup( int aGroupNumber )
953
1193
{
954
 
    std::deque<GLuint>::iterator it = m_displayListsGroup.begin();
 
1194
    std::deque<GLuint>::iterator it = displayListsGroup.begin();
955
1195
    std::advance( it, aGroupNumber );
956
 
    m_displayListsGroup.erase( it );
 
1196
    displayListsGroup.erase( it );
957
1197
 
958
 
    glDeleteLists( (GLint) aGroupNumber, 1 );
 
1198
    glDeleteLists( (GLint)aGroupNumber, 1 );
959
1199
}
960
1200
 
961
1201
 
962
1202
void OPENGL_GAL::DrawGroup( int aGroupNumber )
963
1203
{
964
 
    glCallList( (GLint) aGroupNumber );
965
 
}
966
 
 
967
 
 
968
 
// FIXME Missing grid lines at high zoom steps
969
 
void OPENGL_GAL::DrawGrid()
970
 
{
971
 
    VECTOR2D    screenStartPoint( 0, 0 );
972
 
    VECTOR2D    screenEndPoint = m_screenSize;
973
 
    MATRIX3x3D  inverseMatrix  = m_worldScreenMatrix.Inverse();
974
 
 
975
 
    VECTOR2D    worldStartPoint = inverseMatrix * screenStartPoint;
976
 
    VECTOR2D    worldEndPoint   = inverseMatrix * screenEndPoint;
977
 
 
978
 
    // Compute grid variables
979
 
    double      gridStartX = round( worldStartPoint.x / m_gridSize.x );
980
 
    double      gridEndX   = round( worldEndPoint.x / m_gridSize.x );
981
 
    double      gridStartY = round( worldStartPoint.y / m_gridSize.y );
982
 
    double      gridEndY   = round( worldEndPoint.y / m_gridSize.y );
983
 
 
984
 
    // TODO use macro
985
 
    if( gridEndX < gridStartX )
986
 
    {
987
 
        double tmp = gridEndX;
988
 
        gridEndX = gridStartX;
989
 
        gridStartX = tmp;
990
 
    }
991
 
 
992
 
    if( gridEndY < gridStartY)
993
 
    {
994
 
        double tmp = gridEndY;
995
 
        gridEndY = gridStartY;
996
 
        gridStartY = tmp;
997
 
    }
998
 
 
999
 
    // Correct the index, else some lines are not correctly painted
1000
 
    gridStartX -= 1;
1001
 
    gridStartY -= 1;
1002
 
 
1003
 
    gridEndX += 1;
1004
 
    gridEndY += 1;
1005
 
 
1006
 
    glPushMatrix();
1007
 
 
1008
 
    // TODO Grid color configurable
1009
 
    glColor4d( 1, 1, 1, 0.1 );
1010
 
 
1011
 
    // TODO Grid distance
1012
 
    glTranslated( 0, 0, m_layerDepth );
1013
 
 
1014
 
    glBegin( GL_QUADS );
1015
 
 
1016
 
    double offset = 1.0 / m_zoomFactor / m_worldScale / 2;
1017
 
 
1018
 
    for( double j = gridStartY - 1; j < gridEndY + 1; j += 1)
1019
 
    {
1020
 
        glVertex2d( gridStartX * m_gridSize.x, j * m_gridSize.y - offset );
1021
 
        glVertex2d( gridStartX * m_gridSize.x, j * m_gridSize.y + offset );
1022
 
        glVertex2d( gridEndX * m_gridSize.x, j * m_gridSize.y + offset );
1023
 
        glVertex2d( gridEndX * m_gridSize.x, j * m_gridSize.y - offset );
1024
 
    }
1025
 
 
1026
 
    for( double i = gridStartX - 1; i < gridEndX + 1; i += 1)
1027
 
    {
1028
 
        glVertex2d( i * m_gridSize.x - offset, gridStartY * m_gridSize.y );
1029
 
        glVertex2d( i * m_gridSize.x + offset, gridStartY * m_gridSize.y );
1030
 
        glVertex2d( i * m_gridSize.x + offset, gridEndY * m_gridSize.y );
1031
 
        glVertex2d( i * m_gridSize.x - offset, gridEndY * m_gridSize.y );
1032
 
    }
1033
 
    glEnd();
1034
 
    glPopMatrix();
 
1204
    glCallList( (GLint)aGroupNumber );
1035
1205
}
1036
1206
 
1037
1207
 
1038
1208
void OPENGL_GAL::computeUnitArcs()
1039
1209
{
1040
 
    m_displayListsArcs = glGenLists( CIRCLE_POINTS + 1 );
 
1210
    displayListsArcs = glGenLists( CIRCLE_POINTS + 1 );
1041
1211
 
1042
1212
    // Create an individual display list for each arc in with an angle [0 .. 2pi]
1043
 
    for( int j = 0; j < CIRCLE_POINTS + 1; j++)
 
1213
    for( int j = 0; j < CIRCLE_POINTS + 1; j++ )
1044
1214
    {
1045
 
        glNewList( m_displayListsArcs + j, GL_COMPILE );
 
1215
        glNewList( displayListsArcs + j, GL_COMPILE );
1046
1216
 
1047
 
        for( int i = 0; i < j; i++)
 
1217
        for( int i = 0; i < j; i++ )
1048
1218
        {
1049
1219
            glVertex2d( cos( 2 * M_PI / CIRCLE_POINTS * i ), sin( 2 * M_PI / CIRCLE_POINTS * i ) );
1050
1220
        }
1056
1226
 
1057
1227
void OPENGL_GAL::computeUnitCircle()
1058
1228
{
1059
 
    m_displayListCircle = glGenLists( 1 );
1060
 
    glNewList( m_displayListCircle, GL_COMPILE );
 
1229
    displayListCircle = glGenLists( 1 );
 
1230
    glNewList( displayListCircle, GL_COMPILE );
1061
1231
 
1062
1232
    // Compute the circle points for a given number of segments
1063
1233
    // Insert in a display list and a vector
1064
 
    for( int i = 0; i < CIRCLE_POINTS + 1; i++)
 
1234
    for( int i = 0; i < CIRCLE_POINTS + 1; i++ )
1065
1235
    {
1066
1236
        double valueX = cos( 2 * M_PI / CIRCLE_POINTS * i );
1067
1237
        double valueY = sin( 2 * M_PI / CIRCLE_POINTS * i );
1068
 
        glVertex2d( valueX, valueY );
1069
 
        m_unitCirclePoints.push_back( VECTOR2D( valueX, valueY ) );
 
1238
        glVertex3d( valueX, valueY, 0 );
 
1239
        unitCirclePoints.push_back( VECTOR2D( valueX, valueY ) );
1070
1240
    }
1071
1241
 
1072
1242
    glEndList();
1075
1245
 
1076
1246
void OPENGL_GAL::computeUnitSemiCircle()
1077
1247
{
1078
 
    m_displayListSemiCircle = glGenLists( 1 );
1079
 
    glNewList( m_displayListSemiCircle, GL_COMPILE );
 
1248
    displayListSemiCircle = glGenLists( 1 );
 
1249
    glNewList( displayListSemiCircle, GL_COMPILE );
1080
1250
 
1081
 
    for( int i = 0; i < CIRCLE_POINTS / 2 + 1; i++)
 
1251
    for( int i = 0; i < CIRCLE_POINTS / 2 + 1; i++ )
1082
1252
    {
1083
 
        glVertex2d( cos( 2 * M_PI / CIRCLE_POINTS * i ), sin( 2 * M_PI / CIRCLE_POINTS * i ) );
 
1253
        glVertex3d( cos( 2 * M_PI / CIRCLE_POINTS * i ), sin( 2 * M_PI / CIRCLE_POINTS * i ), 0 );
1084
1254
    }
1085
1255
 
1086
1256
    glEndList();
1091
1261
{
1092
1262
    ComputeWorldScale();
1093
1263
 
1094
 
    m_worldScreenMatrix.SetIdentity();
 
1264
    worldScreenMatrix.SetIdentity();
1095
1265
 
1096
1266
    MATRIX3x3D translation;
1097
1267
    translation.SetIdentity();
1098
 
    translation.SetTranslation( 0.5 * m_screenSize );
 
1268
    translation.SetTranslation( 0.5 * screenSize );
1099
1269
 
1100
1270
    MATRIX3x3D scale;
1101
1271
    scale.SetIdentity();
1102
 
    scale.SetScale( VECTOR2D( m_worldScale, m_worldScale ) );
1103
 
 
1104
 
    MATRIX3x3D zoom;
1105
 
    zoom.SetIdentity();
1106
 
    zoom.SetScale( VECTOR2D( m_zoomFactor, m_zoomFactor ) );
 
1272
    scale.SetScale( VECTOR2D( worldScale, worldScale ) );
1107
1273
 
1108
1274
    MATRIX3x3D flip;
1109
1275
    flip.SetIdentity();
1111
1277
 
1112
1278
    MATRIX3x3D lookat;
1113
1279
    lookat.SetIdentity();
1114
 
    lookat.SetTranslation( -m_lookAtPoint );
 
1280
    lookat.SetTranslation( -lookAtPoint );
1115
1281
 
1116
 
    m_worldScreenMatrix = translation * flip * scale * zoom * lookat * m_worldScreenMatrix;
 
1282
    worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix;
1117
1283
}
1118
1284
 
1119
1285
// -------------------------------------
1122
1288
 
1123
1289
// Compare Redbook Chapter 11
1124
1290
 
 
1291
 
1125
1292
void CALLBACK VertexCallback( GLvoid *aVertexPtr )
1126
1293
{
1127
 
    GLdouble* vertex = (GLdouble*) aVertexPtr;
 
1294
    GLdouble* vertex = (GLdouble*)aVertexPtr;
1128
1295
    glVertex3dv( vertex );
1129
1296
}
1130
1297
 
1146
1313
    const GLubyte *estring;
1147
1314
 
1148
1315
    estring = gluErrorString( aErrorCode );
1149
 
    cout << "Tessellation Error: " << (char*) estring << endl;
 
1316
    cout << "Tessellation Error: " << (char*)estring << endl;
1150
1317
}
1151
1318
 
1152
1319
 
1153
1320
void InitTesselatorCallbacks( GLUtesselator* aTesselator )
1154
1321
{
1155
 
    gluTessCallback( aTesselator, GLU_TESS_VERTEX, (void(CALLBACK*)()) VertexCallback );
1156
 
    gluTessCallback( aTesselator, GLU_TESS_BEGIN, (void(CALLBACK*)()) BeginCallback );
 
1322
    gluTessCallback( aTesselator, GLU_TESS_VERTEX, (void (CALLBACK*)()) VertexCallback );
 
1323
    gluTessCallback(aTesselator, GLU_TESS_BEGIN, (void(CALLBACK*)()) BeginCallback );
1157
1324
    gluTessCallback( aTesselator, GLU_TESS_END, (void(CALLBACK*)()) EndCallback );
1158
1325
    gluTessCallback( aTesselator, GLU_TESS_ERROR, (void(CALLBACK*)()) ErrorCallback );
1159
1326
}
1160
1327
 
 
1328
 
1161
1329
// ---------------
1162
1330
// Cursor handling
1163
1331
// ---------------
1164
1332
 
 
1333
 
1165
1334
void OPENGL_GAL::initCursor( int aCursorSize )
1166
1335
{
1167
 
    m_cursorSize = aCursorSize;
 
1336
    cursorSize = aCursorSize;
1168
1337
}
1169
1338
 
1170
1339
 
1171
 
VECTOR2D OPENGL_GAL::ComputeCursorToWorld( VECTOR2D aCursorPosition )
 
1340
POINT2D OPENGL_GAL::ComputeCursorToWorld( POINT2D aCursorPosition )
1172
1341
{
1173
 
    aCursorPosition.y = m_screenSize.y - aCursorPosition.y;
1174
 
    MATRIX3x3D inverseMatrix = m_worldScreenMatrix.Inverse();
1175
 
    VECTOR2D cursorPositionWorld = inverseMatrix * aCursorPosition;
 
1342
    aCursorPosition.y = screenSize.y - aCursorPosition.y;
 
1343
    MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse();
 
1344
    POINT2D cursorPositionWorld = inverseMatrix * aCursorPosition;
1176
1345
 
1177
1346
    return cursorPositionWorld;
1178
1347
}
1180
1349
 
1181
1350
void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition )
1182
1351
{
1183
 
    SetCurrent( *m_glContext );
 
1352
    SetCurrent( *glContext );
1184
1353
 
1185
1354
    // Draw the cursor on the surface
1186
1355
    VECTOR2D cursorPositionWorld = ComputeCursorToWorld( aCursorPosition );
1187
1356
 
1188
 
    cursorPositionWorld.x = round( cursorPositionWorld.x / m_gridSize.x ) * m_gridSize.x;
1189
 
    cursorPositionWorld.y = round( cursorPositionWorld.y / m_gridSize.y ) * m_gridSize.y;
 
1357
    cursorPositionWorld.x = round( cursorPositionWorld.x / gridSize.x ) * gridSize.x;
 
1358
    cursorPositionWorld.y = round( cursorPositionWorld.y / gridSize.y ) * gridSize.y;
1190
1359
 
1191
 
    aCursorPosition = m_worldScreenMatrix * cursorPositionWorld;
 
1360
    aCursorPosition = worldScreenMatrix * cursorPositionWorld;
1192
1361
 
1193
1362
    // Switch to the main frame buffer and blit the scene
1194
1363
    glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
1199
1368
    blitMainTexture( false );
1200
1369
 
1201
1370
    glDisable( GL_TEXTURE_2D );
1202
 
    glColor4d( 1.0, 1.0, 1.0, 1.0 );
1203
 
    glLineWidth(1.0);
1204
 
 
1205
 
    glBegin( GL_LINES );
1206
 
 
1207
 
    glVertex3f( (int) ( aCursorPosition.x - m_cursorSize / 2 ) + 0.5,
1208
 
                (int) ( aCursorPosition.y ) + 0.5, 1 );
1209
 
 
1210
 
    glVertex3f( (int) ( aCursorPosition.x + m_cursorSize / 2 ) + 0.5,
1211
 
                (int) ( aCursorPosition.y ) + 0.5, 1 );
1212
 
 
1213
 
    glVertex3f( (int) ( aCursorPosition.x ) + 0.5,
1214
 
                (int) ( aCursorPosition.y - m_cursorSize / 2 ) + 0.5, 1 );
1215
 
 
1216
 
    glVertex3f( (int) ( aCursorPosition.x ) + 0.5,
1217
 
                (int) ( aCursorPosition.y + m_cursorSize / 2 ) + 0.5, 1 );
 
1371
    glColor4d( cursorColor.r, cursorColor.g, cursorColor.b, cursorColor.a );
 
1372
 
 
1373
    glBegin( GL_QUADS );
 
1374
 
 
1375
    glVertex3f( (int)( aCursorPosition.x - cursorSize / 2 ) + 1,
 
1376
                (int)( aCursorPosition.y ), depthRange.x );
 
1377
 
 
1378
    glVertex3f( (int)( aCursorPosition.x + cursorSize / 2 ) + 1,
 
1379
                (int)( aCursorPosition.y ), depthRange.x );
 
1380
 
 
1381
    glVertex3f( (int)( aCursorPosition.x + cursorSize / 2 ) + 1,
 
1382
                (int)( aCursorPosition.y + 1 ), depthRange.x );
 
1383
 
 
1384
    glVertex3f( (int)( aCursorPosition.x - cursorSize / 2 ) + 1,
 
1385
                (int)( aCursorPosition.y + 1), depthRange.x );
 
1386
 
 
1387
    glVertex3f( (int)( aCursorPosition.x ),
 
1388
                (int)( aCursorPosition.y - cursorSize / 2 ) + 1, depthRange.x );
 
1389
 
 
1390
    glVertex3f( (int)( aCursorPosition.x  ),
 
1391
                (int)( aCursorPosition.y + cursorSize / 2 ) + 1, depthRange.x );
 
1392
 
 
1393
    glVertex3f( (int)( aCursorPosition.x  ) + 1,
 
1394
                (int)( aCursorPosition.y + cursorSize / 2 ) + 1, depthRange.x );
 
1395
 
 
1396
    glVertex3f( (int)( aCursorPosition.x ) + 1,
 
1397
                (int)( aCursorPosition.y - cursorSize / 2 ) + 1, depthRange.x );
1218
1398
    glEnd();
1219
1399
 
1220
1400
    // Blit the current screen contents
1221
1401
    SwapBuffers();
1222
1402
}
1223
1403
 
 
1404
 
 
1405
void OPENGL_GAL::DrawGridLine( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
 
1406
{
 
1407
    // We check, if we got a horizontal or a vertical grid line and compute the offset
 
1408
    VECTOR2D perpendicularVector;
 
1409
    if( aStartPoint.x == aEndPoint.x )
 
1410
    {
 
1411
        perpendicularVector = VECTOR2D( 0.5 * lineWidth, 0 );
 
1412
    }
 
1413
    else
 
1414
    {
 
1415
        perpendicularVector = VECTOR2D( 0, 0.5 * lineWidth );
 
1416
    }
 
1417
 
 
1418
    // Now we compute the edge points of the quad
 
1419
    VECTOR2D point1 = aStartPoint + perpendicularVector;
 
1420
    VECTOR2D point2 = aStartPoint - perpendicularVector;
 
1421
    VECTOR2D point3 = aEndPoint + perpendicularVector;
 
1422
    VECTOR2D point4 = aEndPoint - perpendicularVector;
 
1423
 
 
1424
    // Set color
 
1425
    glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
 
1426
 
 
1427
    // Draw the quad for the grid line
 
1428
    glBegin( GL_QUADS );
 
1429
    double gridDepth = depthRange.y * 0.75;
 
1430
    glVertex3d( point1.x, point1.y, gridDepth );
 
1431
    glVertex3d( point2.x, point2.y, gridDepth );
 
1432
    glVertex3d( point4.x, point4.y, gridDepth );
 
1433
    glVertex3d( point3.x, point3.y, gridDepth );
 
1434
    glEnd();
 
1435
}