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