1 /*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Mario Luzeiro <mrluzeiro@ua.pt>
5 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25 #include "layer_triangles.h"
26 #include "../raytracing/ray.h"
27 #include <wx/debug.h> // For the wxASSERT
28 #include <mutex>
29
30
TRIANGLE_LIST(unsigned int aNrReservedTriangles,bool aReserveNormals)31 TRIANGLE_LIST::TRIANGLE_LIST( unsigned int aNrReservedTriangles, bool aReserveNormals )
32 {
33 wxASSERT( aNrReservedTriangles > 0 );
34
35 m_vertexs.clear();
36 m_normals.clear();
37
38 m_vertexs.reserve( aNrReservedTriangles * 3 );
39
40 if( aReserveNormals )
41 m_normals.reserve( aNrReservedTriangles * 3 );
42 }
43
44
Reserve_More(unsigned int aNrReservedTriangles,bool aReserveNormals)45 void TRIANGLE_LIST::Reserve_More( unsigned int aNrReservedTriangles, bool aReserveNormals )
46 {
47 m_vertexs.reserve( m_vertexs.size() + aNrReservedTriangles * 3 );
48
49 if( aReserveNormals )
50 m_normals.reserve( m_normals.size() + aNrReservedTriangles * 3 );
51 }
52
53
AddQuad(const SFVEC3F & aV1,const SFVEC3F & aV2,const SFVEC3F & aV3,const SFVEC3F & aV4)54 void TRIANGLE_LIST::AddQuad( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3,
55 const SFVEC3F& aV4 )
56 {
57 m_vertexs.push_back( aV1 );
58 m_vertexs.push_back( aV2 );
59 m_vertexs.push_back( aV3 );
60
61 m_vertexs.push_back( aV3 );
62 m_vertexs.push_back( aV4 );
63 m_vertexs.push_back( aV1 );
64 }
65
66
AddTriangle(const SFVEC3F & aV1,const SFVEC3F & aV2,const SFVEC3F & aV3)67 void TRIANGLE_LIST::AddTriangle( const SFVEC3F& aV1, const SFVEC3F& aV2, const SFVEC3F& aV3 )
68 {
69 m_vertexs.push_back( aV1 );
70 m_vertexs.push_back( aV2 );
71 m_vertexs.push_back( aV3 );
72 }
73
74
AddNormal(const SFVEC3F & aN1,const SFVEC3F & aN2,const SFVEC3F & aN3)75 void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3 )
76 {
77 m_normals.push_back( aN1 );
78 m_normals.push_back( aN2 );
79 m_normals.push_back( aN3 );
80 }
81
AddNormal(const SFVEC3F & aN1,const SFVEC3F & aN2,const SFVEC3F & aN3,const SFVEC3F & aN4)82 void TRIANGLE_LIST::AddNormal( const SFVEC3F& aN1, const SFVEC3F& aN2, const SFVEC3F& aN3,
83 const SFVEC3F& aN4 )
84 {
85 m_normals.push_back( aN1 );
86 m_normals.push_back( aN2 );
87 m_normals.push_back( aN3 );
88
89 m_normals.push_back( aN3 );
90 m_normals.push_back( aN4 );
91 m_normals.push_back( aN1 );
92 }
93
94
TRIANGLE_DISPLAY_LIST(unsigned int aNrReservedTriangles)95 TRIANGLE_DISPLAY_LIST::TRIANGLE_DISPLAY_LIST( unsigned int aNrReservedTriangles )
96 {
97 wxASSERT( aNrReservedTriangles > 0 );
98
99 m_layer_top_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false );
100 m_layer_top_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false );
101 m_layer_middle_contourns_quads = new TRIANGLE_LIST( aNrReservedTriangles, true );
102 m_layer_bot_triangles = new TRIANGLE_LIST( aNrReservedTriangles, false );
103 m_layer_bot_segment_ends = new TRIANGLE_LIST( aNrReservedTriangles, false );
104 }
105
106
~TRIANGLE_DISPLAY_LIST()107 TRIANGLE_DISPLAY_LIST::~TRIANGLE_DISPLAY_LIST()
108 {
109 delete m_layer_top_segment_ends;
110 m_layer_top_segment_ends = nullptr;
111
112 delete m_layer_top_triangles;
113 m_layer_top_triangles = nullptr;
114
115 delete m_layer_middle_contourns_quads;
116 m_layer_middle_contourns_quads = nullptr;
117
118 delete m_layer_bot_triangles;
119 m_layer_bot_triangles = nullptr;
120
121 delete m_layer_bot_segment_ends;
122 m_layer_bot_segment_ends = nullptr;
123 }
124
125
AddToMiddleContourns(const std::vector<SFVEC2F> & aContournPoints,float zBot,float zTop,bool aInvertFaceDirection,const BVH_CONTAINER_2D * aThroughHoles)126 void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const std::vector< SFVEC2F >& aContournPoints,
127 float zBot, float zTop, bool aInvertFaceDirection,
128 const BVH_CONTAINER_2D* aThroughHoles )
129 {
130 if( aContournPoints.size() >= 4 )
131 {
132 // Calculate normals of each segment of the contourn
133 std::vector< SFVEC2F > contournNormals;
134
135 contournNormals.clear();
136 contournNormals.resize( aContournPoints.size() - 1 );
137
138 if( aInvertFaceDirection )
139 {
140 for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
141 {
142 const SFVEC2F& v0 = aContournPoints[i + 0];
143 const SFVEC2F& v1 = aContournPoints[i + 1];
144 const SFVEC2F n = glm::normalize( v1 - v0 );
145
146 contournNormals[i] = SFVEC2F( n.y,-n.x );
147 }
148 }
149 else
150 {
151 for( unsigned int i = 0; i < ( aContournPoints.size() - 1 ); ++i )
152 {
153 const SFVEC2F& v0 = aContournPoints[i + 0];
154 const SFVEC2F& v1 = aContournPoints[i + 1];
155 const SFVEC2F n = glm::normalize( v1 - v0 );
156
157 contournNormals[i] = SFVEC2F( -n.y, n.x );
158 }
159 }
160
161
162 if( aInvertFaceDirection )
163 std::swap( zBot, zTop );
164
165 const unsigned int nContournsToProcess = ( aContournPoints.size() - 1 );
166
167 for( unsigned int i = 0; i < nContournsToProcess; ++i )
168 {
169 SFVEC2F lastNormal;
170
171 if( i > 0 )
172 lastNormal = contournNormals[i - 1];
173 else
174 lastNormal = contournNormals[nContournsToProcess - 1];
175
176 SFVEC2F n0 = contournNormals[i];
177
178 // Only interpolate the normal if the angle is closer
179 if( glm::dot( n0, lastNormal ) > 0.5f )
180 n0 = glm::normalize( n0 + lastNormal );
181
182 SFVEC2F nextNormal;
183
184 if( i < (nContournsToProcess - 1) )
185 nextNormal = contournNormals[i + 1];
186 else
187 nextNormal = contournNormals[0];
188
189 SFVEC2F n1 = contournNormals[i];
190
191 if( glm::dot( n1, nextNormal ) > 0.5f )
192 n1 = glm::normalize( n1 + nextNormal );
193
194 const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f );
195 const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
196
197 const SFVEC2F& v0 = aContournPoints[i + 0];
198 const SFVEC2F& v1 = aContournPoints[i + 1];
199
200 if( aThroughHoles && aThroughHoles->IntersectAny( RAYSEG2D( v0, v1 ) ) )
201 {
202 continue;
203 }
204 else
205 {
206 std::lock_guard<std::mutex> lock( m_middle_layer_lock );
207 m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ),
208 SFVEC3F( v1.x, v1.y, zTop ),
209 SFVEC3F( v1.x, v1.y, zBot ),
210 SFVEC3F( v0.x, v0.y, zBot ) );
211
212 m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 );
213 }
214 }
215 }
216 }
217
218
AddToMiddleContourns(const SHAPE_LINE_CHAIN & outlinePath,float zBot,float zTop,double aBiuTo3Du,bool aInvertFaceDirection,const BVH_CONTAINER_2D * aThroughHoles)219 void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_LINE_CHAIN& outlinePath, float zBot,
220 float zTop, double aBiuTo3Du,
221 bool aInvertFaceDirection,
222 const BVH_CONTAINER_2D* aThroughHoles )
223 {
224 std::vector< SFVEC2F >contournPoints;
225
226 contournPoints.clear();
227 contournPoints.reserve( outlinePath.PointCount() + 2 );
228
229 const VECTOR2I& firstV = outlinePath.CPoint( 0 );
230
231 SFVEC2F lastV = SFVEC2F( firstV.x * aBiuTo3Du, -firstV.y * aBiuTo3Du );
232
233 contournPoints.push_back( lastV );
234
235 for( unsigned int i = 1; i < (unsigned int)outlinePath.PointCount(); ++i )
236 {
237 const VECTOR2I& v = outlinePath.CPoint( i );
238
239 const SFVEC2F vf = SFVEC2F( v.x * aBiuTo3Du, -v.y * aBiuTo3Du );
240
241 if( vf != lastV ) // Do not add repeated points
242 {
243 lastV = vf;
244 contournPoints.push_back( vf );
245 }
246 }
247
248 // Add first position fo the list to close the path
249 if( lastV != contournPoints[0] )
250 contournPoints.push_back( contournPoints[0] );
251
252 AddToMiddleContourns( contournPoints, zBot, zTop, aInvertFaceDirection, aThroughHoles );
253 }
254
255
AddToMiddleContourns(const SHAPE_POLY_SET & aPolySet,float zBot,float zTop,double aBiuTo3Du,bool aInvertFaceDirection,const BVH_CONTAINER_2D * aThroughHoles)256 void TRIANGLE_DISPLAY_LIST::AddToMiddleContourns( const SHAPE_POLY_SET& aPolySet, float zBot,
257 float zTop, double aBiuTo3Du,
258 bool aInvertFaceDirection,
259 const BVH_CONTAINER_2D* aThroughHoles )
260 {
261 if( aPolySet.OutlineCount() == 0 )
262 return;
263
264 // Calculate an estimation of points to reserve
265 unsigned int nrContournPointsToReserve = 0;
266
267 for( int i = 0; i < aPolySet.OutlineCount(); ++i )
268 {
269 const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
270
271 nrContournPointsToReserve += pathOutline.PointCount();
272
273 for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
274 {
275 const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h );
276
277 nrContournPointsToReserve += hole.PointCount();
278 }
279 }
280
281 // Request to reserve more space
282 m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2, true );
283
284 for( int i = 0; i < aPolySet.OutlineCount(); i++ )
285 {
286 // Add outline
287 const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
288
289 AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection,
290 aThroughHoles );
291
292 // Add holes for this outline
293 for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
294 {
295 const SHAPE_LINE_CHAIN& hole = aPolySet.CHole( i, h );
296 AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection,
297 aThroughHoles );
298 }
299 }
300 }
301
302
OPENGL_RENDER_LIST(const TRIANGLE_DISPLAY_LIST & aLayerTriangles,GLuint aTextureIndexForSegEnds,float aZBot,float aZTop)303 OPENGL_RENDER_LIST::OPENGL_RENDER_LIST( const TRIANGLE_DISPLAY_LIST& aLayerTriangles,
304 GLuint aTextureIndexForSegEnds,
305 float aZBot, float aZTop )
306 {
307 m_zBot = aZBot;
308 m_zTop = aZTop;
309
310 m_layer_top_segment_ends = 0;
311 m_layer_top_triangles = 0;
312 m_layer_middle_contourns_quads = 0;
313 m_layer_bot_triangles = 0;
314 m_layer_bot_segment_ends = 0;
315
316 if( aTextureIndexForSegEnds )
317 {
318 wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
319
320 if( glIsTexture( aTextureIndexForSegEnds ) )
321 {
322 m_layer_top_segment_ends =
323 generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends,
324 true, aTextureIndexForSegEnds );
325
326 m_layer_bot_segment_ends =
327 generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends,
328 false, aTextureIndexForSegEnds );
329 }
330 }
331
332 m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles,
333 true );
334
335 m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles,
336 false );
337
338
339 if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 )
340 {
341 m_layer_middle_contourns_quads =
342 generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads );
343 }
344
345 m_draw_it_transparent = false;
346 m_haveTransformation = false;
347 m_zPositionTransformation = 0.0f;
348 m_zScaleTransformation = 0.0f;
349 }
350
351
~OPENGL_RENDER_LIST()352 OPENGL_RENDER_LIST::~OPENGL_RENDER_LIST()
353 {
354 if( glIsList( m_layer_top_segment_ends ) )
355 glDeleteLists( m_layer_top_segment_ends, 1 );
356
357 if( glIsList( m_layer_top_triangles ) )
358 glDeleteLists( m_layer_top_triangles, 1 );
359
360 if( glIsList( m_layer_middle_contourns_quads ) )
361 glDeleteLists( m_layer_middle_contourns_quads, 1 );
362
363 if( glIsList( m_layer_bot_triangles ) )
364 glDeleteLists( m_layer_bot_triangles, 1 );
365
366 if( glIsList( m_layer_bot_segment_ends ) )
367 glDeleteLists( m_layer_bot_segment_ends, 1 );
368
369 m_layer_top_segment_ends = 0;
370 m_layer_top_triangles = 0;
371 m_layer_middle_contourns_quads = 0;
372 m_layer_bot_triangles = 0;
373 m_layer_bot_segment_ends = 0;
374 }
375
376
DrawTopAndMiddle() const377 void OPENGL_RENDER_LIST::DrawTopAndMiddle() const
378 {
379 beginTransformation();
380
381 if( glIsList( m_layer_middle_contourns_quads ) )
382 glCallList( m_layer_middle_contourns_quads );
383
384 if( glIsList( m_layer_top_triangles ) )
385 glCallList( m_layer_top_triangles );
386
387 if( glIsList( m_layer_top_segment_ends ) )
388 glCallList( m_layer_top_segment_ends );
389
390 endTransformation();
391 }
392
393
DrawBotAndMiddle() const394 void OPENGL_RENDER_LIST::DrawBotAndMiddle() const
395 {
396 beginTransformation();
397
398 if( glIsList( m_layer_middle_contourns_quads ) )
399 glCallList( m_layer_middle_contourns_quads );
400
401 if( glIsList( m_layer_bot_triangles ) )
402 glCallList( m_layer_bot_triangles );
403
404 if( glIsList( m_layer_bot_segment_ends ) )
405 glCallList( m_layer_bot_segment_ends );
406
407 endTransformation();
408 }
409
410
DrawTop() const411 void OPENGL_RENDER_LIST::DrawTop() const
412 {
413 beginTransformation();
414
415 if( glIsList( m_layer_top_triangles ) )
416 glCallList( m_layer_top_triangles );
417
418 if( glIsList( m_layer_top_segment_ends ) )
419 glCallList( m_layer_top_segment_ends );
420
421 endTransformation();
422 }
423
424
DrawBot() const425 void OPENGL_RENDER_LIST::DrawBot() const
426 {
427 beginTransformation();
428
429 if( glIsList( m_layer_bot_triangles ) )
430 glCallList( m_layer_bot_triangles );
431
432 if( glIsList( m_layer_bot_segment_ends ) )
433 glCallList( m_layer_bot_segment_ends );
434
435 endTransformation();
436 }
437
438
DrawMiddle() const439 void OPENGL_RENDER_LIST::DrawMiddle() const
440 {
441 beginTransformation();
442
443 if( glIsList( m_layer_middle_contourns_quads ) )
444 glCallList( m_layer_middle_contourns_quads );
445
446 endTransformation();
447 }
448
449
DrawAll(bool aDrawMiddle) const450 void OPENGL_RENDER_LIST::DrawAll( bool aDrawMiddle ) const
451 {
452 beginTransformation();
453
454 if( aDrawMiddle )
455 if( glIsList( m_layer_middle_contourns_quads ) )
456 glCallList( m_layer_middle_contourns_quads );
457
458 if( glIsList( m_layer_top_triangles ) )
459 glCallList( m_layer_top_triangles );
460
461 if( glIsList( m_layer_bot_triangles ) )
462 glCallList( m_layer_bot_triangles );
463
464 if( glIsList( m_layer_top_segment_ends ) )
465 glCallList( m_layer_top_segment_ends );
466
467 if( glIsList( m_layer_bot_segment_ends ) )
468 glCallList( m_layer_bot_segment_ends );
469
470 endTransformation();
471 }
472
473
DrawAllCameraCulled(float zCameraPos,bool aDrawMiddle) const474 void OPENGL_RENDER_LIST::DrawAllCameraCulled( float zCameraPos, bool aDrawMiddle ) const
475 {
476 zCameraPos = m_haveTransformation
477 ? ( ( zCameraPos - m_zPositionTransformation ) / m_zScaleTransformation )
478 : zCameraPos;
479
480 if( aDrawMiddle )
481 DrawMiddle();
482
483 if( zCameraPos > m_zTop )
484 {
485 DrawTop();
486 }
487 else
488 {
489 if( zCameraPos < m_zBot )
490 {
491 DrawBot();
492 }
493 else
494 {
495 // If camera is in the middle dont draw it.
496 }
497 }
498 }
499
500
DrawAllCameraCulledSubtractLayer(bool aDrawMiddle,const OPENGL_RENDER_LIST * aLayerToSubtractA,const OPENGL_RENDER_LIST * aLayerToSubtractB,const OPENGL_RENDER_LIST * aLayerToSubtractC,const OPENGL_RENDER_LIST * aLayerToSubtractD) const501 void OPENGL_RENDER_LIST::DrawAllCameraCulledSubtractLayer( bool aDrawMiddle,
502 const OPENGL_RENDER_LIST* aLayerToSubtractA,
503 const OPENGL_RENDER_LIST* aLayerToSubtractB,
504 const OPENGL_RENDER_LIST* aLayerToSubtractC,
505 const OPENGL_RENDER_LIST* aLayerToSubtractD ) const
506 {
507 glClearStencil( 0x00 );
508 glClear( GL_STENCIL_BUFFER_BIT );
509
510 glEnable( GL_CULL_FACE );
511 glCullFace( GL_BACK );
512
513 glDisable( GL_DEPTH_TEST );
514 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
515 glDepthMask( GL_FALSE );
516 glEnable( GL_STENCIL_TEST );
517 glStencilFunc( GL_ALWAYS, 1, 0 );
518 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
519
520 if( aLayerToSubtractA )
521 aLayerToSubtractA->DrawBot();
522
523 if( aLayerToSubtractB )
524 aLayerToSubtractB->DrawBot();
525
526 if( aLayerToSubtractC )
527 aLayerToSubtractC->DrawBot();
528
529 if( aLayerToSubtractD )
530 aLayerToSubtractD->DrawBot();
531
532 glEnable(GL_DEPTH_TEST);
533 glDepthMask(GL_TRUE);
534
535 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
536 glStencilFunc( GL_EQUAL, 0, 1 );
537 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
538 DrawBot();
539
540 glDisable( GL_DEPTH_TEST );
541 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
542 glDepthMask( GL_FALSE );
543 glEnable( GL_STENCIL_TEST );
544 glStencilFunc( GL_ALWAYS, 2, 0 );
545 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
546
547 if( aLayerToSubtractA )
548 aLayerToSubtractA->DrawTop();
549
550 if( aLayerToSubtractB )
551 aLayerToSubtractB->DrawTop();
552
553 if( aLayerToSubtractC )
554 aLayerToSubtractC->DrawTop();
555
556 if( aLayerToSubtractD )
557 aLayerToSubtractD->DrawTop();
558
559 glEnable(GL_DEPTH_TEST);
560 glDepthMask(GL_TRUE);
561 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
562 glStencilFunc( GL_NOTEQUAL, 2, 0x03 );
563 glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
564 DrawTop();
565
566 if( aDrawMiddle )
567 DrawMiddle();
568
569 glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
570
571 glCullFace( GL_FRONT );
572 glStencilFunc( GL_GEQUAL, 3, 0x03 );
573 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
574 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
575
576 if( aDrawMiddle )
577 {
578 if( aLayerToSubtractA )
579 aLayerToSubtractA->DrawMiddle();
580 }
581
582 glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
583
584 glCullFace( GL_BACK );
585 glDisable( GL_STENCIL_TEST );
586 }
587
588
ApplyScalePosition(float aZposition,float aZscale)589 void OPENGL_RENDER_LIST::ApplyScalePosition( float aZposition, float aZscale )
590 {
591 wxASSERT( aZscale > FLT_EPSILON );
592
593 m_zPositionTransformation = aZposition;
594 m_zScaleTransformation = aZscale;
595 m_haveTransformation = true;
596 }
597
598
SetItIsTransparent(bool aSetTransparent)599 void OPENGL_RENDER_LIST::SetItIsTransparent( bool aSetTransparent )
600 {
601 m_draw_it_transparent = aSetTransparent;
602 }
603
604
generate_top_or_bot_seg_ends(const TRIANGLE_LIST * aTriangleContainer,bool aIsNormalUp,GLuint aTextureId) const605 GLuint OPENGL_RENDER_LIST::generate_top_or_bot_seg_ends(
606 const TRIANGLE_LIST* aTriangleContainer, bool aIsNormalUp, GLuint aTextureId ) const
607 {
608 wxASSERT( aTriangleContainer != nullptr );
609
610 wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
611
612 // Top and Bot dont have normals array stored in container
613 wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
614
615 if( ( aTriangleContainer->GetVertexSize() > 0 )
616 && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) )
617 {
618 GLuint listIdx = glGenLists( 1 );
619
620 if( glIsList( listIdx ) )
621 {
622 // Prepare an array of UV text coordinates
623 SFVEC2F* uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()];
624
625 for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 )
626 {
627 uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f );
628 uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f );
629 uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f );
630 }
631
632 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
633 glDisableClientState( GL_COLOR_ARRAY );
634 glDisableClientState( GL_NORMAL_ARRAY );
635 glEnableClientState( GL_VERTEX_ARRAY );
636 glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
637 glTexCoordPointer( 2, GL_FLOAT, 0, uvArray );
638
639 glNewList( listIdx, GL_COMPILE );
640
641 glDisable( GL_COLOR_MATERIAL );
642
643 glEnable( GL_TEXTURE_2D );
644 glBindTexture( GL_TEXTURE_2D, aTextureId );
645
646 glAlphaFunc( GL_GREATER, 0.2f );
647 glEnable( GL_ALPHA_TEST );
648
649 glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
650
651 glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
652
653 glDisable( GL_TEXTURE_2D );
654 glDisable( GL_ALPHA_TEST );
655 glDisable( GL_BLEND );
656
657 glEndList();
658
659 glDisableClientState( GL_VERTEX_ARRAY );
660 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
661
662 delete [] uvArray;
663 return listIdx;
664 }
665 }
666
667 return 0;
668 }
669
670
generate_top_or_bot_triangles(const TRIANGLE_LIST * aTriangleContainer,bool aIsNormalUp) const671 GLuint OPENGL_RENDER_LIST::generate_top_or_bot_triangles( const TRIANGLE_LIST* aTriangleContainer,
672 bool aIsNormalUp ) const
673 {
674 wxASSERT( aTriangleContainer != nullptr );
675
676 wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
677
678 // Top and Bot dont have normals array stored in container
679 wxASSERT( aTriangleContainer->GetNormalsSize() == 0 );
680
681 if( ( aTriangleContainer->GetVertexSize() > 0 )
682 && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 ) )
683 {
684 const GLuint listIdx = glGenLists( 1 );
685
686 if( glIsList( listIdx ) )
687 {
688 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
689 glDisableClientState( GL_COLOR_ARRAY );
690 glDisableClientState( GL_NORMAL_ARRAY );
691 glEnableClientState( GL_VERTEX_ARRAY );
692 glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
693
694 glNewList( listIdx, GL_COMPILE );
695
696 setBlendfunction();
697
698 glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f );
699
700 glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
701
702 glDisable( GL_BLEND );
703 glEndList();
704
705 glDisableClientState( GL_VERTEX_ARRAY );
706
707 return listIdx;
708 }
709 }
710
711 return 0;
712 }
713
714
generate_middle_triangles(const TRIANGLE_LIST * aTriangleContainer) const715 GLuint OPENGL_RENDER_LIST::generate_middle_triangles(
716 const TRIANGLE_LIST* aTriangleContainer ) const
717 {
718 wxASSERT( aTriangleContainer != nullptr );
719
720 // We expect that it is a multiple of 3 vertex
721 wxASSERT( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 );
722
723 // We expect that it is a multiple of 6 vertex (because we expect to add quads)
724 wxASSERT( (aTriangleContainer->GetVertexSize() % 6 ) == 0 );
725
726 // We expect that there are normals with same size as vertex
727 wxASSERT( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() );
728
729 if( ( aTriangleContainer->GetVertexSize() > 0 )
730 && ( ( aTriangleContainer->GetVertexSize() % 3 ) == 0 )
731 && ( ( aTriangleContainer->GetVertexSize() % 6 ) == 0 )
732 && ( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) )
733 {
734 const GLuint listIdx = glGenLists( 1 );
735
736 if( glIsList( listIdx ) )
737 {
738 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
739 glDisableClientState( GL_COLOR_ARRAY );
740 glEnableClientState( GL_NORMAL_ARRAY );
741 glEnableClientState( GL_VERTEX_ARRAY );
742 glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() );
743 glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() );
744
745 glNewList( listIdx, GL_COMPILE );
746
747 setBlendfunction();
748
749 glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() );
750
751 glDisable( GL_BLEND );
752 glEndList();
753
754 glDisableClientState( GL_VERTEX_ARRAY );
755 glDisableClientState( GL_NORMAL_ARRAY );
756
757 return listIdx;
758 }
759 }
760
761 return 0;
762 }
763
764
endTransformation() const765 void OPENGL_RENDER_LIST::endTransformation() const
766 {
767 if( m_haveTransformation )
768 {
769 glPopMatrix();
770 }
771 }
772
773
setBlendfunction() const774 void OPENGL_RENDER_LIST::setBlendfunction() const
775 {
776 glEnable( GL_BLEND );
777 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
778 }
779
780
beginTransformation() const781 void OPENGL_RENDER_LIST::beginTransformation() const
782 {
783 if( m_haveTransformation )
784 {
785 glPushMatrix();
786 glTranslatef( 0.0f, 0.0f, m_zPositionTransformation );
787 glScalef( 1.0f, 1.0f, m_zScaleTransformation );
788 }
789 }
790