KiCad PCB EDA Suite
sg_shape.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2015-2017 Cirilo Bernardo <[email protected]>
5  * Copyright (C) 2020 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 #include <iostream>
27 #include <sstream>
28 #include <wx/log.h>
29 
30 #include "3d_cache/sg/sg_shape.h"
31 #include "3d_cache/sg/sg_faceset.h"
33 #include "3d_cache/sg/sg_helpers.h"
35 #include "3d_cache/sg/sg_coords.h"
36 #include "3d_cache/sg/sg_colors.h"
37 #include "3d_cache/sg/sg_normals.h"
38 
39 
40 SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
41 {
43  m_Appearance = nullptr;
44  m_RAppearance = nullptr;
45  m_FaceSet = nullptr;
46  m_RFaceSet = nullptr;
47 
48  if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
49  {
50  m_Parent = nullptr;
51 
52  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] inappropriate parent to SGSHAPE (type %d)" ),
53  __FILE__, __FUNCTION__, __LINE__, aParent->GetNodeType() );
54  }
55  else if( nullptr != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
56  {
57  m_Parent->AddChildNode( this );
58  }
59 }
60 
61 
63 {
64  // drop references
65  if( m_RAppearance )
66  {
67  m_RAppearance->delNodeRef( this );
68  m_RAppearance = nullptr;
69  }
70 
71  if( m_RFaceSet )
72  {
73  m_RFaceSet->delNodeRef( this );
74  m_RFaceSet = nullptr;
75  }
76 
77  // delete objects
78  if( m_Appearance )
79  {
80  m_Appearance->SetParent( nullptr, false );
81  delete m_Appearance;
82  m_Appearance = nullptr;
83  }
84 
85  if( m_FaceSet )
86  {
87  m_FaceSet->SetParent( nullptr, false );
88  delete m_FaceSet;
89  m_FaceSet = nullptr;
90  }
91 }
92 
93 
94 bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
95 {
96  if( nullptr != m_Parent )
97  {
98  if( aParent == m_Parent )
99  return true;
100 
101  // handle the change in parents
102  if( notify )
103  m_Parent->unlinkChildNode( this );
104 
105  m_Parent = nullptr;
106 
107  if( nullptr == aParent )
108  return true;
109  }
110 
111  // only a SGTRANSFORM may be parent to a SGSHAPE
112  if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
113  return false;
114 
115  m_Parent = aParent;
116 
117  if( m_Parent )
118  m_Parent->AddChildNode( this );
119 
120  return true;
121 }
122 
123 
124 SGNODE* SGSHAPE::FindNode( const char* aNodeName, const SGNODE* aCaller )
125 {
126  if( nullptr == aNodeName || 0 == aNodeName[0] )
127  return nullptr;
128 
129  if( !m_Name.compare( aNodeName ) )
130  return this;
131 
132  SGNODE* tmp = nullptr;
133 
134  if( nullptr != m_Appearance )
135  {
136  tmp = m_Appearance->FindNode( aNodeName, this );
137 
138  if( tmp )
139  {
140  return tmp;
141  }
142  }
143 
144  if( nullptr != m_FaceSet )
145  {
146  tmp = m_FaceSet->FindNode( aNodeName, this );
147 
148  if( tmp )
149  {
150  return tmp;
151  }
152  }
153 
154  // query the parent if appropriate
155  if( aCaller == m_Parent || nullptr == m_Parent )
156  return nullptr;
157 
158  return m_Parent->FindNode( aNodeName, this );
159 }
160 
161 
162 void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
163 {
164  if( nullptr == aNode )
165  return;
166 
167  if( isChild )
168  {
169  if( aNode == m_Appearance )
170  {
171  m_Appearance = nullptr;
172  return;
173  }
174 
175  if( aNode == m_FaceSet )
176  {
177  m_FaceSet = nullptr;
178  return;
179  }
180  }
181  else
182  {
183  if( aNode == m_RAppearance )
184  {
185  delNodeRef( this );
186  m_RAppearance = nullptr;
187  return;
188  }
189 
190  if( aNode == m_RFaceSet )
191  {
192  delNodeRef( this );
193  m_RFaceSet = nullptr;
194  return;
195  }
196  }
197 
198  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] unlinkNode() did not find its target" ),
199  __FILE__, __FUNCTION__, __LINE__ );
200 }
201 
202 
203 void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
204 {
205  unlinkNode( aNode, true );
206 }
207 
208 
209 void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
210 {
211  unlinkNode( aNode, false );
212 }
213 
214 
215 bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
216 {
217  wxCHECK( aNode, false );
218 
219  if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
220  {
221  if( m_Appearance || m_RAppearance )
222  {
223  if( aNode != m_Appearance && aNode != m_RAppearance )
224  {
225  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple Appearance "
226  "nodes" ),
227  __FILE__, __FUNCTION__, __LINE__ );
228 
229  return false;
230  }
231 
232  return true;
233  }
234 
235  if( isChild )
236  {
237  m_Appearance = (SGAPPEARANCE*)aNode;
238  m_Appearance->SetParent( this );
239  }
240  else
241  {
242  m_RAppearance = (SGAPPEARANCE*)aNode;
243  m_RAppearance->addNodeRef( this );
244  }
245 
246  return true;
247  }
248 
249  if( S3D::SGTYPE_FACESET == aNode->GetNodeType() )
250  {
251  if( m_FaceSet || m_RFaceSet )
252  {
253  if( aNode != m_FaceSet && aNode != m_RFaceSet )
254  {
255  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] assigning multiple FaceSet nodes" ),
256  __FILE__, __FUNCTION__, __LINE__ );
257 
258  return false;
259  }
260 
261  return true;
262  }
263 
264  if( isChild )
265  {
266  m_FaceSet = (SGFACESET*)aNode;
267  m_FaceSet->SetParent( this );
268  }
269  else
270  {
271  m_RFaceSet = (SGFACESET*)aNode;
272  m_RFaceSet->addNodeRef( this );
273  }
274 
275  return true;
276  }
277 
278  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] object %s is not a valid type for this "
279  "object (%d)" ),
280  __FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
281 
282  return false;
283 }
284 
285 
287 {
288  return addNode( aNode, false );
289 }
290 
291 
293 {
294  return addNode( aNode, true );
295 }
296 
297 
299 {
300  m_written = false;
301 
302  // rename this node
303  m_Name.clear();
304  GetName();
305 
306  // rename Appearance
307  if( m_Appearance )
309 
310  // rename FaceSet
311  if( m_FaceSet )
313 }
314 
315 
316 bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
317 {
319  {
320  return false;
321  }
322 
323  if( aReuseFlag )
324  {
325  if( !m_written )
326  {
327  aFile << "DEF " << GetName() << " Shape {\n";
328  m_written = true;
329  }
330  else
331  {
332  aFile << " USE " << GetName() << "\n";
333  return true;
334  }
335  }
336  else
337  {
338  aFile << " Shape {\n";
339  }
340 
341  if( m_Appearance )
342  m_Appearance->WriteVRML( aFile, aReuseFlag );
343 
344  if( m_RAppearance )
345  m_RAppearance->WriteVRML( aFile, aReuseFlag );
346 
347  if( m_FaceSet )
348  m_FaceSet->WriteVRML( aFile, aReuseFlag );
349 
350  if( m_RFaceSet )
351  m_RFaceSet->WriteVRML( aFile, aReuseFlag );
352 
353  aFile << "}\n";
354 
355  return true;
356 }
357 
358 
359 bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
360 {
361  if( nullptr == parentNode )
362  {
363  wxCHECK( m_Parent, false );
364 
365  SGNODE* np = m_Parent;
366 
367  while( nullptr != np->GetParent() )
368  np = np->GetParent();
369 
370  if( np->WriteCache( aFile, nullptr ) )
371  {
372  m_written = true;
373  return true;
374  }
375 
376  return false;
377  }
378 
379  wxCHECK( parentNode == m_Parent, false );
380 
381  if( !aFile.good() )
382  {
383  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [BUG] bad stream" ),
384  __FILE__, __FUNCTION__, __LINE__ );
385 
386  return false;
387  }
388 
389  // check if any references are unwritten and swap parents if so
390  if( nullptr != m_RAppearance && !m_RAppearance->isWritten() )
391  m_RAppearance->SwapParent(this);
392 
393  if( nullptr != m_RFaceSet && !m_RFaceSet->isWritten() )
394  m_RFaceSet->SwapParent( this );
395 
396  aFile << "[" << GetName() << "]";
397  #define NITEMS 4
398  bool items[NITEMS];
399  int i;
400 
401  for( i = 0; i < NITEMS; ++i )
402  items[i] = 0;
403 
404  i = 0;
405 
406  if( nullptr != m_Appearance )
407  items[i] = true;
408 
409  ++i;
410 
411  if( nullptr != m_RAppearance )
412  items[i] = true;
413 
414  ++i;
415 
416  if( nullptr != m_FaceSet )
417  items[i] = true;
418 
419  ++i;
420 
421  if( nullptr != m_RFaceSet )
422  items[i] = true;
423 
424  for( int jj = 0; jj < NITEMS; ++jj )
425  aFile.write( (char*)&items[jj], sizeof(bool) );
426 
427  if( items[0] )
428  m_Appearance->WriteCache( aFile, this );
429 
430  if( items[1] )
431  aFile << "[" << m_RAppearance->GetName() << "]";
432 
433  if( items[2] )
434  m_FaceSet->WriteCache( aFile, this );
435 
436  if( items[3] )
437  aFile << "[" << m_RFaceSet->GetName() << "]";
438 
439  if( aFile.fail() )
440  return false;
441 
442  m_written = true;
443  return true;
444 }
445 
446 
447 bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
448 {
449  wxCHECK( m_Appearance == nullptr && m_RAppearance == nullptr && m_FaceSet == nullptr &&
450  m_RFaceSet == nullptr, false );
451 
452  #define NITEMS 4
453  bool items[NITEMS];
454 
455  for( int i = 0; i < NITEMS; ++i )
456  aFile.read( (char*)&items[i], sizeof(bool) );
457 
458  if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
459  {
460  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; multiple item definitions "
461  "at position %ul" ),
462  __FILE__, __FUNCTION__, __LINE__,
463  static_cast<unsigned long>( aFile.tellg() ) );
464 
465  return false;
466  }
467 
468  std::string name;
469 
470  if( items[0] )
471  {
472  if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
473  {
474  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child appearance "
475  "tag at position %ul" ),
476  __FILE__, __FUNCTION__, __LINE__,
477  static_cast<unsigned long>( aFile.tellg() ) );
478 
479  return false;
480  }
481 
482  m_Appearance = new SGAPPEARANCE( this );
483  m_Appearance->SetName( name.c_str() );
484 
485  if( !m_Appearance->ReadCache( aFile, this ) )
486  {
487  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading appearance "
488  "'%s'" ),
489  __FILE__, __FUNCTION__, __LINE__, name );
490 
491  return false;
492  }
493  }
494 
495  if( items[1] )
496  {
497  if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
498  {
499  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref appearance tag "
500  "at position %ul" ),
501  __FILE__, __FUNCTION__, __LINE__,
502  static_cast<unsigned long>( aFile.tellg() ) );
503 
504  return false;
505  }
506 
507  SGNODE* np = FindNode( name.c_str(), this );
508 
509  if( !np )
510  {
511  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref "
512  "appearance '%s'" ),
513  __FILE__, __FUNCTION__, __LINE__,
514  name );
515 
516  return false;
517  }
518 
519  if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
520  {
521  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not "
522  "SGAPPEARANCE '%s'" ),
523  __FILE__, __FUNCTION__, __LINE__,
524  name );
525 
526  return false;
527  }
528 
530  m_RAppearance->addNodeRef( this );
531  }
532 
533  if( items[2] )
534  {
535  if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
536  {
537  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad child face set tag "
538  "at position %ul" ),
539  __FILE__, __FUNCTION__, __LINE__,
540  static_cast<unsigned long>( aFile.tellg() ) );
541 
542  return false;
543  }
544 
545  m_FaceSet = new SGFACESET( this );
546  m_FaceSet->SetName( name.c_str() );
547 
548  if( !m_FaceSet->ReadCache( aFile, this ) )
549  {
550  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data while reading face set "
551  "'%s'" ),
552  __FILE__, __FUNCTION__, __LINE__, name );
553 
554  return false;
555  }
556  }
557 
558  if( items[3] )
559  {
560  if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
561  {
562  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data; bad ref face set tag at "
563  "position %ul" ),
564  __FILE__, __FUNCTION__, __LINE__,
565  static_cast<unsigned long>( aFile.tellg() ) );
566 
567  return false;
568  }
569 
570  SGNODE* np = FindNode( name.c_str(), this );
571 
572  if( !np )
573  {
574  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: cannot find ref face "
575  "set '%s'" ),
576  __FILE__, __FUNCTION__, __LINE__,
577  name );
578 
579  return false;
580  }
581 
582  if( S3D::SGTYPE_FACESET != np->GetNodeType() )
583  {
584  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] corrupt data: type is not SGFACESET "
585  "'%s'" ),
586  __FILE__, __FUNCTION__, __LINE__,
587  name );
588 
589  return false;
590  }
591 
592  m_RFaceSet = (SGFACESET*)np;
593  m_RFaceSet->addNodeRef( this );
594  }
595 
596  if( aFile.fail() )
597  return false;
598 
599  return true;
600 }
601 
602 
603 bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
604  std::vector< SMESH >& meshes )
605 {
606  SMESH m;
607  S3D::INIT_SMESH( m );
608 
610  SGFACESET* pf = m_FaceSet;
611 
612  if( nullptr == pa )
613  pa = m_RAppearance;
614 
615  if( nullptr == pf )
616  pf = m_RFaceSet;
617 
618  // no face sets = nothing to render, which is valid though pointless
619  if( nullptr == pf )
620  return true;
621 
622  if( !pf->validate() )
623  {
624  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; inconsistent data" ),
625  __FILE__, __FUNCTION__, __LINE__ );
626 
627  return true;
628  }
629 
630  if( nullptr == pa )
631  {
632  m.m_MaterialIdx = 0;
633  }
634  else
635  {
636  int idx;
637 
638  if( !S3D::GetMatIndex( materials, pa, idx ) )
639  {
640  m.m_MaterialIdx = 0;
641  }
642  else
643  {
644  m.m_MaterialIdx = idx;
645  }
646  }
647 
648  SGCOLORS* pc = pf->m_Colors;
649  SGCOORDS* pv = pf->m_Coords;
650  SGCOORDINDEX* vidx = pf->m_CoordIndices;
651  SGNORMALS* pn = pf->m_Normals;
652 
653  if( nullptr == pc )
654  pc = pf->m_RColors;
655 
656  if( nullptr == pv )
657  pv = pf->m_RCoords;
658 
659  if( nullptr == pn )
660  pn = pf->m_RNormals;
661 
662  // set the vertex points and indices
663  size_t nCoords = 0;
664  SGPOINT* pCoords = nullptr;
665  pv->GetCoordsList( nCoords, pCoords );
666 
667  size_t nColors = 0;
668  SGCOLOR* pColors = nullptr;
669 
670  if( pc )
671  {
672  // check the vertex colors
673  pc->GetColorList( nColors, pColors );
674 
675  if( nColors < nCoords )
676  {
677  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough colors per "
678  "vertex (%ul vs %ul)" ),
679  __FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( nColors ),
680  static_cast<unsigned long>( nCoords ) );
681 
682  return true;
683  }
684  }
685 
686  // set the vertex indices
687  size_t nvidx = 0;
688  int* lv = nullptr;
689  vidx->GetIndices( nvidx, lv );
690 
691  // note: reduce the vertex set to include only the referenced vertices
692  std::vector< int > vertices; // store the list of temp vertex indices
693  std::map< int, unsigned int > indexmap; // map temp vertex to true vertex
694  std::map< int, unsigned int >::iterator mit;
695 
696  for( unsigned int i = 0; i < nvidx; ++i )
697  {
698  mit = indexmap.find( lv[i] );
699 
700  if( mit == indexmap.end() )
701  {
702  indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
703  vertices.push_back( lv[i] );
704  }
705  }
706 
707  if( vertices.size() < 3 )
708  {
709  wxLogTrace( MASK_3D_SG, wxT( "%s:%s:%d * [INFO] bad model; not enough vertices" ),
710  __FILE__, __FUNCTION__, __LINE__ );
711 
712  return true;
713  }
714 
715  // construct the final vertex/color list
716  SFVEC3F* lColors = nullptr;
717  SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
718  int ti;
719 
720  if( pc )
721  {
722  lColors = new SFVEC3F[vertices.size()];
723  m.m_Color = lColors;
724  }
725 
726  if( pc )
727  {
728  for( size_t i = 0; i < vertices.size(); ++i )
729  {
730  ti = vertices[i];
731  glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
732  pt = (*aTransform) * pt;
733  pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
734  lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
735  }
736  }
737  else
738  {
739  for( size_t i = 0; i < vertices.size(); ++i )
740  {
741  ti = vertices[i];
742  glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
743  pt = (*aTransform) * pt;
744  lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
745  }
746  }
747 
748  m.m_VertexSize = (unsigned int) vertices.size();
749  m.m_Positions = lCoords;
750  unsigned int* lvidx = new unsigned int[ nvidx ];
751 
752  for( unsigned int i = 0; i < nvidx; ++i )
753  {
754  mit = indexmap.find( lv[i] );
755  lvidx[i] = mit->second;
756  }
757 
758  m.m_FaceIdxSize = (unsigned int )nvidx;
759  m.m_FaceIdx = lvidx;
760 
761  // set the per-vertex normals
762  size_t nNorms = 0;
763  SGVECTOR* pNorms = nullptr;
764  double x, y, z;
765 
766  pn->GetNormalList( nNorms, pNorms );
767  SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ];
768 
769  for( size_t i = 0; i < vertices.size(); ++i )
770  {
771  ti = vertices[i];
772  pNorms[ti].GetVector( x, y, z );
773  glm::dvec4 pt( x, y, z, 0.0 );
774  pt = (*aTransform) * pt;
775 
776  lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z );
777  }
778 
779  m.m_Normals = lNorms;
780  meshes.push_back( m );
781 
782  return true;
783 }
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
Define an indexed face set for a scenegraph.
Definition: sg_faceset.h:46
virtual ~SGSHAPE()
Definition: sg_shape.cpp:62
Define an RGB color set for a scenegraph object.
Definition: sg_colors.h:38
void addNodeRef(SGNODE *aNode)
Add a pointer to a node which references this node, but does not own.
Definition: sg_node.cpp:170
SGCOORDINDEX * m_CoordIndices
Definition: sg_faceset.h:81
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition: sg_node.h:227
An object to maintain a coordinate index list.
Definition: sg_coordindex.h:42
void unlinkChildNode(const SGNODE *aNode) override
Remove references to an owned child.
Definition: sg_shape.cpp:203
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: sg_shape.cpp:447
bool GetColorList(size_t &aListSize, SGCOLOR *&aColorList)
Definition: sg_colors.cpp:128
SGCOLORS * m_Colors
Definition: sg_faceset.h:79
void unlinkNode(const SGNODE *aNode, bool isChild)
Definition: sg_shape.cpp:162
bool GetMatIndex(MATLIST &aList, SGNODE *aNode, int &aIndex)
Definition: sg_node.cpp:245
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_shape.cpp:316
bool addNode(SGNODE *aNode, bool isChild)
Definition: sg_shape.cpp:215
Define a vertex coordinate set for a scenegraph object.
Definition: sg_coords.h:40
SGFACESET * m_RFaceSet
Definition: sg_shape.h:77
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: sg_faceset.cpp:493
bool GetCoordsList(size_t &aListSize, SGPOINT *&aCoordsList)
Definition: sg_coords.cpp:130
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
void delNodeRef(const SGNODE *aNode)
Remove a pointer to a node which references this node, but does not own.
Definition: sg_node.cpp:185
bool Prepare(const glm::dmat4 *aTransform, S3D::MATLIST &materials, std::vector< SMESH > &meshes)
Definition: sg_shape.cpp:603
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: sg_shape.cpp:359
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
void GetColor(float &aRedVal, float &aGreenVal, float &aBlueVal) const noexcept
Definition: sg_base.cpp:59
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
SGCOLORS * m_RColors
Definition: sg_faceset.h:85
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: sg_faceset.cpp:601
Define a set of vertex normals for a scene graph object.
Definition: sg_normals.h:38
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: sg_faceset.cpp:413
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) noexcept override
Search the tree of linked nodes and return a reference to the first node found with the given name.
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) override
Search the tree of linked nodes and return a reference to the first node found with the given name.
Definition: sg_faceset.cpp:149
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
const char * GetName(void)
Definition: sg_node.cpp:146
SGCOORDS * m_RCoords
Definition: sg_faceset.h:86
SGAPPEARANCE * m_Appearance
Definition: sg_shape.h:72
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition: sg_node.h:230
bool AddRefNode(SGNODE *aNode) override
Definition: sg_shape.cpp:286
S3D::SGTYPES ReadTag(std::istream &aFile, std::string &aName)
Read the text tag of a binary cache file which is the NodeTag and unique ID number combined.
Definition: sg_helpers.cpp:195
#define NITEMS
virtual void unlinkChildNode(const SGNODE *aNode)=0
Remove references to an owned child.
bool GetIndices(size_t &nIndices, int *&aIndexList)
Retrieve the number of indices and a pointer to the list.
Definition: sg_index.cpp:126
bool SwapParent(SGNODE *aNewParent)
Swap the ownership with the given parent.
Definition: sg_node.cpp:116
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: sg_shape.cpp:298
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
void INIT_SMESH(SMESH &aMesh) noexcept
Definition: sg_node.cpp:276
SGFACESET * m_FaceSet
Definition: sg_shape.h:73
bool validate(void)
Definition: sg_faceset.cpp:854
virtual SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller)=0
Search the tree of linked nodes and return a reference to the first node found with the given name.
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) override
Search the tree of linked nodes and return a reference to the first node found with the given name.
Definition: sg_shape.cpp:124
SGNODE * GetParent(void) const noexcept
Returns a pointer to the parent SGNODE of this object or NULL if the object has no parent (ie.
Definition: sg_node.cpp:110
void SetName(const char *aName)
Definition: sg_node.cpp:155
std::string m_Name
name to use for referencing the entity by name.
Definition: sg_node.h:229
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: sg_faceset.cpp:119
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition: sg_node.h:228
SGCOORDS * m_Coords
Definition: sg_faceset.h:80
const char * name
Definition: DXF_plotter.cpp:56
glm::vec3 SFVEC3F
Definition: xv3d_types.h:44
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
SGSHAPE(SGNODE *aParent)
Definition: sg_shape.cpp:40
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_faceset.cpp:438
bool AddChildNode(SGNODE *aNode) override
Definition: sg_shape.cpp:292
bool isWritten(void) noexcept
Return true if the object had already been written to a cache file or VRML file.
Definition: sg_node.h:220
virtual bool AddChildNode(SGNODE *aNode)=0
SGAPPEARANCE * m_RAppearance
Definition: sg_shape.h:76
SGNORMALS * m_Normals
Definition: sg_faceset.h:82
Define a number of macros to aid in repetitious code which is probably best expressed as a preprocess...
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
SGNORMALS * m_RNormals
Definition: sg_faceset.h:87
void GetVector(double &aXVal, double &aYVal, double &aZVal) const noexcept
Definition: sg_base.cpp:225
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
void unlinkRefNode(const SGNODE *aNode) override
Remove pointers to a referenced node.
Definition: sg_shape.cpp:209
bool GetNormalList(size_t &aListSize, SGVECTOR *&aNormalList)
Definition: sg_normals.cpp:129
Defines the generic material appearance of a scenegraph object.
Definition: sg_appearance.h:37
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: sg_shape.cpp:94