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