KiCad PCB EDA Suite
layer_triangles.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2016 Mario Luzeiro <[email protected]>
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 
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 
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 
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 
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 
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 
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 
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 
108 {
110  m_layer_top_segment_ends = nullptr;
111 
112  delete m_layer_top_triangles;
113  m_layer_top_triangles = nullptr;
114 
117 
118  delete m_layer_bot_triangles;
119  m_layer_bot_triangles = nullptr;
120 
122  m_layer_bot_segment_ends = nullptr;
123 }
124 
125 
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 
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 
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 
304  GLuint aTextureIndexForSegEnds,
305  float aZBot, float aZTop )
306 {
307  m_zBot = aZBot;
308  m_zTop = aZTop;
309 
315 
316  if( aTextureIndexForSegEnds )
317  {
318  wxASSERT( glIsTexture( aTextureIndexForSegEnds ) );
319 
320  if( glIsTexture( aTextureIndexForSegEnds ) )
321  {
324  true, aTextureIndexForSegEnds );
325 
328  false, aTextureIndexForSegEnds );
329  }
330  }
331 
333  true );
334 
336  false );
337 
338 
339  if( aLayerTriangles.m_layer_middle_contourns_quads->GetVertexSize() > 0 )
340  {
343  }
344 
345  m_draw_it_transparent = false;
346  m_haveTransformation = false;
348  m_zScaleTransformation = 0.0f;
349 }
350 
351 
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 
374 }
375 
376 
378 {
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 
391 }
392 
393 
395 {
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 
408 }
409 
410 
412 {
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 
422 }
423 
424 
426 {
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 
436 }
437 
438 
440 {
442 
443  if( glIsList( m_layer_middle_contourns_quads ) )
444  glCallList( m_layer_middle_contourns_quads );
445 
447 }
448 
449 
450 void OPENGL_RENDER_LIST::DrawAll( bool aDrawMiddle ) const
451 {
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 
471 }
472 
473 
474 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 
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 
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 
599 void OPENGL_RENDER_LIST::SetItIsTransparent( bool aSetTransparent )
600 {
601  m_draw_it_transparent = aSetTransparent;
602 }
603 
604 
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 
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 
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 
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 
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 
766 {
768  {
769  glPopMatrix();
770  }
771 }
772 
773 
775 {
776  glEnable( GL_BLEND );
777  glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
778 }
779 
780 
782 {
784  {
785  glPushMatrix();
786  glTranslatef( 0.0f, 0.0f, m_zPositionTransformation );
787  glScalef( 1.0f, 1.0f, m_zScaleTransformation );
788  }
789 }
Container to manage a vector of triangles.
TRIANGLE_LIST(unsigned int aNrReservedTriangles, bool aReserveNormals)
int OutlineCount() const
Return the number of vertices in a given outline/hole.
bool IntersectAny(const RAYSEG2D &aSegRay) const override
Intersect and check if a segment ray hits a object or is inside it.
unsigned int GetVertexSize() const
Store arrays of triangles to be used to create display lists.
void DrawBotAndMiddle() const
Call the display lists for the bottom elements and middle contours.
void DrawTop() const
Call the display lists for the top elements.
void DrawAllCameraCulledSubtractLayer(bool aDrawMiddle, const OPENGL_RENDER_LIST *aLayerToSubtractA=nullptr, const OPENGL_RENDER_LIST *aLayerToSubtractB=nullptr, const OPENGL_RENDER_LIST *aLayerToSubtractC=nullptr, const OPENGL_RENDER_LIST *aLayerToSubtractD=nullptr) const
void DrawAllCameraCulled(float zCameraPos, bool aDrawMiddle=true) const
Draw all layers if they are visible by the camera if camera position is above the layer.
std::mutex m_middle_layer_lock
void beginTransformation() const
TRIANGLE_LIST * m_layer_middle_contourns_quads
void DrawTopAndMiddle() const
Call the display lists for the top elements and middle contours.
void Reserve_More(unsigned int aNrReservedTriangles, bool aReserveNormals)
Reserve more triangles.
TRIANGLE_LIST * m_layer_top_triangles
TRIANGLE_DISPLAY_LIST(unsigned int aNrReservedTriangles)
Initialize arrays with reserved triangles.
void DrawMiddle() const
Call the display lists for the middle elements.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
int PointCount() const
Return the number of points (vertices) in this line chain.
void setBlendfunction() const
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
OPENGL_RENDER_LIST(const TRIANGLE_DISPLAY_LIST &aLayerTriangles, GLuint aTextureIndexForSegEnds, float aZBot, float aZTop)
Create the display lists for a layer.
const float * GetNormalsPointer() const
Get the array of normals.
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
unsigned int GetNormalsSize() const
Represent a set of closed polygons.
void AddQuad(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4)
void AddTriangle(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3)
void ApplyScalePosition(float aZposition, float aZscale)
void AddToMiddleContourns(const SHAPE_LINE_CHAIN &outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
TRIANGLE_LIST * m_layer_bot_triangles
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
void DrawAll(bool aDrawMiddle=true) const
Call to draw all the display lists.
SFVEC3F_VECTOR m_normals
normals array
Store the OpenGL display lists to related with a layer.
const float * GetVertexPointer() const
Get the array of vertices.
GLuint generate_top_or_bot_seg_ends(const TRIANGLE_LIST *aTriangleContainer, bool aIsNormalUp, GLuint aTextureId) const
void DrawBot() const
Call the display lists for the bottom elements.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
GLuint generate_middle_triangles(const TRIANGLE_LIST *aTriangleContainer) const
void SetItIsTransparent(bool aSetTransparent)
GLuint generate_top_or_bot_triangles(const TRIANGLE_LIST *aTriangleContainer, bool aIsNormalUp) const
TRIANGLE_LIST * m_layer_bot_segment_ends
GLuint m_layer_middle_contourns_quads
void endTransformation() const
~OPENGL_RENDER_LIST()
Destroy this class while free the display lists from GPU memory.
void AddNormal(const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3)
TRIANGLE_LIST * m_layer_top_segment_ends
SFVEC3F_VECTOR m_vertexs
vertex array
Definition: ray.h:105