KiCad PCB EDA Suite
c3d_render_createscene_ogl_legacy.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 <mrluzeiro@ua.pt>
5  * Copyright (C) 1992-2016 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 
30 #include "c3d_render_ogl_legacy.h"
31 #include "ogl_legacy_utils.h"
32 #include <board.h>
33 #include <footprint.h>
34 #include "../../3d_math.h"
35 #include "../../3d_fastmath.h"
36 #include <trigo.h>
37 #include <project.h>
38 #include <profile.h> // To use GetRunningMicroSecs or another profiling utility
39 
40 
42  CLAYER_TRIANGLES *aDstLayer,
43  float aZtop,
44  float aZbot )
45 {
46  const SFVEC2F &center = aFilledCircle->GetCenter();
47  const float radius = aFilledCircle->GetRadius() *
48  2.0f; // Double because the render triangle
49 
50  // This is a small adjustment to the circle texture
51  const float texture_factor = (8.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
52  const float f = (sqrtf(2.0f) / 2.0f) * radius * texture_factor;
53 
54  // Top and Bot segments ends are just triangle semi-circles, so need to add
55  // it in duplicated
56  aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ),
57  SFVEC3F( center.x - f, center.y, aZtop ),
58  SFVEC3F( center.x,
59  center.y - f, aZtop ) );
60 
61  aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZtop ),
62  SFVEC3F( center.x + f, center.y, aZtop ),
63  SFVEC3F( center.x,
64  center.y + f, aZtop ) );
65 
66  aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ),
67  SFVEC3F( center.x + f, center.y, aZbot ),
68  SFVEC3F( center.x,
69  center.y - f, aZbot ) );
70 
71  aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ),
72  SFVEC3F( center.x - f, center.y, aZbot ),
73  SFVEC3F( center.x,
74  center.y + f, aZbot ) );
75 }
76 
77 
79  CLAYER_TRIANGLES *aDstLayer,
80  float aZtop,
81  float aZbot )
82 {
83  const SFVEC2F &v0 = aPoly->GetV0();
84  const SFVEC2F &v1 = aPoly->GetV1();
85  const SFVEC2F &v2 = aPoly->GetV2();
86  const SFVEC2F &v3 = aPoly->GetV3();
87 
88  add_triangle_top_bot( aDstLayer, v0, v2, v1, aZtop, aZbot );
89  add_triangle_top_bot( aDstLayer, v2, v0, v3, aZtop, aZbot );
90 }
91 
92 
94  float aInnerRadius,
95  float aOuterRadius,
96  unsigned int aNr_sides_per_circle,
97  std::vector< SFVEC2F > &aInnerContourResult,
98  std::vector< SFVEC2F > &aOuterContourResult,
99  bool aInvertOrder )
100 {
101  aInnerContourResult.clear();
102  aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
103 
104  aOuterContourResult.clear();
105  aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
106 
107  const int delta = 3600 / aNr_sides_per_circle;
108 
109  for( int ii = 0; ii < 3600; ii += delta )
110  {
111  float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
112  * 2.0f * glm::pi<float>() / 3600.0f;
113  const SFVEC2F rotatedDir = SFVEC2F( cos( angle ), sin( angle ) );
114 
115  aInnerContourResult.emplace_back( aCenter.x + rotatedDir.x * aInnerRadius,
116  aCenter.y + rotatedDir.y * aInnerRadius );
117 
118  aOuterContourResult.emplace_back( aCenter.x + rotatedDir.x * aOuterRadius,
119  aCenter.y + rotatedDir.y * aOuterRadius );
120  }
121 
122  aInnerContourResult.push_back( aInnerContourResult[0] );
123  aOuterContourResult.push_back( aOuterContourResult[0] );
124 
125  wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
126 }
127 
128 
130  CLAYER_TRIANGLES *aDstLayer,
131  float aZtop,
132  float aZbot )
133 {
134  const SFVEC2F &center = aRing->GetCenter();
135  const float inner = aRing->GetInnerRadius();
136  const float outer = aRing->GetOuterRadius();
137 
138  std::vector< SFVEC2F > innerContour;
139  std::vector< SFVEC2F > outerContour;
140 
141  generate_ring_contour( center,
142  inner,
143  outer,
144  m_boardAdapter.GetNrSegmentsCircle( outer * 2.0f ),
145  innerContour,
146  outerContour,
147  false );
148 
149  // This will add the top and bot quads that will form the approximated ring
150 
151  for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
152  {
153  const SFVEC2F &vi0 = innerContour[i + 0];
154  const SFVEC2F &vi1 = innerContour[i + 1];
155  const SFVEC2F &vo0 = outerContour[i + 0];
156  const SFVEC2F &vo1 = outerContour[i + 1];
157 
158  aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
159  SFVEC3F( vi0.x, vi0.y, aZtop ),
160  SFVEC3F( vo0.x, vo0.y, aZtop ),
161  SFVEC3F( vo1.x, vo1.y, aZtop ) );
162 
163  aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
164  SFVEC3F( vo1.x, vo1.y, aZbot ),
165  SFVEC3F( vo0.x, vo0.y, aZbot ),
166  SFVEC3F( vi0.x, vi0.y, aZbot ) );
167  }
168 }
169 
170 
172  CLAYER_TRIANGLES *aDstLayer,
173  float aZtop,
174  float aZbot )
175 {
176  const SFVEC2F &v1 = aTri->GetP1();
177  const SFVEC2F &v2 = aTri->GetP2();
178  const SFVEC2F &v3 = aTri->GetP3();
179 
180  add_triangle_top_bot( aDstLayer, v1, v2, v3, aZtop, aZbot );
181 }
182 
183 
185  CLAYER_TRIANGLES *aDstLayer,
186  float aZtop,
187  float aZbot )
188 {
189  const SFVEC2F& leftStart = aSeg->GetLeftStar();
190  const SFVEC2F& leftEnd = aSeg->GetLeftEnd();
191  const SFVEC2F& leftDir = aSeg->GetLeftDir();
192 
193  const SFVEC2F& rightStart = aSeg->GetRightStar();
194  const SFVEC2F& rightEnd = aSeg->GetRightEnd();
195  const SFVEC2F& rightDir = aSeg->GetRightDir();
196  const float radius = aSeg->GetRadius();
197 
198  const SFVEC2F& start = aSeg->GetStart();
199  const SFVEC2F& end = aSeg->GetEnd();
200 
201  const float texture_factor = (12.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
202  const float texture_factorF= ( 6.0f / (float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
203 
204  const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f );
205  const float radius_triangle_factor = (radius_of_the_square - radius) / radius;
206 
207  const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor,
208  rightDir.x * radius * radius_triangle_factor );
209 
210  const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor,
211  leftDir.x * radius * radius_triangle_factor );
212 
213  // Top end segment triangles (semi-circles)
215  SFVEC3F( rightEnd.x + texture_factor * factorS.x,
216  rightEnd.y + texture_factor * factorS.y,
217  aZtop ),
218  SFVEC3F( leftStart.x + texture_factor * factorE.x,
219  leftStart.y + texture_factor * factorE.y,
220  aZtop ),
221  SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
222  start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
223  aZtop ) );
224 
226  SFVEC3F( leftEnd.x + texture_factor * factorE.x,
227  leftEnd.y + texture_factor * factorE.y, aZtop ),
228  SFVEC3F( rightStart.x + texture_factor * factorS.x,
229  rightStart.y + texture_factor * factorS.y, aZtop ),
230  SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
231  end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
232  aZtop ) );
233 
234  // Bot end segment triangles (semi-circles)
236  SFVEC3F( leftStart.x + texture_factor * factorE.x,
237  leftStart.y + texture_factor * factorE.y,
238  aZbot ),
239  SFVEC3F( rightEnd.x + texture_factor * factorS.x,
240  rightEnd.y + texture_factor * factorS.y,
241  aZbot ),
242  SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
243  start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
244  aZbot ) );
245 
247  SFVEC3F( rightStart.x + texture_factor * factorS.x,
248  rightStart.y + texture_factor * factorS.y, aZbot ),
249  SFVEC3F( leftEnd.x + texture_factor * factorE.x,
250  leftEnd.y + texture_factor * factorE.y, aZbot ),
251  SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
252  end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
253  aZbot ) );
254 
255  // Segment top and bot planes
256  aDstLayer->m_layer_top_triangles->AddQuad(
257  SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
258  SFVEC3F( rightStart.x, rightStart.y, aZtop ),
259  SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
260  SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
261 
262  aDstLayer->m_layer_bot_triangles->AddQuad(
263  SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
264  SFVEC3F( leftStart.x, leftStart.y, aZbot ),
265  SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
266  SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
267 }
268 
269 
271  const LIST_OBJECT2D &aListHolesObject2d,
272  const SHAPE_POLY_SET &aPoly,
273  float aZtop,
274  float aZbot,
275  bool aInvertFaces,
276  const CBVHCONTAINER2D *aThroughHoles )
277 {
279 
280  if( aListHolesObject2d.size() > 0 )
281  {
282  CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( aListHolesObject2d.size() * 2 );
283 
284  // Convert the list of objects(filled circles) to triangle layer structure
285  for( LIST_OBJECT2D::const_iterator itemOnLayer = aListHolesObject2d.begin();
286  itemOnLayer != aListHolesObject2d.end();
287  ++itemOnLayer )
288  {
289  const COBJECT2D* object2d_A = static_cast<const COBJECT2D*>( *itemOnLayer );
290 
291  wxASSERT( ( object2d_A->GetObjectType() == OBJECT2D_TYPE::FILLED_CIRCLE )
292  || ( object2d_A->GetObjectType() == OBJECT2D_TYPE::ROUNDSEG ) );
293 
294  switch( object2d_A->GetObjectType() )
295  {
297  add_object_to_triangle_layer( static_cast<const CFILLEDCIRCLE2D*>( object2d_A ),
298  layerTriangles, aZtop, aZbot );
299  break;
300 
302  add_object_to_triangle_layer( static_cast<const CROUNDSEGMENT2D*>( object2d_A ),
303  layerTriangles, aZtop, aZbot );
304  break;
305 
306  default:
307  wxFAIL_MSG(
308  "C3D_RENDER_OGL_LEGACY::generate_holes_display_list: Object type is not implemented" );
309  break;
310  }
311  }
312 
313  // Note: he can have a aListHolesObject2d whith holes but without countours
314  // eg: when there are only NPTH on the list and the contours were not
315  // added
316 
317  if( aPoly.OutlineCount() > 0 )
318  {
319  layerTriangles->AddToMiddleContourns( aPoly,
320  aZbot,
321  aZtop,
323  aInvertFaces,
324  aThroughHoles );
325  }
326 
327  ret = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
329  aZbot,
330  aZtop );
331 
332  delete layerTriangles;
333  }
334 
335  return ret;
336 }
337 
338 
340  const SHAPE_POLY_SET *aPolyList,
341  PCB_LAYER_ID aLayerId,
342  const CBVHCONTAINER2D *aThroughHoles )
343 {
344  if( aContainer == nullptr )
345  return nullptr;
346 
347  const LIST_OBJECT2D &listObject2d = aContainer->GetList();
348 
349  if( listObject2d.size() == 0 )
350  return nullptr;
351 
352  float layer_z_bot = 0.0f;
353  float layer_z_top = 0.0f;
354 
355  get_layer_z_pos( aLayerId, layer_z_top, layer_z_bot );
356 
357  // Calculate an estimation for the nr of triangles based on the nr of objects
358  unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
359 
360  CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation );
361 
362  // store in a list so it will be latter deleted
363  m_triangles.push_back( layerTriangles );
364 
365  // Load the 2D (X,Y axis) component of shapes
366  for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
367  itemOnLayer != listObject2d.end();
368  ++itemOnLayer )
369  {
370  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
371 
372  switch( object2d_A->GetObjectType() )
373  {
375  add_object_to_triangle_layer( (const CFILLEDCIRCLE2D *)object2d_A,
376  layerTriangles, layer_z_top, layer_z_bot );
377  break;
378 
380  add_object_to_triangle_layer( (const CPOLYGON4PTS2D *)object2d_A,
381  layerTriangles, layer_z_top, layer_z_bot );
382  break;
383 
384  case OBJECT2D_TYPE::RING:
385  add_object_to_triangle_layer( (const CRING2D *)object2d_A,
386  layerTriangles, layer_z_top, layer_z_bot );
387  break;
388 
390  add_object_to_triangle_layer( (const CTRIANGLE2D *)object2d_A,
391  layerTriangles, layer_z_top, layer_z_bot );
392  break;
393 
395  add_object_to_triangle_layer( (const CROUNDSEGMENT2D *) object2d_A,
396  layerTriangles, layer_z_top, layer_z_bot );
397  break;
398 
399  default:
400  wxFAIL_MSG("C3D_RENDER_OGL_LEGACY: Object type is not implemented");
401  break;
402  }
403  }
404 
405  if( aPolyList )
406  if( aPolyList->OutlineCount() > 0 )
407  layerTriangles->AddToMiddleContourns( *aPolyList, layer_z_bot, layer_z_top,
408  m_boardAdapter.BiuTo3Dunits(), false,
409  aThroughHoles );
410  // Create display list
411  // /////////////////////////////////////////////////////////////////////
412  return new CLAYERS_OGL_DISP_LISTS( *layerTriangles, m_ogl_circle_texture,
413  layer_z_bot, layer_z_top );
414 }
415 
416 
418 {
419  CLAYERS_OGL_DISP_LISTS* dispLists = nullptr;
420  CCONTAINER2D boardContainer;
421  SHAPE_POLY_SET brd_outlines = aBoardPoly;
422 
423  Convert_shape_line_polygon_to_triangles( brd_outlines, boardContainer,
425  (const BOARD_ITEM &)*m_boardAdapter.GetBoard() );
426 
427  const LIST_OBJECT2D &listBoardObject2d = boardContainer.GetList();
428 
429  if( listBoardObject2d.size() > 0 )
430  {
431  // We will set a unitary Z so it will in future used with transformations
432  // since the board poly will be used not only to draw itself but also the
433  // solder mask layers.
434  const float layer_z_top = 1.0f;
435  const float layer_z_bot = 0.0f;
436 
437  CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() );
438 
439  // Convert the list of objects(triangles) to triangle layer structure
440  for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin();
441  itemOnLayer != listBoardObject2d.end();
442  ++itemOnLayer )
443  {
444  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
445 
446  wxASSERT( object2d_A->GetObjectType() == OBJECT2D_TYPE::TRIANGLE );
447 
448  const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
449 
450  const SFVEC2F &v1 = tri->GetP1();
451  const SFVEC2F &v2 = tri->GetP2();
452  const SFVEC2F &v3 = tri->GetP3();
453 
454  add_triangle_top_bot( layerTriangles,
455  v1,
456  v2,
457  v3,
458  layer_z_top,
459  layer_z_bot );
460  }
461 
462  if( aBoardPoly.OutlineCount() > 0 )
463  {
464  layerTriangles->AddToMiddleContourns( aBoardPoly,
465  layer_z_bot,
466  layer_z_top,
468  false,
469  aThroughHoles );
470 
471  dispLists = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
473  layer_z_top,
474  layer_z_top );
475  }
476 
477  delete layerTriangles;
478  }
479 
480  return dispLists;
481 }
482 
483 
484 void C3D_RENDER_OGL_LEGACY::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
485 {
486  m_reloadRequested = false;
487 
489 
491 
492  unsigned stats_startReloadTime = GetRunningMicroSecs();
493 
494  m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
495 
497  m_camera.SetBoardLookAtPos( camera_pos );
498 
499  if( aStatusReporter )
500  aStatusReporter->Report( _( "Load OpenGL: board" ) );
501 
502  // Create Board
503  // /////////////////////////////////////////////////////////////////////////
504 
506 
508  {
511  m_anti_board_poly.Append( VECTOR2I( -INT_MAX/2, -INT_MAX/2 ) );
512  m_anti_board_poly.Append( VECTOR2I( INT_MAX/2, -INT_MAX/2 ) );
513  m_anti_board_poly.Append( VECTOR2I( INT_MAX/2, INT_MAX/2 ) );
514  m_anti_board_poly.Append( VECTOR2I( -INT_MAX/2, INT_MAX/2 ) );
515  m_anti_board_poly.Outline( 0 ).SetClosed( true );
516 
519  }
520 
521  SHAPE_POLY_SET board_poly_with_holes = m_boardAdapter.GetBoardPoly();
524 
525 
526  m_ogl_disp_list_board_with_holes = createBoard( board_poly_with_holes );
527 
530 
531  // Create Through Holes and vias
532  // /////////////////////////////////////////////////////////////////////////
533 
534  if( aStatusReporter )
535  aStatusReporter->Report( _( "Load OpenGL: holes and vias" ) );
536 
538 
541 
544  outerPolyTHT,
545  1.0f,
546  0.0f,
547  false,
549 
553  1.0f,
554  0.0f,
555  false );
556 
559  {
563  1.0f,
564  0.0f,
565  false );
566  }
567 
568  // Not in use
569  //m_ogl_disp_list_through_holes_vias_inner = generate_holes_display_list(
570  // m_boardAdapter.GetThroughHole_Vias_Inner().GetList(),
571  // m_boardAdapter.GetThroughHole_Vias_Inner_poly(),
572  // 1.0f, 0.0f,
573  // false );
574 
575  const MAP_POLY & innerMapHoles = m_boardAdapter.GetPolyMapHoles_Inner();
576  const MAP_POLY & outerMapHoles = m_boardAdapter.GetPolyMapHoles_Outer();
577 
578  wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
579 
581 
582  if( outerMapHoles.size() > 0 )
583  {
584  float layer_z_bot = 0.0f;
585  float layer_z_top = 0.0f;
586 
587  for( MAP_POLY::const_iterator ii = outerMapHoles.begin();
588  ii != outerMapHoles.end();
589  ++ii )
590  {
591  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
592  const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
593  const CBVHCONTAINER2D *container = map_holes.at( layer_id );
594 
595  get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
596 
598  container->GetList(), *poly, layer_z_top, layer_z_bot, false );
599  }
600 
601  for( MAP_POLY::const_iterator ii = innerMapHoles.begin();
602  ii != innerMapHoles.end();
603  ++ii )
604  {
605  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
606  const SHAPE_POLY_SET *poly = static_cast<const SHAPE_POLY_SET *>(ii->second);
607  const CBVHCONTAINER2D *container = map_holes.at( layer_id );
608 
609  get_layer_z_pos( layer_id, layer_z_top, layer_z_bot );
610 
612  container->GetList(), *poly, layer_z_top, layer_z_bot, false );
613  }
614  }
615 
616  // Generate vertical cylinders of vias and pads (copper)
618 
619  // Add layers maps
620 
621  if( aStatusReporter )
622  aStatusReporter->Report( _( "Load OpenGL: layers" ) );
623 
624  const MAP_POLY &map_poly = m_boardAdapter.GetPolyMap();
625 
626  for( MAP_CONTAINER_2D::const_iterator ii = m_boardAdapter.GetMapLayers().begin();
627  ii != m_boardAdapter.GetMapLayers().end();
628  ++ii )
629  {
630  PCB_LAYER_ID layer_id = static_cast<PCB_LAYER_ID>(ii->first);
631 
632  if( !m_boardAdapter.Is3DLayerEnabled( layer_id ) )
633  continue;
634 
635  const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
636 
637  SHAPE_POLY_SET polyListSubtracted;
638  SHAPE_POLY_SET *aPolyList = nullptr;
639 
640  // Load the vertical (Z axis) component of shapes
641 
642  if( map_poly.find( layer_id ) != map_poly.end() )
643  {
644  polyListSubtracted = *map_poly.at( layer_id );;
645 
646  if( ( layer_id != B_Paste ) && ( layer_id != F_Paste ) &&
648  {
650 
651  if( ( layer_id != B_Mask ) && ( layer_id != F_Mask ) )
652  {
655  }
656 
658  {
659  if( ( ( layer_id == B_SilkS ) && ( map_poly.find( B_Mask ) != map_poly.end() ) ) )
660  polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ), SHAPE_POLY_SET::PM_FAST );
661  else
662  if( ( ( layer_id == F_SilkS ) && ( map_poly.find( F_Mask ) != map_poly.end() ) ) )
663  polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ), SHAPE_POLY_SET::PM_FAST );
664 
665  }
666  }
667 
668  aPolyList = &polyListSubtracted;
669  }
670 
672  aPolyList,
673  layer_id,
675 
676  if( oglList != nullptr )
677  m_ogl_disp_lists_layers[layer_id] = oglList;
678 
679  }// for each layer on
680 
683  {
685  {
690 
692  &polySubtracted, F_Cu );
693  }
694 
696  {
701 
703  &polySubtracted, B_Cu );
704  }
705  }
706 
707  // Load 3D models
708  // /////////////////////////////////////////////////////////////////////////
709  if( aStatusReporter )
710  aStatusReporter->Report( _( "Loading 3D models" ) );
711 
712  load_3D_models( aStatusReporter );
713 
714  if( aStatusReporter )
715  {
716  // Calculation time in seconds
717  const double calculation_time = (double)( GetRunningMicroSecs() -
718  stats_startReloadTime) / 1e6;
719 
720  aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
721  }
722 }
723 
724 
726  const SFVEC2F &v0,
727  const SFVEC2F &v1,
728  const SFVEC2F &v2,
729  float top,
730  float bot )
731 {
732  aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
733  SFVEC3F( v1.x, v1.y, bot ),
734  SFVEC3F( v2.x, v2.y, bot ) );
735 
736  aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ),
737  SFVEC3F( v1.x, v1.y, top ),
738  SFVEC3F( v0.x, v0.y, top ) );
739 }
740 
741 
743  float &aOutZtop,
744  float &aOutZbot ) const
745 {
746  aOutZbot = m_boardAdapter.GetLayerBottomZpos3DU( aLayerID );
747  aOutZtop = m_boardAdapter.GetLayerTopZpos3DU( aLayerID );
748 
749  if( aOutZtop < aOutZbot )
750  {
751  float tmpFloat = aOutZbot;
752  aOutZbot = aOutZtop;
753  aOutZtop = tmpFloat;
754  }
755 }
756 
757 
759  float aInnerRadius,
760  float aOuterRadius,
761  float aZtop,
762  float aZbot,
763  unsigned int aNr_sides_per_circle,
764  CLAYER_TRIANGLES *aDstLayer )
765 {
766  std::vector< SFVEC2F > innerContour;
767  std::vector< SFVEC2F > outerContour;
768 
769  generate_ring_contour( aCenter,
770  aInnerRadius,
771  aOuterRadius,
772  aNr_sides_per_circle,
773  innerContour,
774  outerContour,
775  false );
776 
777  for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
778  {
779  const SFVEC2F &vi0 = innerContour[i + 0];
780  const SFVEC2F &vi1 = innerContour[i + 1];
781  const SFVEC2F &vo0 = outerContour[i + 0];
782  const SFVEC2F &vo1 = outerContour[i + 1];
783 
784  aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
785  SFVEC3F( vi0.x, vi0.y, aZtop ),
786  SFVEC3F( vo0.x, vo0.y, aZtop ),
787  SFVEC3F( vo1.x, vo1.y, aZtop ) );
788 
789  aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
790  SFVEC3F( vo1.x, vo1.y, aZbot ),
791  SFVEC3F( vo0.x, vo0.y, aZbot ),
792  SFVEC3F( vi0.x, vi0.y, aZbot ) );
793  }
794 
795  aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true );
796  aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false );
797 }
798 
799 
801 {
803  {
804  const unsigned int reserve_nr_triangles_estimation =
806  8 *
808 
809  CLAYER_TRIANGLES *layerTriangleVIA = new CLAYER_TRIANGLES( reserve_nr_triangles_estimation );
810 
811  // Insert plated vertical holes inside the board
812  // /////////////////////////////////////////////////////////////////////////
813 
814  // Insert vias holes (vertical cylinders)
815  for( auto track : m_boardAdapter.GetBoard()->Tracks() )
816  {
817  if( track->Type() == PCB_VIA_T )
818  {
819  const VIA *via = static_cast<const VIA*>(track);
820 
821  const float holediameter = via->GetDrillValue() * m_boardAdapter.BiuTo3Dunits();
822  const float thickness = m_boardAdapter.GetCopperThickness3DU();
823  const int nrSegments = m_boardAdapter.GetNrSegmentsCircle( via->GetDrillValue() );
824  const float hole_inner_radius = holediameter / 2.0f;
825 
826  const SFVEC2F via_center( via->GetStart().x * m_boardAdapter.BiuTo3Dunits(),
827  -via->GetStart().y * m_boardAdapter.BiuTo3Dunits() );
828 
829  PCB_LAYER_ID top_layer, bottom_layer;
830  via->LayerPair( &top_layer, &bottom_layer );
831 
832  float ztop, zbot, dummy;
833 
834  get_layer_z_pos( top_layer, ztop, dummy );
835  get_layer_z_pos( bottom_layer, dummy, zbot );
836 
837  wxASSERT( zbot < ztop );
838 
839  generate_cylinder( via_center,
840  hole_inner_radius,
841  hole_inner_radius + thickness,
842  ztop,
843  zbot,
844  nrSegments,
845  layerTriangleVIA );
846  }
847  }
848 
849  m_ogl_disp_list_via = new CLAYERS_OGL_DISP_LISTS( *layerTriangleVIA,
850  0,
851  0.0f,
852  0.0f );
853 
854  delete layerTriangleVIA;
855  }
856 
857 
859  {
860  SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes (the pad)
861  SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes (the hole)
862 
863  tht_outer_holes_poly.RemoveAllContours();
864  tht_inner_holes_poly.RemoveAllContours();
865 
866  // Insert pads holes (vertical cylinders)
867  for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
868  {
869  for( PAD* pad : footprint->Pads() )
870  {
871  if( pad->GetAttribute() != PAD_ATTRIB_NPTH )
872  {
873  const wxSize drillsize = pad->GetDrillSize();
874  const bool hasHole = drillsize.x && drillsize.y;
875 
876  if( !hasHole )
877  continue;
878 
879  const int copperThickness = m_boardAdapter.GetHolePlatingThicknessBIU();
880 
881  pad->TransformHoleWithClearanceToPolygon( tht_outer_holes_poly,
882  copperThickness,
883  ARC_LOW_DEF, ERROR_INSIDE );
884  pad->TransformHoleWithClearanceToPolygon( tht_inner_holes_poly, 0,
885  ARC_LOW_DEF, ERROR_INSIDE );
886  }
887  }
888  }
889 
890  // Subtract the holes
891  tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
892 
895 
896  CCONTAINER2D holesContainer;
897 
898  Convert_shape_line_polygon_to_triangles( tht_outer_holes_poly,
899  holesContainer,
901  (const BOARD_ITEM &)*m_boardAdapter.GetBoard() );
902 
903  const LIST_OBJECT2D &listHolesObject2d = holesContainer.GetList();
904 
905  if( listHolesObject2d.size() > 0 )
906  {
907  float layer_z_top, layer_z_bot, dummy;
908 
909  get_layer_z_pos( F_Cu, layer_z_top, dummy );
910  get_layer_z_pos( B_Cu, dummy, layer_z_bot );
911 
912  CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listHolesObject2d.size() );
913 
914  // Convert the list of objects(triangles) to triangle layer structure
915  for( LIST_OBJECT2D::const_iterator itemOnLayer = listHolesObject2d.begin();
916  itemOnLayer != listHolesObject2d.end();
917  ++itemOnLayer )
918  {
919  const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
920 
921  wxASSERT( object2d_A->GetObjectType() == OBJECT2D_TYPE::TRIANGLE );
922 
923  const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
924 
925  const SFVEC2F &v1 = tri->GetP1();
926  const SFVEC2F &v2 = tri->GetP2();
927  const SFVEC2F &v3 = tri->GetP3();
928 
929  add_triangle_top_bot( layerTriangles, v1, v2, v3,
930  layer_z_top, layer_z_bot );
931  }
932 
933  wxASSERT( tht_outer_holes_poly.OutlineCount() > 0 );
934 
935  if( tht_outer_holes_poly.OutlineCount() > 0 )
936  {
937  layerTriangles->AddToMiddleContourns( tht_outer_holes_poly,
938  layer_z_bot, layer_z_top,
940  false );
941 
943  *layerTriangles,
944  m_ogl_circle_texture, // not need
945  layer_z_top, layer_z_top );
946  }
947 
948  delete layerTriangles;
949  }
950  }
951 }
952 
953 
954 /*
955  * This function will get models from the cache and load it to openGL lists
956  * in the form of C_OGL_3DMODEL. So this map of models will work as a local
957  * cache for this render. (cache based on C_OGL_3DMODEL with associated
958  * openGL lists in GPU memory)
959  */
961 {
965  {
966  return;
967  }
968 
969  // Go for all footprints
970  for( FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
971  {
972  for( const FP_3DMODEL& model : footprint->Models() )
973  {
974  if( model.m_Show && !model.m_Filename.empty() )
975  {
976  if( aStatusReporter )
977  {
978  // Display the short filename of the 3D model loaded:
979  // (the full name is usually too long to be displayed)
980  wxFileName fn( model.m_Filename );
981  wxString msg;
982  msg.Printf( _( "Loading %s" ), fn.GetFullName() );
983  aStatusReporter->Report( msg );
984  }
985 
986  // Check if the model is not present in our cache map
987  // (Not already loaded in memory)
988  if( m_3dmodel_map.find( model.m_Filename ) == m_3dmodel_map.end() )
989  {
990  // It is not present, try get it from cache
991  const S3DMODEL* modelPtr =
992  m_boardAdapter.Get3DCacheManager()->GetModel( model.m_Filename );
993 
994  // only add it if the return is not NULL
995  if( modelPtr )
996  {
998  C_OGL_3DMODEL* ogl_model = new C_OGL_3DMODEL( *modelPtr, materialMode );
999 
1000  if( ogl_model )
1001  m_3dmodel_map[ model.m_Filename ] = ogl_model;
1002  }
1003  }
1004  }
1005  }
1006  }
1007 }
double BiuTo3Dunits() const noexcept
BiuTo3Dunits - Board integer units To 3D units.
bool GetFlag(DISPLAY3D_FLG aFlag) const
GetFlag - get a configuration status of a flag.
void generate_ring_contour(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, unsigned int aNr_sides_per_circle, std::vector< SFVEC2F > &aInnerContourResult, std::vector< SFVEC2F > &aOuterContourResult, bool aInvertOrder)
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_lists_platedPads_F_Cu
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
Definition: track.cpp:422
Definition: track.h:354
void add_object_to_triangle_layer(const CRING2D *aRing, CLAYER_TRIANGLES *aDstLayer, float aZtop, float aZbot)
const SFVEC2F & GetRightEnd() const
const SFVEC2F & GetStart() const
std::map< PCB_LAYER_ID, CBVHCONTAINER2D * > MAP_CONTAINER_2D
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:50
const SFVEC2F & GetV0() const
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
int OutlineCount() const
Returns the number of outlines in the set
The CLAYER_TRIANGLES class stores arrays of triangles to be used to create display lists.
OBJECT2D_TYPE GetObjectType() const
Definition: cobject2d.h:125
SHAPE_POLY_SET m_anti_board_poly
negative polygon representation of the board outline
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_board_with_holes
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
Definition: board_item.h:86
std::map< PCB_LAYER_ID, SHAPE_POLY_SET * > MAP_POLY
A type that stores polysets for each layer id.
Definition: board_adapter.h:56
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_outer
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_lists_platedPads_B_Cu
const wxPoint & GetStart() const
Definition: track.h:116
const SFVEC2F & GetLeftStar() const
const MAP_CONTAINER_2D & GetMapLayersHoles() const noexcept
GetMapLayersHoles -Get the map of container that have the holes per layer.
float GetRadius() const
float GetLayerTopZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerTopZpos3DU - Get the top z position.
float GetCopperThickness3DU() const noexcept
GetCopperThickness3DU - Get the current copper layer thickness.
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
InitSettings - Function to be called by the render when it need to reload the settings for the board.
CLAYERS_OGL_DISP_LISTS * createBoard(const SHAPE_POLY_SET &aBoardPoly, const CBVHCONTAINER2D *aThroughHoles=nullptr)
const SFVEC2F & GetP2() const
Definition: ctriangle2d.h:59
const MAP_POLY & GetPolyMapHoles_Outer() const noexcept
const CBVHCONTAINER2D & GetThroughHole_Vias_Outer() const noexcept
GetThroughHole_Vias_Outer -.
void AddToMiddleContourns(const SHAPE_LINE_CHAIN &outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const CBVHCONTAINER2D *aThroughHoles=nullptr)
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_anti_board
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_outer_ring
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
REPORTER is a pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:64
const CBVHCONTAINER2D * GetPlatedPads_Front() const noexcept
const SHAPE_POLY_SET * GetPolyPlatedPads_Front()
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
CLAYERS_OGL_DISP_LISTS * generateLayerListFromContainer(const CBVHCONTAINER2D *aContainer, const SHAPE_POLY_SET *aPolyList, PCB_LAYER_ID aLayerId, const CBVHCONTAINER2D *aThroughHoles=nullptr)
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Function Report is a pure virtual function to override in the derived object.
const SFVEC2F & GetV3() const
const MAP_CONTAINER_2D & GetMapLayers() const noexcept
GetMapLayers - Get the map of container that have the objects per layer.
S3DMODEL * GetModel(const wxString &aModelFileName)
Function GetModel attempts to load the scene data for a model and to translate it into an S3D_MODEL s...
Definition: 3d_cache.cpp:664
const SHAPE_POLY_SET & GetThroughHole_Outer_poly_NPTH() const noexcept
float GetOuterRadius() const
Definition: cring2d.h:40
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_outer
void SetClosed(bool aClosed)
Function SetClosed()
const SFVEC2F & GetRightStar() const
void get_layer_z_pos(PCB_LAYER_ID aLayerID, float &aOutZtop, float &aOutZbot) const
PCB_LAYER_ID
A quick note on layer IDs:
float GetInnerRadius() const
Definition: cring2d.h:39
unsigned int GetNrSegmentsCircle(float aDiameter3DU) const
GetNrSegmentsCircle.
const CBVHCONTAINER2D & GetThroughHole_Outer() const noexcept
GetThroughHole_Outer - Get the inflated ThroughHole container.
const SFVEC2F & GetV2() const
const SFVEC2F & GetLeftEnd() const
const SFVEC2F & GetEnd() const
float GetLayerBottomZpos3DU(PCB_LAYER_ID aLayerId) const noexcept
GetLayerBottomZpos3DU - Get the bottom z position.
glm::vec2 SFVEC2F
Definition: xv3d_types.h:45
const CBVHCONTAINER2D * GetPlatedPads_Back() const noexcept
#define NULL
int GetHolePlatingThicknessBIU() const noexcept
GetCopperThicknessBIU - Get the current copper layer thickness.
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
Definition: track.cpp:170
const MAP_POLY & GetPolyMapHoles_Inner() const noexcept
SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
const SFVEC2F & GetCenter() const
Definition: cring2d.h:38
const SHAPE_POLY_SET * GetPolyPlatedPads_Back()
FOOTPRINTS & Footprints()
Definition: board.h:283
CLAYER_TRIANGLE_CONTAINER * m_layer_top_triangles
S3D_CACHE * Get3DCacheManager() const noexcept
Get3DCacheManager - Return the 3d cache manager pointer.
Definition: board_adapter.h:89
const BOARD * GetBoard() const noexcept
GetBoard - Get current board to be rendered.
bool Is3DLayerEnabled(PCB_LAYER_ID aLayer) const
Is3DLayerEnabled - Check if a layer is enabled.
void load_3D_models(REPORTER *aStatusReporter)
const CBVHCONTAINER2D & GetThroughHole_Inner() const noexcept
GetThroughHole_Inner - Get the ThroughHole container.
void AddTriangle(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3)
AddTriangle.
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_through_holes_vias_outer
float GetRadiusSquared() const
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
GetBoardPoly - Get the current polygon of the epoxy board.
MATERIAL_MODE
Render 3d model shape materials mode.
Definition: 3d_enums.h:117
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
int NewOutline()
Creates a new empty polygon in the set and returns its index
const SHAPE_POLY_SET & GetThroughHole_Outer_Ring_poly() const noexcept
static COBJECT2D_STATS & Instance()
Definition: cobject2d.h:152
void reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
const SFVEC2F & GetCenter() const
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_via
BOARD_ADAPTER & m_boardAdapter
settings refrence in use for this render
const SFVEC2F & GetRightDir() const
const MAP_POLY & GetPolyMap() const noexcept
GetPolyMap - Get maps of polygons's layers.
const CBVHCONTAINER2D & GetThroughHole_Outer_Ring() const noexcept
GetThroughHole_Outer_Ring - Get the ThroughHole container that include the width of the annular ring.
const SFVEC2F & GetLeftDir() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers_holes_inner
The CLAYERS_OGL_DISP_LISTS class stores the openGL display lists to related with a layer.
#define SIZE_OF_CIRCLE_TEXTURE
const SHAPE_POLY_SET & GetThroughHole_Outer_poly() const noexcept
This handles simple polygons with 4 points.
const SFVEC3F & GetBoardCenter3DU() const noexcept
GetBoardCenter - the board center position in 3d units.
CLAYER_TRIANGLE_CONTAINER * m_layer_bot_segment_ends
bool m_reloadRequested
!TODO: this must be reviewed in order to flag change types
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
CLAYER_TRIANGLE_CONTAINER * m_layer_bot_triangles
std::list< COBJECT2D * > LIST_OBJECT2D
Definition: ccontainer2d.h:37
const SFVEC2F & GetP1() const
Definition: ctriangle2d.h:58
const SFVEC2F & GetP3() const
Definition: ctriangle2d.h:60
const SFVEC2F & GetV1() const
#define _(s)
Definition: 3d_actions.cpp:33
unsigned GetRunningMicroSecs()
Function GetRunningMicroSecs An alternate way to calculate an elapset time (in microsecondes) to clas...
glm::vec3 SFVEC3F
Definition: xv3d_types.h:47
unsigned int GetStats_Nr_Holes() const noexcept
GetStats_Nr_Holes - Get statistics of the nr of holes.
void SetItIsTransparent(bool aSetTransparent)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: ccamera.h:118
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
void ResetStats()
Definition: cobject2d.h:135
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_board
const SHAPE_POLY_SET & GetThroughHole_Vias_Outer_poly() const noexcept
unsigned int GetStats_Nr_Vias() const noexcept
GetStats_Nr_Vias - Get statistics of the nr of vias.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
float GetStats_Med_Via_Hole_Diameter3DU() const noexcept
GetStats_Med_Via_Hole_Diameter3DU - Average diameter of the via holes.
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
float GetRadius() const
Definition: pad.h:59
CLAYER_TRIANGLE_CONTAINER * m_layer_top_segment_ends
void add_triangle_top_bot(CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot)
CLAYERS_OGL_DISP_LISTS * m_ogl_disp_list_pads_holes
const LIST_OBJECT2D & GetList() const
Definition: ccontainer2d.h:69
MATERIAL_MODE MaterialModeGet() const noexcept
MaterialModeGet.
TRACKS & Tracks()
Definition: board.h:280
CLAYERS_OGL_DISP_LISTS * generate_holes_display_list(const LIST_OBJECT2D &aListHolesObject2d, const SHAPE_POLY_SET &aPoly, float aZtop, float aZbot, bool aInvertFaces, const CBVHCONTAINER2D *aThroughHoles=nullptr)
void Convert_shape_line_polygon_to_triangles(SHAPE_POLY_SET &aPolyList, CGENERICCONTAINER2D &aDstContainer, float aBiuTo3DunitsScale, const BOARD_ITEM &aBoardItem)
void generate_cylinder(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, CLAYER_TRIANGLES *aDstLayer)
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
void AddQuad(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4)
AddQuad.