KiCad PCB EDA Suite
Loading...
Searching...
No Matches
opengl/create_scene.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) 2023 CERN
6 * Copyright (C) 2015-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include "render_3d_opengl.h"
27#include <board.h>
28#include <footprint.h>
29#include "../../3d_math.h"
31#include <lset.h>
32#include <trigo.h>
33#include <project.h>
34#include <core/profile.h> // To use GetRunningMicroSecs or another profiling utility
35#include <fp_lib_table.h>
36#include <eda_3d_viewer_frame.h>
37#include <project_pcb.h>
38
39
41 TRIANGLE_DISPLAY_LIST* aDstLayer, float aZtop,
42 float aZbot )
43{
44 const SFVEC2F& center = aCircle->GetCenter();
45 const float radius = aCircle->GetRadius() * 2.0f; // Double because the render triangle
46
47 // This is a small adjustment to the circle texture
48 const float texture_factor = ( 8.0f / (float) SIZE_OF_CIRCLE_TEXTURE ) + 1.0f;
49 const float f = ( sqrtf( 2.0f ) / 2.0f ) * radius * texture_factor;
50
51 // Top and Bot segments ends are just triangle semi-circles, so need to add it in duplicated.
52 aDstLayer->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZtop ),
53 SFVEC3F( center.x - f, center.y, aZtop ),
54 SFVEC3F( center.x, center.y - f, aZtop ) );
55
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, center.y + f, aZtop ) );
59
60 aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, aZbot ),
61 SFVEC3F( center.x + f, center.y, aZbot ),
62 SFVEC3F( center.x, center.y - f, aZbot ) );
63
64 aDstLayer->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, aZbot ),
65 SFVEC3F( center.x - f, center.y, aZbot ),
66 SFVEC3F( center.x, center.y + f, aZbot ) );
67}
68
69
71 TRIANGLE_DISPLAY_LIST* aDstLayer,
72 float aZtop, float aZbot )
73{
74 const SFVEC2F& v0 = aPoly->GetV0();
75 const SFVEC2F& v1 = aPoly->GetV1();
76 const SFVEC2F& v2 = aPoly->GetV2();
77 const SFVEC2F& v3 = aPoly->GetV3();
78
79 addTopAndBottomTriangles( aDstLayer, v0, v2, v1, aZtop, aZbot );
80 addTopAndBottomTriangles( aDstLayer, v2, v0, v3, aZtop, aZbot );
81}
82
83
84void RENDER_3D_OPENGL::generateRing( const SFVEC2F& aCenter, float aInnerRadius,
85 float aOuterRadius, unsigned int aNr_sides_per_circle,
86 std::vector< SFVEC2F >& aInnerContourResult,
87 std::vector< SFVEC2F >& aOuterContourResult,
88 bool aInvertOrder )
89{
90 aInnerContourResult.clear();
91 aInnerContourResult.reserve( aNr_sides_per_circle + 2 );
92
93 aOuterContourResult.clear();
94 aOuterContourResult.reserve( aNr_sides_per_circle + 2 );
95
96 const int delta = 3600 / aNr_sides_per_circle;
97
98 for( int ii = 0; ii < 3600; ii += delta )
99 {
100 float angle = (float)( aInvertOrder ? ( 3600 - ii ) : ii )
101 * 2.0f * glm::pi<float>() / 3600.0f;
102 const SFVEC2F rotatedDir = SFVEC2F( cos( angle ), sin( angle ) );
103
104 aInnerContourResult.emplace_back( aCenter.x + rotatedDir.x * aInnerRadius,
105 aCenter.y + rotatedDir.y * aInnerRadius );
106
107 aOuterContourResult.emplace_back( aCenter.x + rotatedDir.x * aOuterRadius,
108 aCenter.y + rotatedDir.y * aOuterRadius );
109 }
110
111 aInnerContourResult.push_back( aInnerContourResult[0] );
112 aOuterContourResult.push_back( aOuterContourResult[0] );
113
114 wxASSERT( aInnerContourResult.size() == aOuterContourResult.size() );
115}
116
117
119 float aZtop, float aZbot )
120{
121 const SFVEC2F& center = aRing->GetCenter();
122 const float inner = aRing->GetInnerRadius();
123 const float outer = aRing->GetOuterRadius();
124
125 std::vector< SFVEC2F > innerContour;
126 std::vector< SFVEC2F > outerContour;
127
128 generateRing( center, inner, outer, m_boardAdapter.GetCircleSegmentCount( outer * 2.0f ),
129 innerContour, outerContour, false );
130
131 // This will add the top and bot quads that will form the approximated ring
132 for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
133 {
134 const SFVEC2F& vi0 = innerContour[i + 0];
135 const SFVEC2F& vi1 = innerContour[i + 1];
136 const SFVEC2F& vo0 = outerContour[i + 0];
137 const SFVEC2F& vo1 = outerContour[i + 1];
138
139 aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
140 SFVEC3F( vi0.x, vi0.y, aZtop ),
141 SFVEC3F( vo0.x, vo0.y, aZtop ),
142 SFVEC3F( vo1.x, vo1.y, aZtop ) );
143
144 aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
145 SFVEC3F( vo1.x, vo1.y, aZbot ),
146 SFVEC3F( vo0.x, vo0.y, aZbot ),
147 SFVEC3F( vi0.x, vi0.y, aZbot ) );
148 }
149}
150
151
153 TRIANGLE_DISPLAY_LIST* aDstLayer,
154 float aZtop, float aZbot )
155{
156 const SFVEC2F& v1 = aTri->GetP1();
157 const SFVEC2F& v2 = aTri->GetP2();
158 const SFVEC2F& v3 = aTri->GetP3();
159
160 addTopAndBottomTriangles( aDstLayer, v1, v2, v3, aZtop, aZbot );
161}
162
163
165 TRIANGLE_DISPLAY_LIST* aDstLayer,
166 float aZtop, float aZbot )
167{
168 const SFVEC2F& leftStart = aSeg->GetLeftStar();
169 const SFVEC2F& leftEnd = aSeg->GetLeftEnd();
170 const SFVEC2F& leftDir = aSeg->GetLeftDir();
171
172 const SFVEC2F& rightStart = aSeg->GetRightStar();
173 const SFVEC2F& rightEnd = aSeg->GetRightEnd();
174 const SFVEC2F& rightDir = aSeg->GetRightDir();
175 const float radius = aSeg->GetRadius();
176
177 const SFVEC2F& start = aSeg->GetStart();
178 const SFVEC2F& end = aSeg->GetEnd();
179
180 const float texture_factor = ( 12.0f / (float) SIZE_OF_CIRCLE_TEXTURE ) + 1.0f;
181 const float texture_factorF = ( 6.0f / (float) SIZE_OF_CIRCLE_TEXTURE ) + 1.0f;
182
183 const float radius_of_the_square = sqrtf( aSeg->GetRadiusSquared() * 2.0f );
184 const float radius_triangle_factor = ( radius_of_the_square - radius ) / radius;
185
186 const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor,
187 rightDir.x * radius * radius_triangle_factor );
188
189 const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor,
190 leftDir.x * radius * radius_triangle_factor );
191
192 // Top end segment triangles (semi-circles)
194 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
195 rightEnd.y + texture_factor * factorS.y,
196 aZtop ),
197 SFVEC3F( leftStart.x + texture_factor * factorE.x,
198 leftStart.y + texture_factor * factorE.y,
199 aZtop ),
200 SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
201 start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
202 aZtop ) );
203
205 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
206 leftEnd.y + texture_factor * factorE.y, aZtop ),
207 SFVEC3F( rightStart.x + texture_factor * factorS.x,
208 rightStart.y + texture_factor * factorS.y, aZtop ),
209 SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
210 end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
211 aZtop ) );
212
213 // Bot end segment triangles (semi-circles)
215 SFVEC3F( leftStart.x + texture_factor * factorE.x,
216 leftStart.y + texture_factor * factorE.y,
217 aZbot ),
218 SFVEC3F( rightEnd.x + texture_factor * factorS.x,
219 rightEnd.y + texture_factor * factorS.y,
220 aZbot ),
221 SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf( 2.0f ),
222 start.y - texture_factorF * leftDir.y * radius * sqrtf( 2.0f ),
223 aZbot ) );
224
226 SFVEC3F( rightStart.x + texture_factor * factorS.x,
227 rightStart.y + texture_factor * factorS.y, aZbot ),
228 SFVEC3F( leftEnd.x + texture_factor * factorE.x,
229 leftEnd.y + texture_factor * factorE.y, aZbot ),
230 SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf( 2.0f ),
231 end.y - texture_factorF * rightDir.y * radius * sqrtf( 2.0f ),
232 aZbot ) );
233
234 // Segment top and bot planes
235 aDstLayer->m_layer_top_triangles->AddQuad(
236 SFVEC3F( rightEnd.x, rightEnd.y, aZtop ),
237 SFVEC3F( rightStart.x, rightStart.y, aZtop ),
238 SFVEC3F( leftEnd.x, leftEnd.y, aZtop ),
239 SFVEC3F( leftStart.x, leftStart.y, aZtop ) );
240
241 aDstLayer->m_layer_bot_triangles->AddQuad(
242 SFVEC3F( rightEnd.x, rightEnd.y, aZbot ),
243 SFVEC3F( leftStart.x, leftStart.y, aZbot ),
244 SFVEC3F( leftEnd.x, leftEnd.y, aZbot ),
245 SFVEC3F( rightStart.x, rightStart.y, aZbot ) );
246}
247
248
250 const SHAPE_POLY_SET& aPoly, float aZtop,
251 float aZbot, bool aInvertFaces,
252 const BVH_CONTAINER_2D* aThroughHoles )
253{
254 OPENGL_RENDER_LIST* ret = nullptr;
255
256 if( aListHolesObject2d.size() > 0 )
257 {
258 TRIANGLE_DISPLAY_LIST* layerTriangles =
259 new TRIANGLE_DISPLAY_LIST( aListHolesObject2d.size() * 2 );
260
261 // Convert the list of objects(filled circles) to triangle layer structure
262 for( const OBJECT_2D* itemOnLayer : aListHolesObject2d )
263 {
264 const OBJECT_2D* object2d_A = itemOnLayer;
265
266 wxASSERT( ( object2d_A->GetObjectType() == OBJECT_2D_TYPE::FILLED_CIRCLE )
267 || ( object2d_A->GetObjectType() == OBJECT_2D_TYPE::ROUNDSEG ) );
268
269 switch( object2d_A->GetObjectType() )
270 {
271 case OBJECT_2D_TYPE::FILLED_CIRCLE:
272 addObjectTriangles( static_cast<const FILLED_CIRCLE_2D*>( object2d_A ),
273 layerTriangles, aZtop, aZbot );
274 break;
275
276 case OBJECT_2D_TYPE::ROUNDSEG:
277 addObjectTriangles( static_cast<const ROUND_SEGMENT_2D*>( object2d_A ),
278 layerTriangles, aZtop, aZbot );
279 break;
280
281 default:
282 wxFAIL_MSG( wxT( "RENDER_3D_OPENGL::generateHoles: Object type not implemented" ) );
283 break;
284 }
285 }
286
287 // Note: he can have a aListHolesObject2d with holes but without contours
288 // eg: when there are only NPTH on the list and the contours were not added
289 if( aPoly.OutlineCount() > 0 )
290 {
291 layerTriangles->AddToMiddleContourns( aPoly, aZbot, aZtop,
293 aInvertFaces, aThroughHoles );
294 }
295
296 ret = new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture, aZbot, aZtop );
297
298 delete layerTriangles;
299 }
300
301 return ret;
302}
303
304
306 const SHAPE_POLY_SET* aPolyList,
307 PCB_LAYER_ID aLayer,
308 const BVH_CONTAINER_2D* aThroughHoles )
309{
310 if( aContainer == nullptr )
311 return nullptr;
312
313 const LIST_OBJECT2D& listObject2d = aContainer->GetList();
314
315 if( listObject2d.size() == 0 )
316 return nullptr;
317
318 float layer_z_bot = 0.0f;
319 float layer_z_top = 0.0f;
320
321 getLayerZPos( aLayer, layer_z_top, layer_z_bot );
322
323 // Calculate an estimation for the nr of triangles based on the nr of objects
324 unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
325
326 TRIANGLE_DISPLAY_LIST* layerTriangles = new TRIANGLE_DISPLAY_LIST( nrTrianglesEstimation );
327
328 // store in a list so it will be latter deleted
329 m_triangles.push_back( layerTriangles );
330
331 // Load the 2D (X,Y axis) component of shapes
332 for( const OBJECT_2D* itemOnLayer : listObject2d )
333 {
334 const OBJECT_2D* object2d_A = itemOnLayer;
335
336 switch( object2d_A->GetObjectType() )
337 {
338 case OBJECT_2D_TYPE::FILLED_CIRCLE:
339 addObjectTriangles( static_cast<const FILLED_CIRCLE_2D*>( object2d_A ),
340 layerTriangles, layer_z_top, layer_z_bot );
341 break;
342
343 case OBJECT_2D_TYPE::POLYGON4PT:
344 addObjectTriangles( static_cast<const POLYGON_4PT_2D*>( object2d_A ),
345 layerTriangles, layer_z_top, layer_z_bot );
346 break;
347
348 case OBJECT_2D_TYPE::RING:
349 addObjectTriangles( static_cast<const RING_2D*>( object2d_A ),
350 layerTriangles, layer_z_top, layer_z_bot );
351 break;
352
353 case OBJECT_2D_TYPE::TRIANGLE:
354 addObjectTriangles( static_cast<const TRIANGLE_2D*>( object2d_A ),
355 layerTriangles, layer_z_top, layer_z_bot );
356 break;
357
358 case OBJECT_2D_TYPE::ROUNDSEG:
359 addObjectTriangles( static_cast<const ROUND_SEGMENT_2D*>( object2d_A ),
360 layerTriangles, layer_z_top, layer_z_bot );
361 break;
362
363 default:
364 wxFAIL_MSG( wxT( "RENDER_3D_OPENGL: Object type is not implemented" ) );
365 break;
366 }
367 }
368
369 if( aPolyList && aPolyList->OutlineCount() > 0 )
370 {
371 layerTriangles->AddToMiddleContourns( *aPolyList, layer_z_bot, layer_z_top,
372 m_boardAdapter.BiuTo3dUnits(), false, aThroughHoles );
373 }
374
375 // Create display list
376 return new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture, layer_z_bot, layer_z_top );
377}
378
379
381{
382 float layer_z_bot = 0.0f;
383 float layer_z_top = 0.0f;
384
385 getLayerZPos( aLayer, layer_z_top, layer_z_bot );
386
387 TRIANGLE_DISPLAY_LIST* layerTriangles = new TRIANGLE_DISPLAY_LIST( 1 );
388
389 // store in a list so it will be latter deleted
390 m_triangles.push_back( layerTriangles );
391
392 return new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture, layer_z_bot, layer_z_top );
393}
394
395
397 const BVH_CONTAINER_2D* aThroughHoles )
398{
399 OPENGL_RENDER_LIST* dispLists = nullptr;
400 CONTAINER_2D boardContainer;
401
402 ConvertPolygonToTriangles( aBoardPoly, boardContainer, m_boardAdapter.BiuTo3dUnits(),
403 (const BOARD_ITEM &)*m_boardAdapter.GetBoard() );
404
405 const LIST_OBJECT2D& listBoardObject2d = boardContainer.GetList();
406
407 if( listBoardObject2d.size() > 0 )
408 {
409 // We will set a unitary Z so it will in future used with transformations since the
410 // board poly will be used not only to draw itself but also the solder mask layers.
411 const float layer_z_top = 1.0f;
412 const float layer_z_bot = 0.0f;
413
414 TRIANGLE_DISPLAY_LIST* layerTriangles =
415 new TRIANGLE_DISPLAY_LIST( listBoardObject2d.size() );
416
417 // Convert the list of objects(triangles) to triangle layer structure
418 for( const OBJECT_2D* itemOnLayer : listBoardObject2d )
419 {
420 const OBJECT_2D* object2d_A = itemOnLayer;
421
422 wxASSERT( object2d_A->GetObjectType() == OBJECT_2D_TYPE::TRIANGLE );
423
424 const TRIANGLE_2D* tri = static_cast<const TRIANGLE_2D*>( object2d_A );
425
426 const SFVEC2F& v1 = tri->GetP1();
427 const SFVEC2F& v2 = tri->GetP2();
428 const SFVEC2F& v3 = tri->GetP3();
429
430 addTopAndBottomTriangles( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot );
431 }
432
433 if( aBoardPoly.OutlineCount() > 0 )
434 {
435 layerTriangles->AddToMiddleContourns( aBoardPoly, layer_z_bot, layer_z_top,
437 aThroughHoles );
438
439 dispLists = new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture,
440 layer_z_top, layer_z_top );
441 }
442
443 delete layerTriangles;
444 }
445
446 return dispLists;
447}
448
449
450void RENDER_3D_OPENGL::reload( REPORTER* aStatusReporter, REPORTER* aWarningReporter )
451{
452 m_reloadRequested = false;
453
454 freeAllLists();
455
457
458 int64_t stats_startReloadTime = GetRunningMicroSecs();
459
460 m_boardAdapter.InitSettings( aStatusReporter, aWarningReporter );
461
463 m_camera.SetBoardLookAtPos( camera_pos );
464
465 if( aStatusReporter )
466 aStatusReporter->Report( _( "Load OpenGL: board" ) );
467
468 // Create Board
470
473 m_antiBoardPolys.Append( VECTOR2I( -INT_MAX/2, -INT_MAX/2 ) );
474 m_antiBoardPolys.Append( VECTOR2I( INT_MAX/2, -INT_MAX/2 ) );
475 m_antiBoardPolys.Append( VECTOR2I( INT_MAX/2, INT_MAX/2 ) );
476 m_antiBoardPolys.Append( VECTOR2I( -INT_MAX/2, INT_MAX/2 ) );
478
482
486
487 m_boardWithHoles = createBoard( board_poly_with_holes );
488
489 if( m_antiBoard )
491
492 // Create Through Holes and vias
493 if( aStatusReporter )
494 aStatusReporter->Report( _( "Load OpenGL: holes and vias" ) );
495
497
500
502 1.0f, 0.0f, false, &m_boardAdapter.GetTH_IDs() );
503
505 m_boardAdapter.GetViaTH_ODPolys(), 1.0f, 0.0f, false );
506
508 {
511 1.0f, 0.0f, false );
512 }
513
514 const MAP_POLY& innerMapHoles = m_boardAdapter.GetHoleIdPolysMap();
515 const MAP_POLY& outerMapHoles = m_boardAdapter.GetHoleOdPolysMap();
516
517 wxASSERT( innerMapHoles.size() == outerMapHoles.size() );
518
520
521 if( outerMapHoles.size() > 0 )
522 {
523 float layer_z_bot = 0.0f;
524 float layer_z_top = 0.0f;
525
526 for( const auto& [ layer, poly ] : outerMapHoles )
527 {
528 getLayerZPos( layer, layer_z_top, layer_z_bot );
529
530 m_outerLayerHoles[layer] = generateHoles( map_holes.at( layer )->GetList(), *poly,
531 layer_z_top, layer_z_bot, false );
532 }
533
534 for( const auto& [ layer, poly ] : innerMapHoles )
535 {
536 getLayerZPos( layer, layer_z_top, layer_z_bot );
537
538 m_innerLayerHoles[layer] = generateHoles( map_holes.at( layer )->GetList(), *poly,
539 layer_z_top, layer_z_bot, false );
540 }
541 }
542
543 // Generate vertical cylinders of vias and pads (copper)
545
546 // Add layers maps
547 if( aStatusReporter )
548 aStatusReporter->Report( _( "Load OpenGL: layers" ) );
549
550 std::bitset<LAYER_3D_END> visibilityFlags = m_boardAdapter.GetVisibleLayers();
551 const MAP_POLY& map_poly = m_boardAdapter.GetPolyMap();
552 wxString msg;
553
554 for( const auto& [ layer, container2d ] : m_boardAdapter.GetLayerMap() )
555 {
556 if( !m_boardAdapter.Is3dLayerEnabled( layer, visibilityFlags ) )
557 continue;
558
559 if( aStatusReporter )
560 {
561 msg = m_boardAdapter.GetBoard()->GetLayerName( layer );
562 aStatusReporter->Report( wxString::Format( _( "Load OpenGL layer %s" ), msg ) );
563 }
564
565 SHAPE_POLY_SET polyListSubtracted;
566 SHAPE_POLY_SET* polyList = nullptr;
567
568 // Load the vertical (Z axis) component of shapes
569
571 {
572 if( map_poly.find( layer ) != map_poly.end() )
573 {
574 polyListSubtracted = *map_poly.at( layer );
575
576 if( LSET::PhysicalLayersMask().test( layer ) )
577 {
578 polyListSubtracted.BooleanIntersection( m_boardAdapter.GetBoardPoly(),
580 }
581
582 if( layer != B_Mask && layer != F_Mask )
583 {
584 polyListSubtracted.BooleanSubtract( m_boardAdapter.GetTH_ODPolys(),
586 polyListSubtracted.BooleanSubtract( m_boardAdapter.GetNPTH_ODPolys(),
588 }
589
591 {
592 if( layer == B_SilkS && map_poly.find( B_Mask ) != map_poly.end() )
593 {
594 polyListSubtracted.BooleanSubtract( *map_poly.at( B_Mask ),
596 }
597 else if( layer == F_SilkS && map_poly.find( F_Mask ) != map_poly.end() )
598 {
599 polyListSubtracted.BooleanSubtract( *map_poly.at( F_Mask ),
601 }
602 }
603
604 polyList = &polyListSubtracted;
605 }
606 }
607
608 OPENGL_RENDER_LIST* oglList = generateLayerList( container2d, polyList, layer,
610
611 if( oglList != nullptr )
612 m_layers[layer] = oglList;
613 }
614
616 {
617 const SHAPE_POLY_SET* frontPlatedPadAndGraphicPolys = m_boardAdapter.GetFrontPlatedPadAndGraphicPolys();
618 const SHAPE_POLY_SET* backPlatedPadAndGraphicPolys = m_boardAdapter.GetBackPlatedPadAndGraphicPolys();
619
620 if( frontPlatedPadAndGraphicPolys )
621 {
622 SHAPE_POLY_SET poly = frontPlatedPadAndGraphicPolys->CloneDropTriangulation();
626
628
629 // An entry for F_Cu must exist in m_layers or we'll never look at m_platedPadsFront
630 if( m_layers.count( F_Cu ) == 0 )
632 }
633
634 if( backPlatedPadAndGraphicPolys )
635 {
636 SHAPE_POLY_SET poly = backPlatedPadAndGraphicPolys->CloneDropTriangulation();
640
642
643 // An entry for B_Cu must exist in m_layers or we'll never look at m_platedPadsBack
644 if( m_layers.count( B_Cu ) == 0 )
646 }
647 }
648
650 {
651 if( const BVH_CONTAINER_2D* padsFront = m_boardAdapter.GetOffboardPadsFront() )
652 m_offboardPadsFront = generateLayerList( padsFront, nullptr, F_Cu );
653
654 if( const BVH_CONTAINER_2D* padsBack = m_boardAdapter.GetOffboardPadsBack() )
655 m_offboardPadsBack = generateLayerList( padsBack, nullptr, B_Cu );
656 }
657
658 // Load 3D models
659 if( aStatusReporter )
660 aStatusReporter->Report( _( "Loading 3D models..." ) );
661
662 load3dModels( aStatusReporter );
663
664 if( aStatusReporter )
665 {
666 // Calculation time in seconds
667 double calculation_time = (double)( GetRunningMicroSecs() - stats_startReloadTime) / 1e6;
668
669 aStatusReporter->Report( wxString::Format( _( "Reload time %.3f s" ), calculation_time ) );
670 }
671}
672
673
675 const SFVEC2F& v1, const SFVEC2F& v2, float top,
676 float bot )
677{
678 aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
679 SFVEC3F( v1.x, v1.y, bot ),
680 SFVEC3F( v2.x, v2.y, bot ) );
681
683 SFVEC3F( v1.x, v1.y, top ),
684 SFVEC3F( v0.x, v0.y, top ) );
685}
686
687
688void RENDER_3D_OPENGL::getLayerZPos( PCB_LAYER_ID aLayer, float& aOutZtop, float& aOutZbot ) const
689{
690 aOutZbot = m_boardAdapter.GetLayerBottomZPos( aLayer );
691 aOutZtop = m_boardAdapter.GetLayerTopZPos( aLayer );
692
693 if( aOutZtop < aOutZbot )
694 {
695 float tmpFloat = aOutZbot;
696 aOutZbot = aOutZtop;
697 aOutZtop = tmpFloat;
698 }
699}
700
701
702void RENDER_3D_OPENGL::generateCylinder( const SFVEC2F& aCenter, float aInnerRadius,
703 float aOuterRadius, float aZtop, float aZbot,
704 unsigned int aNr_sides_per_circle,
705 TRIANGLE_DISPLAY_LIST* aDstLayer )
706{
707 std::vector< SFVEC2F > innerContour;
708 std::vector< SFVEC2F > outerContour;
709
710 generateRing( aCenter, aInnerRadius, aOuterRadius, aNr_sides_per_circle, innerContour,
711 outerContour, false );
712
713 for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
714 {
715 const SFVEC2F& vi0 = innerContour[i + 0];
716 const SFVEC2F& vi1 = innerContour[i + 1];
717 const SFVEC2F& vo0 = outerContour[i + 0];
718 const SFVEC2F& vo1 = outerContour[i + 1];
719
720 aDstLayer->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZtop ),
721 SFVEC3F( vi0.x, vi0.y, aZtop ),
722 SFVEC3F( vo0.x, vo0.y, aZtop ),
723 SFVEC3F( vo1.x, vo1.y, aZtop ) );
724
725 aDstLayer->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, aZbot ),
726 SFVEC3F( vo1.x, vo1.y, aZbot ),
727 SFVEC3F( vo0.x, vo0.y, aZbot ),
728 SFVEC3F( vi0.x, vi0.y, aZbot ) );
729 }
730
731 aDstLayer->AddToMiddleContourns( outerContour, aZbot, aZtop, true );
732 aDstLayer->AddToMiddleContourns( innerContour, aZbot, aZtop, false );
733}
734
735
737{
738 if( !m_boardAdapter.GetBoard() )
739 return;
740
741 const int platingThickness = m_boardAdapter.GetHolePlatingThickness();
742 const float platingThickness3d = platingThickness * m_boardAdapter.BiuTo3dUnits();
743
744 if( m_boardAdapter.GetViaCount() > 0 )
745 {
746 float averageDiameter = m_boardAdapter.GetAverageViaHoleDiameter();
747 unsigned int averageSegCount = m_boardAdapter.GetCircleSegmentCount( averageDiameter );
748 unsigned int trianglesEstimate = averageSegCount * 8 * m_boardAdapter.GetViaCount();
749
750 TRIANGLE_DISPLAY_LIST* layerTriangleVIA = new TRIANGLE_DISPLAY_LIST( trianglesEstimate );
751
752 // Insert plated vertical holes inside the board
753
754 // Insert vias holes (vertical cylinders)
755 for( const PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
756 {
757 if( track->Type() == PCB_VIA_T )
758 {
759 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
760
761 if( via->GetViaType() == VIATYPE::THROUGH )
762 continue; // handle with pad holes so castellation is taken into account
763
764 const float holediameter = via->GetDrillValue() * m_boardAdapter.BiuTo3dUnits();
765 const int nrSegments = m_boardAdapter.GetCircleSegmentCount( via->GetDrillValue() );
766 const float hole_inner_radius = holediameter / 2.0f;
767
768 const SFVEC2F via_center( via->GetStart().x * m_boardAdapter.BiuTo3dUnits(),
769 -via->GetStart().y * m_boardAdapter.BiuTo3dUnits() );
770
771 PCB_LAYER_ID top_layer, bottom_layer;
772 via->LayerPair( &top_layer, &bottom_layer );
773
774 float ztop, zbot, dummy;
775
776 getLayerZPos( top_layer, ztop, dummy );
777 getLayerZPos( bottom_layer, dummy, zbot );
778
779 wxASSERT( zbot < ztop );
780
781 generateCylinder( via_center, hole_inner_radius,
782 hole_inner_radius + platingThickness3d,
783 ztop, zbot, nrSegments, layerTriangleVIA );
784 }
785 }
786
787 m_vias = new OPENGL_RENDER_LIST( *layerTriangleVIA, 0, 0.0f, 0.0f );
788
789 delete layerTriangleVIA;
790 }
791
792
794 {
795 SHAPE_POLY_SET tht_outer_holes_poly; // Stores the outer poly of the copper holes
796 SHAPE_POLY_SET tht_inner_holes_poly; // Stores the inner poly of the copper holes
797
798 tht_outer_holes_poly.RemoveAllContours();
799 tht_inner_holes_poly.RemoveAllContours();
800
801 // Insert through-via holes (vertical cylinders)
802 for( const PCB_TRACK* track : m_boardAdapter.GetBoard()->Tracks() )
803 {
804 if( track->Type() == PCB_VIA_T )
805 {
806 const PCB_VIA* via = static_cast<const PCB_VIA*>( track );
807
808 if( via->GetViaType() == VIATYPE::THROUGH )
809 {
810 TransformCircleToPolygon( tht_outer_holes_poly, via->GetPosition(),
811 via->GetDrill() / 2 + platingThickness,
813
814 TransformCircleToPolygon( tht_inner_holes_poly, via->GetPosition(),
815 via->GetDrill() / 2, ARC_HIGH_DEF, ERROR_INSIDE );
816 }
817 }
818 }
819
820 // Insert pads holes (vertical cylinders)
821 for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
822 {
823 for( const PAD* pad : footprint->Pads() )
824 {
825 if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
826 {
827 const VECTOR2I drillsize = pad->GetDrillSize();
828 const bool hasHole = drillsize.x && drillsize.y;
829
830 if( !hasHole )
831 continue;
832
833 pad->TransformHoleToPolygon( tht_outer_holes_poly, platingThickness,
835 pad->TransformHoleToPolygon( tht_inner_holes_poly, 0, ARC_HIGH_DEF,
836 ERROR_INSIDE );
837 }
838 }
839 }
840
841 // Subtract the holes
842 tht_outer_holes_poly.BooleanSubtract( tht_inner_holes_poly, SHAPE_POLY_SET::PM_FAST );
843
845
846 CONTAINER_2D holesContainer;
847
848 ConvertPolygonToTriangles( tht_outer_holes_poly, holesContainer,
850
851 const LIST_OBJECT2D& holes2D = holesContainer.GetList();
852
853 if( holes2D.size() > 0 )
854 {
855 float layer_z_top, layer_z_bot, dummy;
856
857 getLayerZPos( F_Cu, layer_z_top, dummy );
858 getLayerZPos( B_Cu, dummy, layer_z_bot );
859
860 TRIANGLE_DISPLAY_LIST* layerTriangles = new TRIANGLE_DISPLAY_LIST( holes2D.size() );
861
862 // Convert the list of objects(triangles) to triangle layer structure
863 for( const OBJECT_2D* itemOnLayer : holes2D )
864 {
865 const OBJECT_2D* object2d_A = itemOnLayer;
866
867 wxASSERT( object2d_A->GetObjectType() == OBJECT_2D_TYPE::TRIANGLE );
868
869 const TRIANGLE_2D* tri = static_cast<const TRIANGLE_2D*>( object2d_A );
870
871 const SFVEC2F& v1 = tri->GetP1();
872 const SFVEC2F& v2 = tri->GetP2();
873 const SFVEC2F& v3 = tri->GetP3();
874
875 addTopAndBottomTriangles( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot );
876 }
877
878 wxASSERT( tht_outer_holes_poly.OutlineCount() > 0 );
879
880 if( tht_outer_holes_poly.OutlineCount() > 0 )
881 {
882 layerTriangles->AddToMiddleContourns( tht_outer_holes_poly,
883 layer_z_bot, layer_z_top,
884 m_boardAdapter.BiuTo3dUnits(), false );
885
886 m_padHoles = new OPENGL_RENDER_LIST( *layerTriangles, m_circleTexture,
887 layer_z_top, layer_z_top );
888 }
889
890 delete layerTriangles;
891 }
892 }
893}
894
895
897{
898 if( m_3dModelMap.size() > 0 )
899 return;
900
901 wxFrame* frame = dynamic_cast<EDA_3D_VIEWER_FRAME*>( m_canvas->GetParent() );
902
903 if( frame )
904 {
905 STATUSBAR_REPORTER activityReporter( frame->GetStatusBar(),
906 (int) EDA_3D_VIEWER_STATUSBAR::ACTIVITY );
907 load3dModels( &activityReporter );
908 }
909 else
910 {
911 load3dModels( nullptr );
912 }
913}
914
915
917{
918 if( !m_boardAdapter.GetBoard() )
919 return;
920
921 // Building the 3D models late crashes on recent versions of macOS
922 // Unclear the exact mechanism, but as a workaround, just build them
923 // all the time. See https://gitlab.com/kicad/code/kicad/-/issues/17198
924#ifndef __WXMAC__
929 {
930 return;
931 }
932#endif
933
934 // Go for all footprints
935 for( const FOOTPRINT* footprint : m_boardAdapter.GetBoard()->Footprints() )
936 {
937 wxString libraryName = footprint->GetFPID().GetLibNickname();
938 wxString footprintBasePath = wxEmptyString;
939
941 {
942 try
943 {
944 // FindRow() can throw an exception
945 const FP_LIB_TABLE_ROW* fpRow =
947 ->FindRow( libraryName, false );
948
949 if( fpRow )
950 footprintBasePath = fpRow->GetFullURI( true );
951 }
952 catch( ... )
953 {
954 // Do nothing if the libraryName is not found in lib table
955 }
956 }
957
958 for( const FP_3DMODEL& fp_model : footprint->Models() )
959 {
960 if( fp_model.m_Show && !fp_model.m_Filename.empty() )
961 {
962 if( aStatusReporter )
963 {
964 // Display the short filename of the 3D fp_model loaded:
965 // (the full name is usually too long to be displayed)
966 wxFileName fn( fp_model.m_Filename );
967 aStatusReporter->Report( wxString::Format( _( "Loading %s..." ),
968 fn.GetFullName() ) );
969 }
970
971 // Check if the fp_model is not present in our cache map
972 // (Not already loaded in memory)
973 if( m_3dModelMap.find( fp_model.m_Filename ) == m_3dModelMap.end() )
974 {
975 // It is not present, try get it from cache
976 const S3DMODEL* modelPtr =
977 m_boardAdapter.Get3dCacheManager()->GetModel( fp_model.m_Filename, footprintBasePath, footprint );
978
979 // only add it if the return is not NULL
980 if( modelPtr )
981 {
983 MODEL_3D* model = new MODEL_3D( *modelPtr, materialMode );
984
985 m_3dModelMap[ fp_model.m_Filename ] = model;
986 }
987 }
988 }
989 }
990 }
991}
MATERIAL_MODE
Render 3d model shape materials mode.
Definition: 3d_enums.h:71
constexpr int ARC_HIGH_DEF
Definition: base_units.h:120
std::map< PCB_LAYER_ID, SHAPE_POLY_SET * > MAP_POLY
A type that stores polysets for each layer id.
Definition: board_adapter.h:61
std::map< PCB_LAYER_ID, BVH_CONTAINER_2D * > MAP_CONTAINER_2D_BASE
A type that stores a container of 2d objects for each layer id.
Definition: board_adapter.h:58
double BiuTo3dUnits() const noexcept
Board integer units To 3D units.
const SHAPE_POLY_SET * GetFrontPlatedPadAndGraphicPolys()
const MAP_CONTAINER_2D_BASE & GetLayerHoleMap() const noexcept
const SHAPE_POLY_SET & GetBoardPoly() const noexcept
Get the current polygon of the epoxy board.
const SHAPE_POLY_SET & GetNPTH_ODPolys() const noexcept
const BVH_CONTAINER_2D * GetOffboardPadsFront() const noexcept
const SHAPE_POLY_SET & GetViaTH_ODPolys() const noexcept
const MAP_POLY & GetPolyMap() const noexcept
Get map of polygon's layers.
const MAP_POLY & GetHoleOdPolysMap() const noexcept
std::bitset< LAYER_3D_END > GetVisibleLayers() const
bool m_IsPreviewer
true if we're in a 3D preview panel, false for the standard 3D viewer
int GetHolePlatingThickness() const noexcept
Get the hole plating thickness (NB: in BOARD UNITS!).
void InitSettings(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
Function to be called by the render when it need to reload the settings for the board.
const BVH_CONTAINER_2D & GetViaAnnuli() const noexcept
float GetLayerBottomZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the bottom z position.
const BVH_CONTAINER_2D * GetOffboardPadsBack() const noexcept
const BVH_CONTAINER_2D & GetTH_IDs() const noexcept
const BVH_CONTAINER_2D * GetPlatedPadsBack() const noexcept
const MAP_POLY & GetHoleIdPolysMap() const noexcept
float GetAverageViaHoleDiameter() const noexcept
unsigned int GetViaCount() const noexcept
const BOARD * GetBoard() const noexcept
const SFVEC3F & GetBoardCenter() const noexcept
The board center position in 3D units.
float GetLayerTopZPos(PCB_LAYER_ID aLayerId) const noexcept
Get the top z position.
const BVH_CONTAINER_2D & GetTH_ODs() const noexcept
const MAP_CONTAINER_2D_BASE & GetLayerMap() const noexcept
Get the map of containers that have the objects per layer.
EDA_3D_VIEWER_SETTINGS * m_Cfg
unsigned int GetHoleCount() const noexcept
const BVH_CONTAINER_2D * GetPlatedPadsFront() const noexcept
unsigned int GetCircleSegmentCount(float aDiameter3DU) const
const BVH_CONTAINER_2D & GetViaTH_ODs() const noexcept
const SHAPE_POLY_SET & GetViaAnnuliPolys() const noexcept
const SHAPE_POLY_SET * GetBackPlatedPadAndGraphicPolys()
bool Is3dLayerEnabled(PCB_LAYER_ID aLayer, const std::bitset< LAYER_3D_END > &aVisibilityFlags) const
Check if a layer is enabled.
S3D_CACHE * Get3dCacheManager() const noexcept
Definition: board_adapter.h:85
const SHAPE_POLY_SET & GetTH_ODPolys() const noexcept
Get through hole outside diameter 2D polygons.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
const FOOTPRINTS & Footprints() const
Definition: board.h:330
const TRACKS & Tracks() const
Definition: board.h:328
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition: board.cpp:575
PROJECT * GetProject() const
Definition: board.h:490
void SetBoardLookAtPos(const SFVEC3F &aBoardPos)
Definition: camera.cpp:182
const LIST_OBJECT2D & GetList() const
Definition: container_2d.h:66
Create and handle a window for the 3d viewer connected to a Kiway and a pcbboard.
const SFVEC2F & GetCenter() const
float GetRadius() const
Hold a record identifying a library accessed by the appropriate footprint library #PLUGIN object in t...
Definition: fp_lib_table.h:42
const FP_LIB_TABLE_ROW * FindRow(const wxString &aNickName, bool aCheckIfEnabled=false)
Return an FP_LIB_TABLE_ROW if aNickName is found in this table or in any chained fall back table frag...
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
static LSET PhysicalLayersMask()
Return a mask holding all layers which are physically realized.
Definition: lset.cpp:822
static OBJECT_2D_STATS & Instance()
Definition: object_2d.h:137
void ResetStats()
Definition: object_2d.h:122
OBJECT_2D_TYPE GetObjectType() const
Definition: object_2d.h:107
Store the OpenGL display lists to related with a layer.
void SetItIsTransparent(bool aSetTransparent)
Definition: pad.h:54
Simple non-intersecting polygon with 4 points.
const SFVEC2F & GetV3() const
const SFVEC2F & GetV0() const
const SFVEC2F & GetV1() const
const SFVEC2F & GetV2() const
static FP_LIB_TABLE * PcbFootprintLibs(PROJECT *aProject)
Return the table of footprint libraries without Kiway.
Definition: project_pcb.cpp:37
CAMERA & m_camera
Flag if the canvas specific for this render was already initialized.
bool m_reloadRequested
The window size that this camera is working.
BOARD_ADAPTER & m_boardAdapter
OPENGL_RENDER_LIST * m_board
void reload(REPORTER *aStatusReporter, REPORTER *aWarningReporter)
OPENGL_RENDER_LIST * m_vias
OPENGL_RENDER_LIST * generateHoles(const LIST_OBJECT2D &aListHolesObject2d, const SHAPE_POLY_SET &aPoly, float aZtop, float aZbot, bool aInvertFaces, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
void generateCylinder(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, float aZtop, float aZbot, unsigned int aNr_sides_per_circle, TRIANGLE_DISPLAY_LIST *aDstLayer)
OPENGL_RENDER_LIST * m_outerThroughHoleRings
OPENGL_RENDER_LIST * m_offboardPadsFront
void generateRing(const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, unsigned int aNr_sides_per_circle, std::vector< SFVEC2F > &aInnerContourResult, std::vector< SFVEC2F > &aOuterContourResult, bool aInvertOrder)
SHAPE_POLY_SET m_antiBoardPolys
The negative polygon representation of the board outline.
void load3dModels(REPORTER *aStatusReporter)
Load footprint models from the cache and load it to openGL lists in the form of MODEL_3D objects.
OPENGL_RENDER_LIST * generateLayerList(const BVH_CONTAINER_2D *aContainer, const SHAPE_POLY_SET *aPolyList, PCB_LAYER_ID aLayer, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
OPENGL_RENDER_LIST * createBoard(const SHAPE_POLY_SET &aBoardPoly, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
void Load3dModelsIfNeeded()
Load footprint models if they are not already loaded, i.e.
void addObjectTriangles(const RING_2D *aRing, TRIANGLE_DISPLAY_LIST *aDstLayer, float aZtop, float aZbot)
MAP_OGL_DISP_LISTS m_layers
MAP_OGL_DISP_LISTS m_innerLayerHoles
OPENGL_RENDER_LIST * m_boardWithHoles
MAP_OGL_DISP_LISTS m_outerLayerHoles
OPENGL_RENDER_LIST * m_offboardPadsBack
std::map< wxString, MODEL_3D * > m_3dModelMap
OPENGL_RENDER_LIST * generateEmptyLayerList(PCB_LAYER_ID aLayer)
LIST_TRIANGLES m_triangles
store pointers so can be deleted latter
OPENGL_RENDER_LIST * m_outerViaThroughHoles
OPENGL_RENDER_LIST * m_outerThroughHoles
OPENGL_RENDER_LIST * m_platedPadsFront
OPENGL_RENDER_LIST * m_antiBoard
void getLayerZPos(PCB_LAYER_ID aLayerID, float &aOutZtop, float &aOutZbot) const
EDA_3D_CANVAS * m_canvas
OPENGL_RENDER_LIST * m_padHoles
void addTopAndBottomTriangles(TRIANGLE_DISPLAY_LIST *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot)
OPENGL_RENDER_LIST * m_platedPadsBack
A pure virtual class used to derive REPORTER objects from.
Definition: reporter.h:71
virtual REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED)=0
Report a string with a given severity.
float GetOuterRadius() const
Definition: ring_2d.h:48
float GetInnerRadius() const
Definition: ring_2d.h:47
const SFVEC2F & GetCenter() const
Definition: ring_2d.h:46
const SFVEC2F & GetLeftEnd() const
const SFVEC2F & GetRightEnd() const
const SFVEC2F & GetLeftStar() const
const SFVEC2F & GetLeftDir() const
const SFVEC2F & GetEnd() const
float GetRadius() const
float GetRadiusSquared() const
const SFVEC2F & GetStart() const
const SFVEC2F & GetRightDir() const
const SFVEC2F & GetRightStar() const
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, const EMBEDDED_FILES *aEmbeddedFiles)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition: 3d_cache.cpp:634
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset difference For aFastMode meaning, see function booleanOp.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
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)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
A wrapper for reporting to a specific text location in a statusbar.
Definition: reporter.h:309
const SFVEC2F & GetP2() const
Definition: triangle_2d.h:45
const SFVEC2F & GetP3() const
Definition: triangle_2d.h:46
const SFVEC2F & GetP1() const
Definition: triangle_2d.h:44
Store arrays of triangles to be used to create display lists.
TRIANGLE_LIST * m_layer_bot_segment_ends
TRIANGLE_LIST * m_layer_top_segment_ends
TRIANGLE_LIST * m_layer_bot_triangles
TRIANGLE_LIST * m_layer_top_triangles
void AddToMiddleContourns(const SHAPE_LINE_CHAIN &outlinePath, float zBot, float zTop, double aBiuTo3Du, bool aInvertFaceDirection, const BVH_CONTAINER_2D *aThroughHoles=nullptr)
void AddTriangle(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3)
void AddQuad(const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4)
T y
Definition: vector3.h:63
T x
Definition: vector3.h:62
std::list< OBJECT_2D * > LIST_OBJECT2D
Definition: container_2d.h:38
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
#define _(s)
Declaration of the eda_3d_viewer class.
@ ERROR_INSIDE
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ B_Mask
Definition: layer_ids.h:106
@ B_Cu
Definition: layer_ids.h:95
@ F_Mask
Definition: layer_ids.h:107
@ F_SilkS
Definition: layer_ids.h:104
@ B_SilkS
Definition: layer_ids.h:103
@ F_Cu
Definition: layer_ids.h:64
int64_t GetRunningMicroSecs()
An alternate way to calculate an elapsed time (in microsecondes) to class PROF_COUNTER.
#define SIZE_OF_CIRCLE_TEXTURE
std::vector< FAB_LAYER_COLOR > dummy
Store the a model based on meshes and materials.
Definition: c3dmodel.h:91
VECTOR3I v1(5, 5, 5)
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
VECTOR2I v3(-2, 1)
constexpr int delta
void ConvertPolygonToTriangles(const SHAPE_POLY_SET &aPolyList, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, const BOARD_ITEM &aBoardItem)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673
glm::vec2 SFVEC2F
Definition: xv3d_types.h:42
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44