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