KiCad PCB EDA Suite
wrlfacet.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) 2016-2017 Cirilo Bernardo <[email protected]>
5 * Copyright (C) 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
26#define GLM_FORCE_RADIANS
27
28#include <glm/glm.hpp>
29#include <glm/gtc/type_ptr.hpp>
30#include <cmath>
31
32#include "wrlfacet.h"
33
34#define LOWER_LIMIT (1e-12)
35
36
37static bool VDegenerate( glm::vec3* pts )
38{
39 // note: only checks the degenerate case of zero length sides; it
40 // does not detect the case of 3 distinct collinear points
41
42 double dx, dy, dz;
43
44 dx = double{ pts[1].x } - pts[0].x;
45 dy = double{ pts[1].y } - pts[0].y;
46 dz = double{ pts[1].z } - pts[0].z;
47
48 if( ( dx*dx + dy*dy + dz*dz ) < LOWER_LIMIT )
49 return true;
50
51 dx = double{ pts[2].x } - pts[0].x;
52 dy = double{ pts[2].y } - pts[0].y;
53 dz = double{ pts[2].z } - pts[0].z;
54
55 if( ( dx*dx + dy*dy + dz*dz ) < LOWER_LIMIT )
56 return true;
57
58 dx = double{ pts[2].x } - pts[1].x;
59 dy = double{ pts[2].y } - pts[1].y;
60 dz = double{ pts[2].z } - pts[1].z;
61
62 if( ( dx*dx + dy*dy + dz*dz ) < LOWER_LIMIT )
63 return true;
64
65 return false;
66}
67
68
69static WRLVEC3F VCalcTriNorm( const WRLVEC3F& p1, const WRLVEC3F& p2, const WRLVEC3F& p3 )
70{
71 // note: p1 = reference vertex
72 glm::vec3 tri = glm::vec3( 0.0, 0.0, 0.0 );
73 glm::vec3 pts[3];
74
75 pts[0] = p1;
76 pts[1] = p2;
77 pts[2] = p3;
78
79 // degenerate points are given a default 0, 0, 0 normal
80 if( VDegenerate( pts ) )
81 return tri;
82
83 // normal
84 tri = glm::cross( pts[2] - pts[0], pts[1] - pts[0] );
85
86 float dn = sqrtf( tri.x * tri.x + tri.y * tri.y + tri.z * tri.z );
87
88 if( dn > LOWER_LIMIT )
89 {
90 tri.x /= dn;
91 tri.y /= dn;
92 tri.z /= dn;
93 }
94
95 return tri;
96}
97
98
99static float VCalcCosAngle( const WRLVEC3F& p1, const WRLVEC3F& p2, const WRLVEC3F& p3 )
100{
101 // note: p1 = reference vertex
102 float l12, l13;
103 float dx, dy, dz;
104
105 dx = p2.x - p1.x;
106 dy = p2.y - p1.y;
107 dz = p2.z - p1.z;
108 float p12 = dx*dx + dy*dy + dz*dz;
109 l12 = sqrtf( p12 );
110
111 dx = p3.x - p2.x;
112 dy = p3.y - p2.y;
113 dz = p3.z - p2.z;
114 float p23 = dx*dx + dy*dy + dz*dz;
115
116 dx = p3.x - p1.x;
117 dy = p3.y - p1.y;
118 dz = p3.z - p1.z;
119 float p13 = dx*dx + dy*dy + dz*dz;
120 l13 = sqrtf( p13 );
121
122 float dn = 2.0f * l12 * l13;
123
124 // place a limit to prevent calculations from blowing up
125 if( dn < LOWER_LIMIT )
126 {
127 if( ( p12 + p13 - p23 ) < FLT_EPSILON )
128 return -1.0f;
129
130 if( ( p12 + p13 - p23 ) > FLT_EPSILON )
131 return 1.0f;
132
133 return 0.0f;
134 }
135
136 float cosAngle = ( p12 + p13 - p23 ) / dn;
137
138 // check the domain; errors in the cosAngle calculation can result in domain errors
139 if( cosAngle > 1.0f )
140 cosAngle = 1.0f;
141 else if( cosAngle < -1.0f )
142 cosAngle = -1.0f;
143
144 // note: we are guaranteed that acosf() is never negative
145 return cosAngle;
146}
147
148
150{
151 face_normal.x = 0.0;
152 face_normal.y = 0.0;
153 face_normal.z = 0.0;
154 maxIdx = 0;
155}
156
157
159{
160 vertices.clear();
161 colors.clear();
162 indices.clear();
163 norms.clear();
164 vnweight.clear();
165
166 face_normal.x = 0.0;
167 face_normal.y = 0.0;
168 face_normal.z = 0.0;
169 maxIdx = 0;
170}
171
172
174{
175 if( vertices.size() < 3 )
176 return false;
177
178 return true;
179}
180
181
183{
184 if( colors.empty() )
185 return false;
186
187 return true;
188}
189
190
191void FACET::AddVertex( WRLVEC3F& aVertex, int aIndex )
192{
193 if( aIndex < 0 )
194 return;
195
196 vertices.push_back( aVertex );
197 indices.push_back( aIndex );
198
199 if( aIndex > maxIdx )
200 maxIdx = aIndex;
201}
202
203
204void FACET::AddColor( const SGCOLOR& aColor )
205{
206 colors.push_back( aColor );
207
208 return;
209}
210
211
213{
214 // note: this calculation assumes that the face is a convex polygon;
215 // concave polygons may be supported in the future via functions which
216 // split the polygon into triangles
217
218 if( vertices.size() < 3 )
219 return 0.0;
220
221 // check if the values were already calculated
222 if( vertices.size() == vnweight.size() )
223 return 0.0;
224
225 WRLVEC3F lCPts[3];
226
227 std::vector< WRLVEC3F >::iterator sV = vertices.begin();
228 std::vector< WRLVEC3F >::iterator eV = vertices.end();
229
230 lCPts[0] = vertices.back();
231 lCPts[1] = *sV;
232 ++sV;
233 lCPts[2] = *sV;
234 ++sV;
235
236 face_normal = VCalcTriNorm( lCPts[1], lCPts[0], lCPts[2] );
237
238 vnweight.clear();
239 WRLVEC3F wnorm = face_normal;
240
241 // calculate area:
242 size_t nv = vertices.size();
243 float a1 = 0.0;
244 glm::vec3 sum( 0.0, 0.0, 0.0 );
245 size_t j = 0;
246
247 for( size_t i = 1; i < nv; ++i, ++j )
248 sum += glm::cross( vertices[j], vertices[i] );
249
250 a1 = fabs( glm::dot( face_normal, sum ) );
251 float a2 = acosf( VCalcCosAngle( lCPts[1], lCPts[0], lCPts[2] ) );
252
253 wnorm.x *= a1 * a2;
254 wnorm.y *= a1 * a2;
255 wnorm.z *= a1 * a2;
256 vnweight.push_back( wnorm );
257
258 float maxV = fabs( wnorm.x );
259 float tV = fabs( wnorm.y );
260
261 if( tV > maxV )
262 maxV = tV;
263
264 tV = fabs( wnorm.z );
265
266 if( tV > maxV )
267 maxV = tV;
268
269 while( sV != eV )
270 {
271 lCPts[0] = lCPts[1];
272 lCPts[1] = lCPts[2];
273 lCPts[2] = *sV;
274 ++sV;
275
276 wnorm = face_normal;
277 a2 = acosf( VCalcCosAngle( lCPts[1], lCPts[0], lCPts[2] ) );
278 wnorm.x *= a1 * a2;
279 wnorm.y *= a1 * a2;
280 wnorm.z *= a1 * a2;
281 vnweight.push_back( wnorm );
282
283 tV = fabs( wnorm.x );
284
285 if( tV > maxV )
286 maxV = tV;
287
288 tV = fabs( wnorm.y );
289
290 if( tV > maxV )
291 maxV = tV;
292
293 tV = fabs( wnorm.z );
294
295 if( tV > maxV )
296 maxV = tV;
297 }
298
299 lCPts[0] = lCPts[1];
300 lCPts[1] = lCPts[2];
301 lCPts[2] = vertices.front();
302
303 wnorm = face_normal;
304 a2 = acosf( VCalcCosAngle( lCPts[1], lCPts[0], lCPts[2] ) );
305 wnorm.x *= a1 * a2;
306 wnorm.y *= a1 * a2;
307 wnorm.z *= a1 * a2;
308 vnweight.push_back( wnorm );
309
310 tV = fabs( wnorm.x );
311
312 if( tV > maxV )
313 maxV = tV;
314
315 tV = fabs( wnorm.y );
316
317 if( tV > maxV )
318 maxV = tV;
319
320 tV = fabs( wnorm.z );
321
322 if( tV > maxV )
323 maxV = tV;
324
325 return maxV;
326}
327
328
329void FACET::CalcVertexNormal( int aIndex, std::list< FACET* > &aFacetList, float aCreaseLimit )
330{
331 if( vertices.size() < 3 )
332 return;
333
334 if( vnweight.size() != vertices.size() )
335 return;
336
337 if( norms.size() != vertices.size() )
338 norms.resize( vertices.size() );
339
340 std::vector< int >::iterator sI = indices.begin();
341 std::vector< int >::iterator eI = indices.end();
342 int idx = 0;
343
344 WRLVEC3F fp[2]; // vectors to calculate facet angle
345 fp[0].x = 0.0;
346 fp[0].y = 0.0;
347 fp[0].z = 0.0;
348
349 while( sI != eI )
350 {
351 if( *sI == aIndex )
352 {
353 // first set the default (weighted) normal value
354 norms[idx] = vnweight[idx];
355
356 // iterate over adjacent facets
357 std::list< FACET* >::iterator sF = aFacetList.begin();
358 std::list< FACET* >::iterator eF = aFacetList.end();
359
360 while( sF != eF )
361 {
362 if( this == *sF )
363 {
364 ++sF;
365 continue;
366 }
367
368 // check the crease angle limit
369 (*sF)->GetFaceNormal( fp[1] );
370
371 float thrs = VCalcCosAngle( fp[0], face_normal, fp[1] );
372
373 if( aCreaseLimit <= thrs && (*sF)->GetWeightedNormal( aIndex, fp[1] ) )
374 {
375 norms[idx].x += fp[1].x;
376 norms[idx].y += fp[1].y;
377 norms[idx].z += fp[1].z;
378 }
379
380 ++sF;
381 }
382
383 // normalize the vector
384 float dn = sqrtf( norms[idx].x * norms[idx].x
385 + norms[idx].y * norms[idx].y
386 + norms[idx].z * norms[idx].z );
387
388 if( dn > LOWER_LIMIT )
389 {
390 norms[idx].x /= dn;
391 norms[idx].y /= dn;
392 norms[idx].z /= dn;
393 }
394
395 // if the normals is an invalid normal this test will pass
396 if( fabs( norms[idx].x ) < 0.5
397 && fabs( norms[idx].y ) < 0.5
398 && fabs( norms[idx].z ) < 0.5 )
399 {
400 norms[idx] = face_normal;
401 }
402
403 return;
404 }
405
406 ++idx;
407 ++sI;
408 }
409}
410
411
412bool FACET::GetWeightedNormal( int aIndex, WRLVEC3F& aNorm )
413{
414 // the default weighted normal shall have no effect even if accidentally included
415 aNorm.x = 0.0;
416 aNorm.y = 0.0;
417 aNorm.z = 0.0;
418
419 if( vertices.size() < 3 )
420 return false;
421
422 if( vnweight.size() != vertices.size() )
423 return false;
424
425 std::vector< int >::iterator sI = indices.begin();
426 std::vector< int >::iterator eI = indices.end();
427 int idx = 0;
428
429 while( sI != eI )
430 {
431 if( *sI == aIndex )
432 {
433 aNorm = vnweight[idx];
434 return true;
435 }
436
437 ++idx;
438 ++sI;
439 }
440
441 return false;
442}
443
444
446{
447 aNorm.x = 0.0;
448 aNorm.y = 0.0;
449 aNorm.z = 0.0;
450
451 if( vertices.size() < 3 )
452 return false;
453
454 if( vnweight.size() != vertices.size() )
455 return false;
456
457 aNorm = face_normal;
458 return true;
459}
460
461
462bool FACET::GetData( std::vector< WRLVEC3F >& aVertexList, std::vector< WRLVEC3F >& aNormalsList,
463 std::vector< SGCOLOR >& aColorsList, WRL1_ORDER aVertexOrder )
464{
465 // if no normals are calculated we simply return
466 if( norms.empty() )
467 return false;
468
469 // the output must always be triangle sets in order to conform to the
470 // requirements of the SG* classes
471 int idx[3];
472
473 idx[0] = 0;
474 idx[1] = 1;
475 idx[2] = 2;
476 WRLVEC3F tnorm;
477
478 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
479 {
480 aVertexList.push_back( vertices[idx[0]] );
481 aVertexList.push_back( vertices[idx[1]] );
482 aVertexList.push_back( vertices[idx[2]] );
483
484 aNormalsList.push_back( norms[idx[0]] );
485 aNormalsList.push_back( norms[idx[1]] );
486 aNormalsList.push_back( norms[idx[2]] );
487 }
488
489 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
490 {
491 aVertexList.push_back( vertices[idx[0]] );
492 aVertexList.push_back( vertices[idx[2]] );
493 aVertexList.push_back( vertices[idx[1]] );
494
495 tnorm = norms[idx[0]];
496 tnorm.x = -tnorm.x;
497 tnorm.y = -tnorm.y;
498 tnorm.z = -tnorm.z;
499 aNormalsList.push_back( tnorm );
500
501 tnorm = norms[idx[2]];
502 tnorm.x = -tnorm.x;
503 tnorm.y = -tnorm.y;
504 tnorm.z = -tnorm.z;
505 aNormalsList.push_back( tnorm );
506
507 tnorm = norms[idx[1]];
508 tnorm.x = -tnorm.x;
509 tnorm.y = -tnorm.y;
510 tnorm.z = -tnorm.z;
511 aNormalsList.push_back( tnorm );
512 }
513
514 bool hasColor = false;
515 bool perVC = false; // per-vertex colors?
516
517 if( !colors.empty() )
518 {
519 hasColor = true;
520
521 if( colors.size() >= vertices.size() )
522 perVC = true;
523
524 if( perVC )
525 {
526 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
527 {
528 aColorsList.push_back( colors[idx[0]] );
529 aColorsList.push_back( colors[idx[1]] );
530 aColorsList.push_back( colors[idx[2]] );
531 }
532
533 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
534 {
535 aColorsList.push_back( colors[idx[0]] );
536 aColorsList.push_back( colors[idx[2]] );
537 aColorsList.push_back( colors[idx[1]] );
538 }
539 }
540 else
541 {
542 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
543 {
544 aColorsList.push_back( colors[0] );
545 aColorsList.push_back( colors[0] );
546 aColorsList.push_back( colors[0] );
547 }
548
549 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
550 {
551 aColorsList.push_back( colors[0] );
552 aColorsList.push_back( colors[0] );
553 aColorsList.push_back( colors[0] );
554 }
555 }
556 }
557
558 int lim = (int) vertices.size() - 1;
559
560 while( idx[2] < lim )
561 {
562 idx[1] = idx[2];
563 ++idx[2];
564
565 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
566 {
567 aVertexList.push_back( vertices[idx[0]] );
568 aVertexList.push_back( vertices[idx[1]] );
569 aVertexList.push_back( vertices[idx[2]] );
570
571 aNormalsList.push_back( norms[idx[0]] );
572 aNormalsList.push_back( norms[idx[1]] );
573 aNormalsList.push_back( norms[idx[2]] );
574 }
575
576 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
577 {
578 aVertexList.push_back( vertices[idx[0]] );
579 aVertexList.push_back( vertices[idx[2]] );
580 aVertexList.push_back( vertices[idx[1]] );
581
582 tnorm = norms[idx[0]];
583 tnorm.x = -tnorm.x;
584 tnorm.y = -tnorm.y;
585 tnorm.z = -tnorm.z;
586 aNormalsList.push_back( tnorm );
587
588 tnorm = norms[idx[2]];
589 tnorm.x = -tnorm.x;
590 tnorm.y = -tnorm.y;
591 tnorm.z = -tnorm.z;
592 aNormalsList.push_back( tnorm );
593
594 tnorm = norms[idx[1]];
595 tnorm.x = -tnorm.x;
596 tnorm.y = -tnorm.y;
597 tnorm.z = -tnorm.z;
598 aNormalsList.push_back( tnorm );
599 }
600
601 if( hasColor )
602 {
603 if( perVC )
604 {
605 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
606 {
607 aColorsList.push_back( colors[idx[0]] );
608 aColorsList.push_back( colors[idx[1]] );
609 aColorsList.push_back( colors[idx[2]] );
610 }
611
612 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
613 {
614 aColorsList.push_back( colors[idx[0]] );
615 aColorsList.push_back( colors[idx[2]] );
616 aColorsList.push_back( colors[idx[1]] );
617 }
618 }
619 else
620 {
621 if( aVertexOrder != WRL1_ORDER::ORD_CLOCKWISE )
622 {
623 aColorsList.push_back( colors[0] );
624 aColorsList.push_back( colors[0] );
625 aColorsList.push_back( colors[0] );
626 }
627
628 if( aVertexOrder != WRL1_ORDER::ORD_CCW )
629 {
630 aColorsList.push_back( colors[0] );
631 aColorsList.push_back( colors[0] );
632 aColorsList.push_back( colors[0] );
633 }
634 }
635 }
636 }
637
638 return true;
639}
640
641
642void FACET::CollectVertices( std::vector< std::list< FACET* > >& aFacetList )
643{
644 // check if this facet may contribute anything at all
645 if( vertices.size() < 3 )
646 return;
647
648 // note: in principle this should never be invoked
649 if( (maxIdx + 1) >= (int)aFacetList.size() )
650 aFacetList.resize( static_cast<std::size_t>( maxIdx ) + 1 );
651
652 std::vector< int >::iterator sI = indices.begin();
653 std::vector< int >::iterator eI = indices.end();
654
655 while( sI != eI )
656 {
657 aFacetList[*sI].push_back( this );
658 ++sI;
659 }
660}
661
662
663void FACET::Renormalize( float aMaxValue )
664{
665 if( vnweight.empty() || aMaxValue < LOWER_LIMIT )
666 return;
667
668 size_t vs = vnweight.size();
669
670 for( size_t i = 0; i < vs; ++i )
671 {
672 vnweight[i].x /= aMaxValue;
673 vnweight[i].y /= aMaxValue;
674 vnweight[i].z /= aMaxValue;
675 }
676}
677
678
680{
681 std::list< FACET* >::iterator sF = facets.begin();
682 std::list< FACET* >::iterator eF = facets.end();
683
684 while( sF != eF )
685 {
686 delete *sF;
687 ++sF;
688 }
689
690 facets.clear();
691 return;
692}
693
694
696{
697 FACET* fp = new FACET;
698 facets.push_back( fp );
699 return fp;
700}
701
702
703SGNODE* SHAPE::CalcShape( SGNODE* aParent, SGNODE* aColor, WRL1_ORDER aVertexOrder,
704 float aCreaseLimit, bool isVRML2 )
705{
706 if( facets.empty() || !facets.front()->HasMinPoints() )
707 return nullptr;
708
709 std::vector< std::list< FACET* > > flist;
710
711 // determine the max. index and size flist as appropriate
712 std::list< FACET* >::iterator sF = facets.begin();
713 std::list< FACET* >::iterator eF = facets.end();
714
715 int maxIdx = 0;
716 int tmi;
717 float maxV = 0.0;
718 float tV = 0.0;
719
720 while( sF != eF )
721 {
722 tV = ( *sF )->CalcFaceNormal();
723 tmi = ( *sF )->GetMaxIndex();
724
725 if( tmi > maxIdx )
726 maxIdx = tmi;
727
728 if( tV > maxV )
729 maxV = tV;
730
731 ++sF;
732 }
733
734 ++maxIdx;
735
736 if( maxIdx < 3 )
737 return nullptr;
738
739 flist.resize( maxIdx );
740
741 // create the lists of facets common to indices
742 sF = facets.begin();
743
744 while( sF != eF )
745 {
746 ( *sF )->Renormalize( tV );
747 ( *sF )->CollectVertices( flist );
748 ++sF;
749 }
750
751 // calculate the normals
752 size_t vs = flist.size();
753
754 for( size_t i = 0; i < vs; ++i )
755 {
756 sF = flist[i].begin();
757 eF = flist[i].end();
758
759 while( sF != eF )
760 {
761 ( *sF )->CalcVertexNormal( static_cast<int>( i ), flist[i], aCreaseLimit );
762 ++sF;
763 }
764 }
765
766 std::vector< WRLVEC3F > vertices;
767 std::vector< WRLVEC3F > normals;
768 std::vector< SGCOLOR > colors;
769
770 // push the facet data to the final output list
771 sF = facets.begin();
772 eF = facets.end();
773
774 while( sF != eF )
775 {
776 ( *sF )->GetData( vertices, normals, colors, aVertexOrder );
777 ++sF;
778 }
779
780 flist.clear();
781
782 if( vertices.size() < 3 )
783 return nullptr;
784
785 IFSG_SHAPE shapeNode( false );
786
787 if( !isVRML2 )
788 {
789 shapeNode.NewNode( aParent );
790
791 if( aColor )
792 {
793 if( nullptr == S3D::GetSGNodeParent( aColor ) )
794 shapeNode.AddChildNode( aColor );
795 else
796 shapeNode.AddRefNode( aColor );
797 }
798 }
799
800 std::vector< SGPOINT > lCPts; // vertex points in SGPOINT (double) format
801 std::vector< SGVECTOR > lCNorm; // per-vertex normals
802 vs = vertices.size();
803
804 for( size_t i = 0; i < vs; ++i )
805 {
806 SGPOINT pt;
807 pt.x = vertices[i].x;
808 pt.y = vertices[i].y;
809 pt.z = vertices[i].z;
810 lCPts.push_back( pt );
811 lCNorm.emplace_back( normals[i].x, normals[i].y, normals[i].z );
812 }
813
814 vertices.clear();
815 normals.clear();
816
817 IFSG_FACESET fsNode( false );
818
819 if( !isVRML2 )
820 fsNode.NewNode( shapeNode );
821 else
822 fsNode.NewNode( aParent );
823
824 IFSG_COORDS cpNode( fsNode );
825 cpNode.SetCoordsList( lCPts.size(), &lCPts[0] );
826 IFSG_COORDINDEX ciNode( fsNode );
827
828 for( int i = 0; i < (int)lCPts.size(); ++i )
829 ciNode.AddIndex( i );
830
831 IFSG_NORMALS nmNode( fsNode );
832 nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
833
834 if( !colors.empty() )
835 {
836 IFSG_COLORS nmColor( fsNode );
837 nmColor.SetColorList( colors.size(), &colors[0] );
838 colors.clear();
839 }
840
841 if( !isVRML2 )
842 return shapeNode.GetRawPtr();
843
844 return fsNode.GetRawPtr();
845}
Definition: wrlfacet.h:43
WRLVEC3F face_normal
Definition: wrlfacet.h:125
std::vector< SGCOLOR > colors
Definition: wrlfacet.h:122
std::vector< WRLVEC3F > vnweight
Definition: wrlfacet.h:127
bool GetFaceNormal(WRLVEC3F &aNorm)
Retrieve the normal for this facet.
Definition: wrlfacet.cpp:445
FACET()
Definition: wrlfacet.cpp:149
bool HasMinPoints()
Definition: wrlfacet.cpp:173
void Renormalize(float aMaxValue)
Definition: wrlfacet.cpp:663
std::vector< WRLVEC3F > vertices
Definition: wrlfacet.h:121
int maxIdx
Definition: wrlfacet.h:129
bool GetWeightedNormal(int aIndex, WRLVEC3F &aNorm)
Retrieve the angle weighted normal for the given vertex index.
Definition: wrlfacet.cpp:412
float CalcFaceNormal()
Calculate the normal to the facet assuming a CCW orientation and perform the calculation of the angle...
Definition: wrlfacet.cpp:212
bool HasColors()
Definition: wrlfacet.cpp:182
void CollectVertices(std::vector< std::list< FACET * > > &aFacetList)
Add a pointer to this object at each position within aFacetList referenced by the internal vertex ind...
Definition: wrlfacet.cpp:642
void AddVertex(WRLVEC3F &aVertex, int aIndex)
Add the vertex and its associated index to the internal list of polygon vertices.
Definition: wrlfacet.cpp:191
std::vector< WRLVEC3F > norms
Definition: wrlfacet.h:126
std::vector< int > indices
Definition: wrlfacet.h:123
void CalcVertexNormal(int aIndex, std::list< FACET * > &aFacetList, float aCreaseAngle)
Calculate the weighted normal for the given vertex.
Definition: wrlfacet.cpp:329
void AddColor(const SGCOLOR &aColor)
Add the given RGB color to the internal list.
Definition: wrlfacet.cpp:204
void Init()
Definition: wrlfacet.cpp:158
bool GetData(std::vector< WRLVEC3F > &aVertexList, std::vector< WRLVEC3F > &aNormalsList, std::vector< SGCOLOR > &aColorsList, WRL1_ORDER aVertexOrder)
Package the internal data as triangles with corresponding per-vertex normals.
Definition: wrlfacet.cpp:462
IFSG_COLORS is the wrapper for SGCOLORS.
Definition: ifsg_colors.h:42
bool SetColorList(size_t aListSize, const SGCOLOR *aColorList)
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:41
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:41
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
bool AddIndex(int aIndex)
Function AddIndex adds a single index to the list.
Definition: ifsg_index.cpp:57
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:65
bool AddChildNode(SGNODE *aNode)
Function AddChildNode adds a node as a child owned by this node.
Definition: ifsg_node.cpp:148
bool AddRefNode(SGNODE *aNode)
Function AddRefNode adds a reference to an existing node which is not owned by (not a child of) this ...
Definition: ifsg_node.cpp:128
IFSG_NORMALS is the wrapper for the SGNORMALS class.
Definition: ifsg_normals.h:41
bool SetNormalList(size_t aListSize, const SGVECTOR *aNormalList)
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:41
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
Definition: ifsg_shape.cpp:121
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
double z
Definition: sg_base.h:72
double x
Definition: sg_base.h:70
double y
Definition: sg_base.h:71
FACET * NewFacet()
Definition: wrlfacet.cpp:695
SGNODE * CalcShape(SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
Definition: wrlfacet.cpp:703
std::list< FACET * > facets
Definition: wrlfacet.h:143
virtual ~SHAPE()
Definition: shape.h:137
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:494
static bool VDegenerate(glm::vec3 *pts)
Definition: wrlfacet.cpp:37
static float VCalcCosAngle(const WRLVEC3F &p1, const WRLVEC3F &p2, const WRLVEC3F &p3)
Definition: wrlfacet.cpp:99
static WRLVEC3F VCalcTriNorm(const WRLVEC3F &p1, const WRLVEC3F &p2, const WRLVEC3F &p3)
Definition: wrlfacet.cpp:69
#define LOWER_LIMIT
Definition: wrlfacet.cpp:34
declares classes to help manage normals calculations from VRML files
WRL1_ORDER
Definition: wrltypes.h:114
glm::vec3 WRLVEC3F
Definition: wrltypes.h:188