131
144
void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent )
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 );
148
wxPostEvent( mouseListener, aEvent );
139
void OPENGL_GAL::initFrameBuffer()
152
void OPENGL_GAL::generateFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer,
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
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 );
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 );
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,
168
glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, screenSize.x,
158
170
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
160
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
172
glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
173
GL_RENDERBUFFER_EXT, *aDepthBuffer );
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 );
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,
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 )
179
190
cerr << "Can't create the frame buffer." << endl;
183
m_isFrameBufferInitialized = true;
194
isFrameBufferInitialized = true;
198
void OPENGL_GAL::deleteFrameBuffer( GLuint* aFrameBuffer, GLuint* aDepthBuffer, GLuint* aTexture )
200
glDeleteFramebuffers( 1, aFrameBuffer );
201
glDeleteRenderbuffers( 1, aDepthBuffer );
202
glDeleteTextures( 1, aTexture );
206
void OPENGL_GAL::initFrameBuffers()
208
generateFrameBuffer( &frameBuffer, &depthBuffer, &texture );
209
generateFrameBuffer( &frameBufferBackup, &depthBufferBackup, &textureBackup );
213
void OPENGL_GAL::SaveScreen()
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,
220
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, frameBuffer );
224
void OPENGL_GAL::RestoreScreen()
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,
219
268
computeUnitSemiCircle();
220
269
computeUnitArcs();
222
m_isGlewInitialized = true;
271
isGlewInitialized = true;
226
275
void OPENGL_GAL::BeginDrawing()
228
SetCurrent( *m_glContext );
277
SetCurrent( *glContext );
230
m_clientDC = new wxClientDC( this );
279
clientDC = new wxClientDC( this );
232
281
// Initialize GLEW & FBOs
233
if( !m_isGlewInitialized )
282
if( !isGlewInitialized )
238
if( !m_isFrameBufferInitialized )
287
if( !isFrameBufferInitialized )
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());
250
m_shaderList[i].ConfigureGeometryShader(256, GL_LINES, GL_QUAD_STRIP);
253
m_shaderList[i].ConfigureGeometryShader(256, GL_TRIANGLES, GL_QUADS);
255
m_shaderList[i].AddSource( prefix + shaderNames[i] + string(".frag"),
256
SHADER_TYPE_FRAGMENT);
257
m_shaderList[i].AddSource( prefix + shaderNames[i] + string(".vert"),
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"));
265
m_isShaderInitialized = true;
293
if( !isShaderInitialized && isUseShader )
295
string shaderNames[SHADER_NUMBER] = { string( "circle" ), string( "line" ) };
296
string prefix = string( "../../../gal/opengl/shader/" );
297
for( int i = 0; i < 2; i++ )
299
shaderList.push_back( SHADER() );
302
shaderList[i].ConfigureGeometryShader( 256, GL_LINES, GL_QUAD_STRIP );
306
shaderList[i].ConfigureGeometryShader( 256, GL_LINES, GL_QUADS );
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" ) );
319
isShaderInitialized = true;
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 );
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 );
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 );
294
346
glMatrixMode( GL_MODELVIEW );
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 );
312
SetFillColor( m_fillColor );
313
SetStrokeColor( m_strokeColor );
314
m_isDeleteSavedPixels = true;
363
SetFillColor( fillColor );
364
SetStrokeColor( strokeColor );
365
isDeleteSavedPixels = true;
362
413
blitMainTexture( true );
420
inline void OPENGL_GAL::drawLineQuad( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
422
VECTOR2D startEndVector = aEndPoint - aStartPoint;
423
double lineLength = startEndVector.EuclideanNorm();
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 )
435
VECTOR2D perpendicularVector( -startEndVector.y * scale, startEndVector.x * scale );
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;
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 );
452
inline void OPENGL_GAL::drawLineCap( POINT2D aStartPoint, POINT2D aEndPoint, double aDepthOffset )
454
VECTOR2D startEndVector = aEndPoint - aStartPoint;
455
double lineLength = startEndVector.EuclideanNorm();
456
double lineAngle = atan2( startEndVector.y, startEndVector.x );
465
// Add a semicircle at the line end
466
drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2, aDepthOffset );
469
case LINE_CAP_SQUARED:
472
offset = startEndVector * ( lineWidth / lineLength / 2.0 );
473
aStartPoint = aStartPoint - offset;
474
aEndPoint = aEndPoint + offset;
369
482
void OPENGL_GAL::DrawLine( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
371
if ( false ) //m_isUseShaders )
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 );
487
shaderList[1].SetParameter( 0, screenSize.x / 2 );
488
shaderList[1].SetParameter( 1, screenSize.y / 2 );
490
glVertex3d( aStartPoint.x, aStartPoint.y, layerDepth );
491
glVertex3d( aEndPoint.x, aEndPoint.y, lineWidth );
385
m_shaderList[1].Deactivate();
493
shaderList[1].Deactivate();
494
bool saved = isFillEnabled;
495
COLOR4D savedColor = fillColor;
496
fillColor = strokeColor;
498
DrawCircle( aStartPoint, lineWidth / 2 );
499
DrawCircle( aEndPoint, lineWidth / 2 );
501
fillColor = savedColor;
388
VECTOR2D startEndVector = aEndPoint - aStartPoint;
389
double lineLength = startEndVector.EuclideanNorm();
390
if ( lineLength > 0.0 )
392
glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
394
if ( m_lineCap == LINE_CAP_SIMPLE )
396
// Use glLines for simple line drawing
397
glDepthMask( GL_FALSE );
398
glLineWidth( m_lineWidth );
400
glVertex3d( aStartPoint.x, aStartPoint.y, m_layerDepth );
401
glVertex3d( aEndPoint.x, aEndPoint.y, m_layerDepth );
403
glDepthMask( GL_TRUE );
407
// In this mode use a quad for drawing of the line
408
// For this purpose compute the edge points of the line
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;
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 );
426
case LINE_CAP_SIMPLE:
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 );
440
case LINE_CAP_SQUARED:
443
offset = startEndVector * ( m_lineWidth / lineLength / 2.0 );
444
aStartPoint = aStartPoint - offset;
445
aEndPoint = aEndPoint + offset;
505
VECTOR2D startEndVector = aEndPoint - aStartPoint;
506
double lineLength = startEndVector.EuclideanNorm();
507
if( lineLength > 0.0 )
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 );
454
void OPENGL_GAL::DrawPolyline( POINTS& aPointList )
519
void OPENGL_GAL::DrawPolyline( POINTS2D& aPointList )
456
LineCap savedLineCap = m_lineCap;
521
LineCap savedLineCap = lineCap;
458
523
bool isFirstPoint = true;
459
524
bool isFirstLine = true;
525
VECTOR2D startEndVector;
526
VECTOR2D lastStartEndVector;
463
529
unsigned int i = 0;
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++ )
535
if( it == aPointList.begin() )
470
537
isFirstPoint = false;
475
if( !isFirstLine && ( i != aPointList.size() - 1 ))
542
POINT2D actualPoint = *it;
543
startEndVector = actualPoint - lastPoint;
547
drawLineCap( lastPoint, actualPoint, layerDepth );
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 );
481
564
case LINE_JOIN_ROUND:
482
m_lineCap = LINE_CAP_ROUND;
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;
574
// Angle correction for some special cases
575
if( angleDiff < -M_PI )
587
else if( angleDiff > M_PI )
602
glBegin( GL_TRIANGLE_FAN );
603
glVertex3d( lastPoint.x, lastPoint.y, layerDepth );
605
SWAP( angle1, >, angle2 );
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 )
611
glVertex3d( lastPoint.x + adjust * sin( a ),
612
lastPoint.y - adjust * cos( a ), layerDepth );
614
glVertex3d( lastPoint.x + adjust * sin( angle2 ),
615
lastPoint.y - adjust * cos( angle2 ), layerDepth );
620
case LINE_JOIN_BEVEL:
622
// We compute the edge points of the line segments at the joint
625
// Determine the correct side
626
if( lastStartEndVector.x * startEndVector.y
627
- lastStartEndVector.y * startEndVector.x
630
edgePoint1 = lastPoint + perpendicularVector1;
631
edgePoint2 = lastPoint + perpendicularVector2;
635
edgePoint1 = lastPoint - perpendicularVector1;
636
edgePoint2 = lastPoint - perpendicularVector2;
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 );
484
648
case LINE_JOIN_MITER:
487
case LINE_JOIN_BEVEL:
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
657
point1 = lastPoint + perpendicularVector1;
658
point3 = lastPoint + perpendicularVector2;
662
POINT2D point2 = point1 - lastStartEndVector;
663
POINT2D point4 = point3 + startEndVector;
665
// Now compute the intersection point of the edges
666
double c1 = point1 ^ point2;
667
double c2 = point3 ^ point4;
668
double quot = startEndVector ^ lastStartEndVector;
670
POINT2D miterPoint( -c1 * startEndVector.x - c2 * lastStartEndVector.x,
671
-c1 * startEndVector.y - c2 * lastStartEndVector.y );
673
miterPoint = ( 1 / quot ) * miterPoint;
675
// Check if the point is outside the limit
676
if( ( lastPoint - miterPoint ).EuclideanNorm() > 2 * lineWidth )
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 );
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 );
705
if( it == aPointList.end() - 1 )
494
m_lineCap = savedLineCap;
707
drawLineCap( actualPoint, lastPoint, layerDepth );
498
DrawLine( startPoint, *it );
710
drawLineQuad( lastPoint, *it );
712
lastStartEndVector = startEndVector;
506
m_lineCap = savedLineCap;
718
lineCap = savedLineCap;
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 );
549
764
void OPENGL_GAL::DrawCircle( VECTOR2D aCenterPoint, double aRadius )
766
// We need a minimum radius, else simply don't draw the circle
551
767
if( aRadius <= 0.0 )
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 );
568
glVertex3d( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
569
glVertex3d( 0, aRadius, 0 );
571
m_shaderList[0].Deactivate();
572
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
573
glDepthFunc( GL_LESS );
577
double outerScale = m_lineWidth / aRadius / 2;
774
// Draw the middle of the circle (not anti-aliased)
775
case DRAW_MODE_NORMAL:
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;
582
if( m_isStrokeEnabled )
586
glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
590
glTranslated( aCenterPoint.x, aCenterPoint.y, 0.0 );
591
glScaled( aRadius, aRadius, 1.0 );
593
glBegin( GL_QUAD_STRIP );
594
for( POINTS::const_iterator it = m_unitCirclePoints.begin();
595
it != m_unitCirclePoints.end(); it++ )
784
innerScale *= 1.0 / cos( M_PI / CIRCLE_POINTS );
786
if( isStrokeEnabled )
788
if( innerScale < outerScale )
597
glVertex2d( it->x * innerScale, it->y * innerScale );
598
glVertex2d( it->x * outerScale, it->y * outerScale );
791
glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
795
glTranslated( aCenterPoint.x, aCenterPoint.y, 0.0 );
796
glScaled( aRadius, aRadius, 1.0 );
798
glBegin( GL_QUAD_STRIP );
799
for( POINTS2D::const_iterator it = unitCirclePoints.begin();
800
it != unitCirclePoints.end(); it++ )
802
glVertex3d( it->x * innerScale, it->y * innerScale, layerDepth );
803
glVertex3d( it->x * outerScale, it->y * outerScale, layerDepth );
605
811
// Filled circles are easy to draw by using the stored display list, scaling and translating
606
if( m_isFillEnabled )
608
glColor4d( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
814
glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
612
glTranslated( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
818
glTranslated( aCenterPoint.x, aCenterPoint.y, layerDepth );
613
819
glScaled( aRadius, aRadius, 1.0 );
615
821
glBegin( GL_TRIANGLE_FAN );
617
glCallList( m_displayListCircle );
822
glVertex3d( 0, 0, 0 );
823
glCallList( displayListCircle );
623
glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
829
glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
833
// Prepare / draw anti-aliased edges
834
case DRAW_MODE_PREPARE_EDGES:
835
case DRAW_MODE_DRAW_EDGES:
839
// Now we enable the shader program for the circle
840
// the shader requires the screen size as uniform argument
842
shaderList[0].SetParameter( 0, screenSize.x / 2 );
843
shaderList[0].SetParameter( 1, screenSize.y / 2 );
845
if( isStrokeEnabled )
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 );
853
glColor4d( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
854
glVertex3d( aCenterPoint.x, aCenterPoint.y, layerDepth );
855
glVertex3d( 0, aRadius, 0 );
858
shaderList[0].Deactivate();
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 )
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);
636
glBegin(GL_TRIANGLE_FAN);
638
glCallList(m_displayListSemiCircle);
871
// XXX Depth seems to be buggy
873
glTranslated( aCenterPoint.x, aCenterPoint.y, aDepthOffset );
874
glScaled( aRadius, aRadius, 1.0 );
875
glRotated( aAngle * 360.0 / ( 2 * M_PI ), 0, 0, 1 );
877
glBegin( GL_TRIANGLE_FAN );
878
glCallList( displayListSemiCircle );
645
885
// FIXME Optimize
646
886
void OPENGL_GAL::DrawArc( VECTOR2D aCenterPoint, double aRadius, double aStartAngle,
652
double outerScale = m_lineWidth / aRadius / 2;
894
double outerScale = lineWidth / aRadius / 2;
653
895
double innerScale = -outerScale;
655
897
outerScale += 1.0;
656
898
innerScale += 1.0;
658
900
// Swap the angles, if start angle is greater than end angle
659
SWAP(aStartAngle, >, aEndAngle);
663
glTranslated( aCenterPoint.x, aCenterPoint.y, m_layerDepth );
664
glScaled( aRadius, aRadius, 1.0 );
901
SWAP( aStartAngle, >, aEndAngle );
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;
671
if( m_isStrokeEnabled)
909
glTranslated( aCenterPoint.x, aCenterPoint.y, layerDepth );
910
glScaled( aRadius, aRadius, 1.0 );
912
if( isStrokeEnabled )
673
glColor4d( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
914
glColor4d( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
675
916
glBegin( GL_QUAD_STRIP );
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 )
680
921
glVertex2d( cos( alpha ) * innerScale, sin( alpha ) * innerScale );
681
922
glVertex2d( cos( alpha ) * outerScale, sin( alpha ) * outerScale );
934
1172
// TODO Error handling
935
1173
int OPENGL_GAL::BeginGroup()
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 );
941
return (int) displayList;
1180
return (int)displayList;
945
1184
void OPENGL_GAL::EndGroup()
1186
isGroupStarted = false;
948
glCallList( m_displayListsGroup.back() );
1188
glCallList( displayListsGroup.back() );
952
1192
void OPENGL_GAL::DeleteGroup( int aGroupNumber )
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 );
958
glDeleteLists( (GLint) aGroupNumber, 1 );
1198
glDeleteLists( (GLint)aGroupNumber, 1 );
962
1202
void OPENGL_GAL::DrawGroup( int aGroupNumber )
964
glCallList( (GLint) aGroupNumber );
968
// FIXME Missing grid lines at high zoom steps
969
void OPENGL_GAL::DrawGrid()
971
VECTOR2D screenStartPoint( 0, 0 );
972
VECTOR2D screenEndPoint = m_screenSize;
973
MATRIX3x3D inverseMatrix = m_worldScreenMatrix.Inverse();
975
VECTOR2D worldStartPoint = inverseMatrix * screenStartPoint;
976
VECTOR2D worldEndPoint = inverseMatrix * screenEndPoint;
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 );
985
if( gridEndX < gridStartX )
987
double tmp = gridEndX;
988
gridEndX = gridStartX;
992
if( gridEndY < gridStartY)
994
double tmp = gridEndY;
995
gridEndY = gridStartY;
999
// Correct the index, else some lines are not correctly painted
1008
// TODO Grid color configurable
1009
glColor4d( 1, 1, 1, 0.1 );
1011
// TODO Grid distance
1012
glTranslated( 0, 0, m_layerDepth );
1014
glBegin( GL_QUADS );
1016
double offset = 1.0 / m_zoomFactor / m_worldScale / 2;
1018
for( double j = gridStartY - 1; j < gridEndY + 1; j += 1)
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 );
1026
for( double i = gridStartX - 1; i < gridEndX + 1; i += 1)
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 );
1204
glCallList( (GLint)aGroupNumber );
1038
1208
void OPENGL_GAL::computeUnitArcs()
1040
m_displayListsArcs = glGenLists( CIRCLE_POINTS + 1 );
1210
displayListsArcs = glGenLists( CIRCLE_POINTS + 1 );
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++ )
1045
glNewList( m_displayListsArcs + j, GL_COMPILE );
1215
glNewList( displayListsArcs + j, GL_COMPILE );
1047
for( int i = 0; i < j; i++)
1217
for( int i = 0; i < j; i++ )
1049
1219
glVertex2d( cos( 2 * M_PI / CIRCLE_POINTS * i ), sin( 2 * M_PI / CIRCLE_POINTS * i ) );
1199
1368
blitMainTexture( false );
1201
1370
glDisable( GL_TEXTURE_2D );
1202
glColor4d( 1.0, 1.0, 1.0, 1.0 );
1205
glBegin( GL_LINES );
1207
glVertex3f( (int) ( aCursorPosition.x - m_cursorSize / 2 ) + 0.5,
1208
(int) ( aCursorPosition.y ) + 0.5, 1 );
1210
glVertex3f( (int) ( aCursorPosition.x + m_cursorSize / 2 ) + 0.5,
1211
(int) ( aCursorPosition.y ) + 0.5, 1 );
1213
glVertex3f( (int) ( aCursorPosition.x ) + 0.5,
1214
(int) ( aCursorPosition.y - m_cursorSize / 2 ) + 0.5, 1 );
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 );
1373
glBegin( GL_QUADS );
1375
glVertex3f( (int)( aCursorPosition.x - cursorSize / 2 ) + 1,
1376
(int)( aCursorPosition.y ), depthRange.x );
1378
glVertex3f( (int)( aCursorPosition.x + cursorSize / 2 ) + 1,
1379
(int)( aCursorPosition.y ), depthRange.x );
1381
glVertex3f( (int)( aCursorPosition.x + cursorSize / 2 ) + 1,
1382
(int)( aCursorPosition.y + 1 ), depthRange.x );
1384
glVertex3f( (int)( aCursorPosition.x - cursorSize / 2 ) + 1,
1385
(int)( aCursorPosition.y + 1), depthRange.x );
1387
glVertex3f( (int)( aCursorPosition.x ),
1388
(int)( aCursorPosition.y - cursorSize / 2 ) + 1, depthRange.x );
1390
glVertex3f( (int)( aCursorPosition.x ),
1391
(int)( aCursorPosition.y + cursorSize / 2 ) + 1, depthRange.x );
1393
glVertex3f( (int)( aCursorPosition.x ) + 1,
1394
(int)( aCursorPosition.y + cursorSize / 2 ) + 1, depthRange.x );
1396
glVertex3f( (int)( aCursorPosition.x ) + 1,
1397
(int)( aCursorPosition.y - cursorSize / 2 ) + 1, depthRange.x );
1220
1400
// Blit the current screen contents
1405
void OPENGL_GAL::DrawGridLine( VECTOR2D aStartPoint, VECTOR2D aEndPoint )
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 )
1411
perpendicularVector = VECTOR2D( 0.5 * lineWidth, 0 );
1415
perpendicularVector = VECTOR2D( 0, 0.5 * lineWidth );
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;
1425
glColor4d( gridColor.r, gridColor.g, gridColor.b, gridColor.a );
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 );