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 <cirilo.bernardo@gmail.com>
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 
37 static 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 
69 static 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 
99 static 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 
191 void 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 
204 void 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 
329 void 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 
412 bool 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 
462 bool 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 
642 void 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 
663 void 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 
703 SGNODE* 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 }
static WRLVEC3F VCalcTriNorm(const WRLVEC3F &p1, const WRLVEC3F &p2, const WRLVEC3F &p3)
Definition: wrlfacet.cpp:69
SGNODE * CalcShape(SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
Definition: wrlfacet.cpp:703
double x
Definition: sg_base.h:70
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:40
glm::vec3 WRLVEC3F
Definition: wrltypes.h:188
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
void AddVertex(WRLVEC3F &aVertex, int aIndex)
Add the vertex and its associated index to the internal list of polygon vertices.
Definition: wrlfacet.cpp:191
void Init()
Definition: wrlfacet.cpp:158
IFSG_COLORS is the wrapper for SGCOLORS.
Definition: ifsg_colors.h:41
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
void Renormalize(float aMaxValue)
Definition: wrlfacet.cpp:663
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:492
double y
Definition: sg_base.h:71
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
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
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
virtual ~SHAPE()
Definition: shape.h:131
bool AddIndex(int aIndex)
Function AddIndex adds a single index to the list.
Definition: ifsg_index.cpp:57
static float VCalcCosAngle(const WRLVEC3F &p1, const WRLVEC3F &p2, const WRLVEC3F &p3)
Definition: wrlfacet.cpp:99
declares classes to help manage normals calculations from VRML files
void AddColor(const SGCOLOR &aColor)
Add the given RGB color to the internal list.
Definition: wrlfacet.cpp:204
bool GetWeightedNormal(int aIndex, WRLVEC3F &aNorm)
Retrieve the angle weighted normal for the given vertex index.
Definition: wrlfacet.cpp:412
IFSG_NORMALS is the wrapper for the SGNORMALS class.
Definition: ifsg_normals.h:40
WRL1_ORDER
Definition: wrltypes.h:113
bool HasColors()
Definition: wrlfacet.cpp:182
bool GetFaceNormal(WRLVEC3F &aNorm)
Retrieve the normal for this facet.
Definition: wrlfacet.cpp:445
bool SetColorList(size_t aListSize, const SGCOLOR *aColorList)
std::vector< SGCOLOR > colors
Definition: wrlfacet.h:122
std::vector< WRLVEC3F > norms
Definition: wrlfacet.h:126
WRLVEC3F face_normal
Definition: wrlfacet.h:125
void CalcVertexNormal(int aIndex, std::list< FACET * > &aFacetList, float aCreaseAngle)
Calculate the weighted normal for the given vertex.
Definition: wrlfacet.cpp:329
std::vector< WRLVEC3F > vertices
Definition: wrlfacet.h:121
FACET * NewFacet()
Definition: wrlfacet.cpp:695
Definition: wrlfacet.h:42
std::list< FACET * > facets
Definition: wrlfacet.h:143
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
float CalcFaceNormal()
Calculate the normal to the facet assuming a CCW orientation and perform the calculation of the angle...
Definition: wrlfacet.cpp:212
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
bool SetNormalList(size_t aListSize, const SGVECTOR *aNormalList)
static bool VDegenerate(glm::vec3 *pts)
Definition: wrlfacet.cpp:37
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:40
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
std::vector< WRLVEC3F > vnweight
Definition: wrlfacet.h:127
double z
Definition: sg_base.h:72
std::vector< int > indices
Definition: wrlfacet.h:123
int maxIdx
Definition: wrlfacet.h:129
FACET()
Definition: wrlfacet.cpp:149
bool NewNode(SGNODE *aParent) override
Function NewNode creates a new node to associate with this wrapper.
Definition: ifsg_shape.cpp:118
#define LOWER_LIMIT
Definition: wrlfacet.cpp:34
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:40
bool HasMinPoints()
Definition: wrlfacet.cpp:173