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 <cirilo.bernardo@gmail.com>
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, "%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, "%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, "%s:%s:%d * [BUG] assigning multiple Appearance nodes",
226  __FILE__, __FUNCTION__, __LINE__ );
227 
228  return false;
229  }
230 
231  return true;
232  }
233 
234  if( isChild )
235  {
236  m_Appearance = (SGAPPEARANCE*)aNode;
237  m_Appearance->SetParent( this );
238  }
239  else
240  {
241  m_RAppearance = (SGAPPEARANCE*)aNode;
242  m_RAppearance->addNodeRef( this );
243  }
244 
245  return true;
246  }
247 
248  if( S3D::SGTYPE_FACESET == aNode->GetNodeType() )
249  {
250  if( m_FaceSet || m_RFaceSet )
251  {
252  if( aNode != m_FaceSet && aNode != m_RFaceSet )
253  {
254  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [BUG] assigning multiple FaceSet nodes",
255  __FILE__, __FUNCTION__, __LINE__ );
256 
257  return false;
258  }
259 
260  return true;
261  }
262 
263  if( isChild )
264  {
265  m_FaceSet = (SGFACESET*)aNode;
266  m_FaceSet->SetParent( this );
267  }
268  else
269  {
270  m_RFaceSet = (SGFACESET*)aNode;
271  m_RFaceSet->addNodeRef( this );
272  }
273 
274  return true;
275  }
276 
277  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [BUG] object %s is not a valid type for this object (%d)",
278  __FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
279 
280  return false;
281 }
282 
283 
285 {
286  return addNode( aNode, false );
287 }
288 
289 
291 {
292  return addNode( aNode, true );
293 }
294 
295 
297 {
298  m_written = false;
299 
300  // rename this node
301  m_Name.clear();
302  GetName();
303 
304  // rename Appearance
305  if( m_Appearance )
307 
308  // rename FaceSet
309  if( m_FaceSet )
311 }
312 
313 
314 bool SGSHAPE::WriteVRML( std::ostream& aFile, bool aReuseFlag )
315 {
317  {
318  return false;
319  }
320 
321  if( aReuseFlag )
322  {
323  if( !m_written )
324  {
325  aFile << "DEF " << GetName() << " Shape {\n";
326  m_written = true;
327  }
328  else
329  {
330  aFile << " USE " << GetName() << "\n";
331  return true;
332  }
333  }
334  else
335  {
336  aFile << " Shape {\n";
337  }
338 
339  if( m_Appearance )
340  m_Appearance->WriteVRML( aFile, aReuseFlag );
341 
342  if( m_RAppearance )
343  m_RAppearance->WriteVRML( aFile, aReuseFlag );
344 
345  if( m_FaceSet )
346  m_FaceSet->WriteVRML( aFile, aReuseFlag );
347 
348  if( m_RFaceSet )
349  m_RFaceSet->WriteVRML( aFile, aReuseFlag );
350 
351  aFile << "}\n";
352 
353  return true;
354 }
355 
356 
357 bool SGSHAPE::WriteCache( std::ostream& aFile, SGNODE* parentNode )
358 {
359  if( nullptr == parentNode )
360  {
361  wxCHECK( m_Parent, false );
362 
363  SGNODE* np = m_Parent;
364 
365  while( nullptr != np->GetParent() )
366  np = np->GetParent();
367 
368  if( np->WriteCache( aFile, nullptr ) )
369  {
370  m_written = true;
371  return true;
372  }
373 
374  return false;
375  }
376 
377  wxCHECK( parentNode == m_Parent, false );
378 
379  if( !aFile.good() )
380  {
381  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [BUG] bad stream", __FILE__, __FUNCTION__, __LINE__ );
382 
383  return false;
384  }
385 
386  // check if any references are unwritten and swap parents if so
387  if( nullptr != m_RAppearance && !m_RAppearance->isWritten() )
388  m_RAppearance->SwapParent(this);
389 
390  if( nullptr != m_RFaceSet && !m_RFaceSet->isWritten() )
391  m_RFaceSet->SwapParent( this );
392 
393  aFile << "[" << GetName() << "]";
394  #define NITEMS 4
395  bool items[NITEMS];
396  int i;
397 
398  for( i = 0; i < NITEMS; ++i )
399  items[i] = 0;
400 
401  i = 0;
402 
403  if( nullptr != m_Appearance )
404  items[i] = true;
405 
406  ++i;
407 
408  if( nullptr != m_RAppearance )
409  items[i] = true;
410 
411  ++i;
412 
413  if( nullptr != m_FaceSet )
414  items[i] = true;
415 
416  ++i;
417 
418  if( nullptr != m_RFaceSet )
419  items[i] = true;
420 
421  for( int jj = 0; jj < NITEMS; ++jj )
422  aFile.write( (char*)&items[jj], sizeof(bool) );
423 
424  if( items[0] )
425  m_Appearance->WriteCache( aFile, this );
426 
427  if( items[1] )
428  aFile << "[" << m_RAppearance->GetName() << "]";
429 
430  if( items[2] )
431  m_FaceSet->WriteCache( aFile, this );
432 
433  if( items[3] )
434  aFile << "[" << m_RFaceSet->GetName() << "]";
435 
436  if( aFile.fail() )
437  return false;
438 
439  m_written = true;
440  return true;
441 }
442 
443 
444 bool SGSHAPE::ReadCache( std::istream& aFile, SGNODE* parentNode )
445 {
446  wxCHECK( m_Appearance == nullptr && m_RAppearance == nullptr && m_FaceSet == nullptr &&
447  m_RFaceSet == nullptr, false );
448 
449  #define NITEMS 4
450  bool items[NITEMS];
451 
452  for( int i = 0; i < NITEMS; ++i )
453  aFile.read( (char*)&items[i], sizeof(bool) );
454 
455  if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
456  {
457  wxLogTrace( MASK_3D_SG,
458  "%s:%s:%d * [INFO] corrupt data; multiple item definitions at position %ul",
459  __FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( aFile.tellg() ) );
460 
461  return false;
462  }
463 
464  std::string name;
465 
466  if( items[0] )
467  {
468  if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
469  {
470  wxLogTrace( MASK_3D_SG,
471  "%s:%s:%d * [INFO] corrupt data; bad child appearance tag at position %ul",
472  __FILE__, __FUNCTION__, __LINE__,
473  static_cast<unsigned long>( aFile.tellg() ) );
474 
475  return false;
476  }
477 
478  m_Appearance = new SGAPPEARANCE( this );
479  m_Appearance->SetName( name.c_str() );
480 
481  if( !m_Appearance->ReadCache( aFile, this ) )
482  {
483  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] corrupt data while reading appearance '%s'",
484  __FILE__, __FUNCTION__, __LINE__, name );
485 
486  return false;
487  }
488  }
489 
490  if( items[1] )
491  {
492  if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
493  {
494  wxLogTrace( MASK_3D_SG,
495  "%s:%s:%d * [INFO] corrupt data; bad ref appearance tag at position %ul",
496  __FILE__, __FUNCTION__, __LINE__,
497  static_cast<unsigned long>( aFile.tellg() ) );
498 
499  return false;
500  }
501 
502  SGNODE* np = FindNode( name.c_str(), this );
503 
504  if( !np )
505  {
506  wxLogTrace( MASK_3D_SG,
507  "%s:%s:%d * [INFO] corrupt data: cannot find ref appearance '%s'",
508  __FILE__, __FUNCTION__, __LINE__, name );
509 
510  return false;
511  }
512 
513  if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
514  {
515  wxLogTrace( MASK_3D_SG,
516  "%s:%s:%d * [INFO] corrupt data: type is not SGAPPEARANCE '%s'",
517  __FILE__, __FUNCTION__, __LINE__, name );
518 
519  return false;
520  }
521 
523  m_RAppearance->addNodeRef( this );
524  }
525 
526  if( items[2] )
527  {
528  if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
529  {
530  wxLogTrace( MASK_3D_SG,
531  "%s:%s:%d * [INFO] corrupt data; bad child face set tag at position %ul",
532  __FILE__, __FUNCTION__, __LINE__,
533  static_cast<unsigned long>( aFile.tellg() ) );
534 
535  return false;
536  }
537 
538  m_FaceSet = new SGFACESET( this );
539  m_FaceSet->SetName( name.c_str() );
540 
541  if( !m_FaceSet->ReadCache( aFile, this ) )
542  {
543  wxLogTrace( MASK_3D_SG,
544  "%s:%s:%d * [INFO] corrupt data while reading face set '%s'",
545  __FILE__, __FUNCTION__, __LINE__, name );
546 
547  return false;
548  }
549  }
550 
551  if( items[3] )
552  {
553  if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
554  {
555  wxLogTrace( MASK_3D_SG,
556  "%s:%s:%d * [INFO] corrupt data; bad ref face set tag at position %ul",
557  __FILE__, __FUNCTION__, __LINE__,
558  static_cast<unsigned long>( aFile.tellg() ) );
559 
560  return false;
561  }
562 
563  SGNODE* np = FindNode( name.c_str(), this );
564 
565  if( !np )
566  {
567  wxLogTrace( MASK_3D_SG,
568  "%s:%s:%d * [INFO] corrupt data: cannot find ref face set '%s'",
569  __FILE__, __FUNCTION__, __LINE__, name );
570 
571  return false;
572  }
573 
574  if( S3D::SGTYPE_FACESET != np->GetNodeType() )
575  {
576  wxLogTrace( MASK_3D_SG,
577  "%s:%s:%d * [INFO] corrupt data: type is not SGFACESET '%s'",
578  __FILE__, __FUNCTION__, __LINE__, name );
579 
580  return false;
581  }
582 
583  m_RFaceSet = (SGFACESET*)np;
584  m_RFaceSet->addNodeRef( this );
585  }
586 
587  if( aFile.fail() )
588  return false;
589 
590  return true;
591 }
592 
593 
594 bool SGSHAPE::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
595  std::vector< SMESH >& meshes )
596 {
597  SMESH m;
598  S3D::INIT_SMESH( m );
599 
601  SGFACESET* pf = m_FaceSet;
602 
603  if( nullptr == pa )
604  pa = m_RAppearance;
605 
606  if( nullptr == pf )
607  pf = m_RFaceSet;
608 
609  // no face sets = nothing to render, which is valid though pointless
610  if( nullptr == pf )
611  return true;
612 
613  if( !pf->validate() )
614  {
615  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad model; inconsistent data",
616  __FILE__, __FUNCTION__, __LINE__ );
617 
618  return true;
619  }
620 
621  if( nullptr == pa )
622  {
623  m.m_MaterialIdx = 0;
624  }
625  else
626  {
627  int idx;
628 
629  if( !S3D::GetMatIndex( materials, pa, idx ) )
630  {
631  m.m_MaterialIdx = 0;
632  }
633  else
634  {
635  m.m_MaterialIdx = idx;
636  }
637  }
638 
639  SGCOLORS* pc = pf->m_Colors;
640  SGCOORDS* pv = pf->m_Coords;
641  SGCOORDINDEX* vidx = pf->m_CoordIndices;
642  SGNORMALS* pn = pf->m_Normals;
643 
644  if( nullptr == pc )
645  pc = pf->m_RColors;
646 
647  if( nullptr == pv )
648  pv = pf->m_RCoords;
649 
650  if( nullptr == pn )
651  pn = pf->m_RNormals;
652 
653  // set the vertex points and indices
654  size_t nCoords = 0;
655  SGPOINT* pCoords = nullptr;
656  pv->GetCoordsList( nCoords, pCoords );
657 
658  size_t nColors = 0;
659  SGCOLOR* pColors = nullptr;
660 
661  if( pc )
662  {
663  // check the vertex colors
664  pc->GetColorList( nColors, pColors );
665 
666  if( nColors < nCoords )
667  {
668  wxLogTrace( MASK_3D_SG,
669  "%s:%s:%d * [INFO] bad model; not enough colors per vertex (%ul vs %ul)",
670  __FILE__, __FUNCTION__, __LINE__, static_cast<unsigned long>( nColors ),
671  static_cast<unsigned long>( nCoords ) );
672 
673  return true;
674  }
675  }
676 
677  // set the vertex indices
678  size_t nvidx = 0;
679  int* lv = nullptr;
680  vidx->GetIndices( nvidx, lv );
681 
682  // note: reduce the vertex set to include only the referenced vertices
683  std::vector< int > vertices; // store the list of temp vertex indices
684  std::map< int, unsigned int > indexmap; // map temp vertex to true vertex
685  std::map< int, unsigned int >::iterator mit;
686 
687  for( unsigned int i = 0; i < nvidx; ++i )
688  {
689  mit = indexmap.find( lv[i] );
690 
691  if( mit == indexmap.end() )
692  {
693  indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
694  vertices.push_back( lv[i] );
695  }
696  }
697 
698  if( vertices.size() < 3 )
699  {
700  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad model; not enough vertices",
701  __FILE__, __FUNCTION__, __LINE__ );
702 
703  return true;
704  }
705 
706  // construct the final vertex/color list
707  SFVEC3F* lColors = nullptr;
708  SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
709  int ti;
710 
711  if( pc )
712  {
713  lColors = new SFVEC3F[vertices.size()];
714  m.m_Color = lColors;
715  }
716 
717  if( pc )
718  {
719  for( size_t i = 0; i < vertices.size(); ++i )
720  {
721  ti = vertices[i];
722  glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
723  pt = (*aTransform) * pt;
724  pColors[ti].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
725  lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
726  }
727  }
728  else
729  {
730  for( size_t i = 0; i < vertices.size(); ++i )
731  {
732  ti = vertices[i];
733  glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
734  pt = (*aTransform) * pt;
735  lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
736  }
737  }
738 
739  m.m_VertexSize = (unsigned int) vertices.size();
740  m.m_Positions = lCoords;
741  unsigned int* lvidx = new unsigned int[ nvidx ];
742 
743  for( unsigned int i = 0; i < nvidx; ++i )
744  {
745  mit = indexmap.find( lv[i] );
746  lvidx[i] = mit->second;
747  }
748 
749  m.m_FaceIdxSize = (unsigned int )nvidx;
750  m.m_FaceIdx = lvidx;
751 
752  // set the per-vertex normals
753  size_t nNorms = 0;
754  SGVECTOR* pNorms = nullptr;
755  double x, y, z;
756 
757  pn->GetNormalList( nNorms, pNorms );
758  SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ];
759 
760  for( size_t i = 0; i < vertices.size(); ++i )
761  {
762  ti = vertices[i];
763  pNorms[ti].GetVector( x, y, z );
764  glm::dvec4 pt( x, y, z, 0.0 );
765  pt = (*aTransform) * pt;
766 
767  lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z );
768  }
769 
770  m.m_Normals = lNorms;
771  meshes.push_back( m );
772 
773  return true;
774 }
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:444
bool GetColorList(size_t &aListSize, SGCOLOR *&aColorList)
Definition: sg_colors.cpp:127
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:243
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: sg_shape.cpp:314
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:488
bool GetCoordsList(size_t &aListSize, SGPOINT *&aCoordsList)
Definition: sg_coords.cpp:129
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:594
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: sg_shape.cpp:357
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:595
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:408
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:147
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:284
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:124
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:296
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
void INIT_SMESH(SMESH &aMesh) noexcept
Definition: sg_node.cpp:274
SGFACESET * m_FaceSet
Definition: sg_shape.h:73
bool validate(void)
Definition: sg_faceset.cpp:831
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:117
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:59
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:433
bool AddChildNode(SGNODE *aNode) override
Definition: sg_shape.cpp:290
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:127
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