KiCad PCB EDA Suite
scenegraph.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 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 #define GLM_FORCE_RADIANS
26 
27 #include <iostream>
28 #include <sstream>
29 #include <glm/glm.hpp>
30 #include <glm/ext.hpp>
31 #include <wx/log.h>
32 
33 #include "3d_cache/sg/scenegraph.h"
34 #include "3d_cache/sg/sg_shape.h"
35 #include "3d_cache/sg/sg_helpers.h"
36 
37 
38 SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
39 {
41  rotation_angle = 0.0;
42  scale_angle = 0.0;
43 
44  scale.x = 1.0;
45  scale.y = 1.0;
46  scale.z = 1.0;
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 SCENEGRAPH (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
67 
68  // delete owned objects
71 }
72 
73 
74 bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
75 {
76  if( nullptr != m_Parent )
77  {
78  if( aParent == m_Parent )
79  return true;
80 
81  // handle the change in parents
82  if( notify )
83  m_Parent->unlinkChildNode( this );
84 
85  m_Parent = nullptr;
86 
87  if( nullptr == aParent )
88  return true;
89  }
90 
91  // only a transform may be parent to a transform
92  if( nullptr != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
93  return false;
94 
95  m_Parent = aParent;
96 
97  if( m_Parent )
98  m_Parent->AddChildNode( this );
99 
100  return true;
101 }
102 
103 
104 SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
105 {
106  if( nullptr == aNodeName || 0 == aNodeName[0] )
107  return nullptr;
108 
109  if( !m_Name.compare( aNodeName ) )
110  return this;
111 
112  FIND_NODE( SCENEGRAPH, aNodeName, m_Transforms, aCaller );
113  FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
114 
115  // query the parent if appropriate
116  if( aCaller == m_Parent || nullptr == m_Parent )
117  return nullptr;
118 
119  return m_Parent->FindNode( aNodeName, this );
120 }
121 
122 
123 void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
124 {
125  if( nullptr == aNode )
126  return;
127 
128  switch( aNode->GetNodeType() )
129  {
132  isChild );
133  break;
134 
135  case S3D::SGTYPE_SHAPE:
136  UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
137  break;
138 
139  default:
140  break;
141  }
142 
143  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [BUG] unlinkNode() did not find its target",
144  __FILE__, __FUNCTION__, __LINE__ );
145 }
146 
147 
149 {
150  unlinkNode( aNode, true );
151  return;
152 }
153 
154 
155 void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
156 {
157  unlinkNode( aNode, false );
158  return;
159 }
160 
161 
162 bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
163 {
164  wxCHECK( aNode, false );
165 
167  ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
168 
169  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [BUG] object '%s' is not a valid type for this object (%d)",
170  __FILE__, __FUNCTION__, __LINE__, aNode->GetName(), aNode->GetNodeType() );
171 
172  return false;
173 }
174 
175 
177 {
178  return addNode( aNode, false );
179 }
180 
181 
183 {
184  return addNode( aNode, true );
185 }
186 
187 
189 {
190  m_written = false;
191 
192  // rename this node
193  m_Name.clear();
194  GetName();
195 
196  // rename all shapes
197  do
198  {
199  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
200  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
201 
202  while( sL != eL )
203  {
204  (*sL)->ReNameNodes();
205  ++sL;
206  }
207 
208  } while( 0 );
209 
210  // rename all transforms
211  do
212  {
213  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
214  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
215 
216  while( sL != eL )
217  {
218  (*sL)->ReNameNodes();
219  ++sL;
220  }
221 
222  } while( 0 );
223 }
224 
225 
226 bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
227 {
228  if( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty() )
229  {
230  return false;
231  }
232 
233  std::string tmp;
234 
235  if( aReuseFlag )
236  {
237  if( !m_written )
238  {
239  aFile << "DEF " << GetName() << " Transform {\n";
240  m_written = true;
241  }
242  else
243  {
244  aFile << "USE " << GetName() << "\n";
245  return true;
246  }
247  }
248  else
249  {
250  aFile << " Transform {\n";
251  }
252 
253  // convert center to 1VRML unit = 0.1 inch
254  SGPOINT pt = center;
255  pt.x /= 2.54;
256  pt.y /= 2.54;
257  pt.z /= 2.54;
258 
259  S3D::FormatPoint( tmp, pt );
260  aFile << " center " << tmp << "\n";
262  aFile << " rotation " << tmp << "\n";
263  S3D::FormatPoint( tmp, scale );
264  aFile << " scale " << tmp << "\n";
266  aFile << " scaleOrientation " << tmp << "\n";
267 
268  // convert translation to 1VRML unit = 0.1 inch
269  pt = translation;
270  pt.x /= 2.54;
271  pt.y /= 2.54;
272  pt.z /= 2.54;
273  S3D::FormatPoint( tmp, pt );
274  aFile << " translation " << tmp << "\n";
275 
276  aFile << " children [\n";
277 
278  if( !m_Transforms.empty() )
279  {
280  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
281  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
282 
283  while( sL != eL )
284  {
285  (*sL)->WriteVRML( aFile, aReuseFlag );
286  ++sL;
287  }
288  }
289 
290  if( !m_RTransforms.empty() )
291  {
292  std::vector< SCENEGRAPH* >::iterator sL = m_RTransforms.begin();
293  std::vector< SCENEGRAPH* >::iterator eL = m_RTransforms.end();
294 
295  while( sL != eL )
296  {
297  (*sL)->WriteVRML( aFile, aReuseFlag );
298  ++sL;
299  }
300  }
301 
302  if( !m_Shape.empty() )
303  {
304  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
305  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
306 
307  while( sL != eL )
308  {
309  (*sL)->WriteVRML( aFile, aReuseFlag );
310  ++sL;
311  }
312  }
313 
314  if( !m_RShape.empty() )
315  {
316  std::vector< SGSHAPE* >::iterator sL = m_RShape.begin();
317  std::vector< SGSHAPE* >::iterator eL = m_RShape.end();
318 
319  while( sL != eL )
320  {
321  (*sL)->WriteVRML( aFile, aReuseFlag );
322  ++sL;
323  }
324  }
325 
326  aFile << "] }\n";
327 
328  return true;
329 }
330 
331 
332 bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
333 {
334  if( nullptr == parentNode && nullptr != m_Parent )
335  {
336  SGNODE* np = m_Parent;
337 
338  while( nullptr != np->GetParent() )
339  np = np->GetParent();
340 
341  if( np->WriteCache( aFile, nullptr ) )
342  {
343  m_written = true;
344  return true;
345  }
346 
347  return false;
348  }
349 
350  wxCHECK( parentNode == m_Parent, false );
351 
352  if( nullptr == m_Parent )
353  {
354  // ensure unique node names
355  ResetNodeIndex();
356  ReNameNodes();
357  }
358 
359  if( aFile.fail() )
360  {
361  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad stream", __FILE__, __FUNCTION__, __LINE__ );
362 
363  return false;
364  }
365 
366  aFile << "[" << GetName() << "]";
367  S3D::WritePoint( aFile, center );
368  S3D::WritePoint( aFile, translation );
370  aFile.write( (char*)&rotation_angle, sizeof( rotation_angle ) );
371  S3D::WritePoint( aFile, scale );
372  S3D::WriteVector( aFile, scale_axis );
373  aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
374 
375  // Transfer ownership of any Transform references which hadn't been written
376  size_t asize = m_RTransforms.size();
377  size_t i;
378 
379  for( i = 0; i < asize; ++i )
380  {
381  if( !m_RTransforms[i]->isWritten() )
382  {
383  m_RTransforms[i]->SwapParent( this );
384  --asize;
385  --i;
386  }
387  }
388 
389  // Transfer ownership of any Shape references which hadn't been written
390  asize = m_RShape.size();
391 
392  for( i = 0; i < asize; ++i )
393  {
394  if( !m_RShape[i]->isWritten() )
395  {
396  m_RShape[i]->SwapParent( this );
397  --asize;
398  --i;
399  }
400  }
401 
402  asize = m_Transforms.size();
403  aFile.write( (char*)&asize, sizeof( size_t ) );
404  asize = m_RTransforms.size();
405  aFile.write( (char*)&asize, sizeof( size_t ) );
406  asize = m_Shape.size();
407  aFile.write( (char*)&asize, sizeof( size_t ) );
408  asize = m_RShape.size();
409  aFile.write( (char*)&asize, sizeof( size_t ) );
410  asize = m_Transforms.size();
411 
412  // write child transforms
413  for( i = 0; i < asize; ++i )
414  {
415  if( !m_Transforms[i]->WriteCache( aFile, this ) )
416  {
417  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad stream while writing child transforms",
418  __FILE__, __FUNCTION__, __LINE__ );
419 
420  return false;
421  }
422  }
423 
424  // write referenced transform names
425  asize = m_RTransforms.size();
426 
427  for( i = 0; i < asize; ++i )
428  aFile << "[" << m_RTransforms[i]->GetName() << "]";
429 
430  // write child shapes
431  asize = m_Shape.size();
432 
433  for( i = 0; i < asize; ++i )
434  {
435  if( !m_Shape[i]->WriteCache( aFile, this ) )
436  {
437  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] bad stream while writing child shapes",
438  __FILE__, __FUNCTION__, __LINE__ );
439 
440  return false;
441  }
442  }
443 
444  // write referenced transform names
445  asize = m_RShape.size();
446 
447  for( i = 0; i < asize; ++i )
448  aFile << "[" << m_RShape[i]->GetName() << "]";
449 
450  if( aFile.fail() )
451  return false;
452 
453  m_written = true;
454  return true;
455 }
456 
457 
458 bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
459 {
460  wxCHECK( m_Transforms.empty() && m_RTransforms.empty() && m_Shape.empty() && m_RShape.empty(),
461  false );
462 
463  std::string name; // name of the node
464 
465  if( nullptr == parentNode )
466  {
467  // we need to read the tag and verify its type
468  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
469  {
470  wxLogTrace( MASK_3D_SG,
471  "%s:%s:%d * [INFO] corrupt data; tag mismatch at position %ul",
472  __FILE__, __FUNCTION__, __LINE__,
473  static_cast<unsigned long>( aFile.tellg() ) );
474 
475  return false;
476  }
477 
478  m_Name = name;
479  }
480 
481  // read fixed member data
482  S3D::ReadPoint( aFile, center );
483  S3D::ReadPoint( aFile, translation );
484  S3D::ReadVector( aFile, rotation_axis );
485  aFile.read( (char*)&rotation_angle, sizeof( rotation_angle ) );
486  S3D::ReadPoint( aFile, scale );
487  S3D::ReadVector( aFile, scale_axis );
488  aFile.read( (char*)&scale_angle, sizeof( scale_angle ) );
489 
490  size_t sizeCT = 0; // child transforms
491  size_t sizeRT = 0; // referenced transforms
492  size_t sizeCS = 0; // child shapes
493  size_t sizeRS = 0; // referenced shapes
494 
495  aFile.read( (char*)&sizeCT, sizeof( size_t ) );
496  aFile.read( (char*)&sizeRT, sizeof( size_t ) );
497  aFile.read( (char*)&sizeCS, sizeof( size_t ) );
498  aFile.read( (char*)&sizeRS, sizeof( size_t ) );
499 
500  size_t i;
501 
502  // read child transforms
503  for( i = 0; i < sizeCT; ++i )
504  {
505  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
506  {
507  wxLogTrace( MASK_3D_SG,
508  "%s:%s:%d * [INFO] corrupt data; bad child transform tag at position %ul",
509  __FILE__, __FUNCTION__, __LINE__,
510  static_cast<unsigned long>( aFile.tellg() ) );
511 
512  return false;
513  }
514 
515  SCENEGRAPH* sp = new SCENEGRAPH( this );
516  sp->SetName( name.c_str() );
517 
518  if( !sp->ReadCache( aFile, this ) )
519  {
520  wxLogTrace( MASK_3D_SG,
521  "%s:%s:%d * [INFO] corrupt data while reading transform %ul",
522  __FILE__, __FUNCTION__, __LINE__,
523  static_cast<unsigned long>( aFile.tellg() ) );
524 
525  return false;
526  }
527  }
528 
529  // read referenced transforms
530  for( i = 0; i < sizeRT; ++i )
531  {
532  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
533  {
534  wxLogTrace( MASK_3D_SG,
535  "%s:%s:%d * [INFO] corrupt data; bad ref transform tag at position %ul",
536  __FILE__, __FUNCTION__, __LINE__,
537  static_cast<unsigned long>( aFile.tellg() ) );
538 
539  return false;
540  }
541 
542  SGNODE* sp = FindNode( name.c_str(), this );
543 
544  if( !sp )
545  {
546  wxLogTrace( MASK_3D_SG,
547  "%s:%s:%d * [INFO] corrupt data: cannot find ref transform at position %ul",
548  __FILE__, __FUNCTION__, __LINE__,
549  static_cast<unsigned long>( aFile.tellg() ) );
550 
551  return false;
552  }
553 
554  if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
555  {
556  wxLogTrace( MASK_3D_SG,
557  "%s:%s:%d * [INFO] corrupt data: type is not TRANSFORM at position %ul",
558  __FILE__, __FUNCTION__, __LINE__,
559  static_cast<unsigned long>( aFile.tellg() ) );
560 
561  return false;
562  }
563 
564  AddRefNode( sp );
565  }
566 
567  // read child shapes
568  for( i = 0; i < sizeCS; ++i )
569  {
570  if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
571  {
572  wxLogTrace( MASK_3D_SG,
573  "%s:%s:%d * [INFO] corrupt data; bad child shape tag at position %ul",
574  __FILE__, __FUNCTION__, __LINE__,
575  static_cast<unsigned long>( aFile.tellg() ) );
576 
577  return false;
578  }
579 
580  SGSHAPE* sp = new SGSHAPE( this );
581  sp->SetName( name.c_str() );
582 
583  if( !sp->ReadCache( aFile, this ) )
584  {
585  wxLogTrace( MASK_3D_SG,
586  "%s:%s:%d * [INFO] corrupt data; corrupt data while reading shape at "
587  "position %ul", __FILE__, __FUNCTION__, __LINE__,
588  static_cast<unsigned long>( aFile.tellg() ) );
589 
590  return false;
591  }
592  }
593 
594  // read referenced shapes
595  for( i = 0; i < sizeRS; ++i )
596  {
597  if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
598  {
599  wxLogTrace( MASK_3D_SG,
600  "%s:%s:%d * [INFO] corrupt data; bad ref shape tag at position %ul",
601  __FILE__, __FUNCTION__, __LINE__,
602  static_cast<unsigned long>( aFile.tellg() ) );
603 
604  return false;
605  }
606 
607  SGNODE* sp = FindNode( name.c_str(), this );
608 
609  if( !sp )
610  {
611  wxLogTrace( MASK_3D_SG,
612  "%s:%s:%d * [INFO] corrupt data: cannot find ref shape at position %ul",
613  __FILE__, __FUNCTION__, __LINE__,
614  static_cast<unsigned long>( aFile.tellg() ) );
615 
616  return false;
617  }
618 
619  if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
620  {
621  wxLogTrace( MASK_3D_SG,
622  "%s:%s:%d * [INFO] corrupt data: type is not SGSHAPE at position %ul",
623  __FILE__, __FUNCTION__, __LINE__,
624  static_cast<unsigned long>( aFile.tellg() ) );
625 
626  return false;
627  }
628 
629  AddRefNode( sp );
630  }
631 
632  if( aFile.fail() )
633  return false;
634 
635  return true;
636 }
637 
638 
639 bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform, S3D::MATLIST& materials,
640  std::vector< SMESH >& meshes )
641 {
642  // calculate the accumulated transform
643  double rX, rY, rZ;
644 
645  // rotation
646  rotation_axis.GetVector( rX, rY, rZ );
647  glm::dmat4 rM = glm::rotate( glm::dmat4( 1.0 ), rotation_angle, glm::dvec3( rX, rY, rZ ) );
648 
649  // translation
650  glm::dmat4 tM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( translation.x, translation.y,
651  translation.z ) );
652  // center
653  glm::dmat4 cM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( center.x, center.y, center.z ) );
654  glm::dmat4 ncM = glm::translate( glm::dmat4( 1.0 ), glm::dvec3( -center.x, -center.y,
655  -center.z ) );
656 
657  // scale
658  glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
659 
660  // scaleOrientation
661  scale_axis.GetVector( rX, rY, rZ );
662  glm::dmat4 srM = glm::rotate( glm::dmat4( 1.0 ), scale_angle, glm::dvec3( rX, rY, rZ ) );
663  glm::dmat4 nsrM = glm::rotate( glm::dmat4( 1.0 ), -scale_angle, glm::dvec3( rX, rY, rZ ) );
664 
665  // resultant point:
666  // P' = T x C x R x SR x S x -SR x -C x P
667  // resultant transform:
668  // tx0 = tM * cM * rM * srM * sM * nsrM * ncM
669  glm::dmat4 tx0;
670 
671  if( nullptr != aTransform )
672  tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
673  else
674  tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
675 
676  bool ok = true;
677 
678  // prepare all shapes
679  do
680  {
681  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
682  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
683 
684  while( sL != eL && ok )
685  {
686  ok = (*sL)->Prepare( &tx0, materials, meshes );
687  ++sL;
688  }
689 
690  sL = m_RShape.begin();
691  eL = m_RShape.end();
692 
693  while( sL != eL && ok )
694  {
695  ok = (*sL)->Prepare( &tx0, materials, meshes );
696  ++sL;
697  }
698 
699  } while( 0 );
700 
701  // prepare all transforms
702  do
703  {
704  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
705  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
706 
707  while( sL != eL && ok )
708  {
709  ok = (*sL)->Prepare( &tx0, materials, meshes );
710  ++sL;
711  }
712 
713  sL = m_RTransforms.begin();
714  eL = m_RTransforms.end();
715 
716  while( sL != eL && ok )
717  {
718  ok = (*sL)->Prepare( &tx0, materials, meshes );
719  ++sL;
720  }
721 
722  } while( 0 );
723 
724  return ok;
725 }
void FormatOrientation(std::string &result, const SGVECTOR &axis, double rotation)
Definition: sg_helpers.cpp:82
SGVECTOR rotation_axis
Definition: scenegraph.h:75
double x
Definition: sg_base.h:70
SGNODE * m_Parent
Pointer to parent node; may be NULL for top level transform.
Definition: sg_node.h:227
void ResetNodeIndex(void) noexcept
Reset the global SG* node indices in preparation for write operations.
Definition: sg_node.cpp:236
Define a complex 3D shape for a scenegraph object.
Definition: sg_shape.h:42
void FormatPoint(std::string &result, const SGPOINT &point)
Definition: sg_helpers.cpp:103
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: sg_shape.cpp:444
bool ReadVector(std::istream &aFile, SGVECTOR &aVector)
Definition: sg_helpers.cpp:279
#define UNLINK_NODE(aNodeID, aType, aNode, aOwnedList, aRefList, isChild)
Definition: sg_helpers.h:86
SGPOINT center
Definition: scenegraph.h:73
void unlinkRefNode(const SGNODE *aNode) override
Remove pointers to a referenced node.
Definition: scenegraph.cpp:155
virtual ~SCENEGRAPH()
Definition: scenegraph.cpp:62
double y
Definition: sg_base.h:71
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
SGPOINT translation
Definition: scenegraph.h:74
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Reads binary format data from a cache file.
Definition: scenegraph.cpp:458
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Writes this node's data to a VRML file.
Definition: scenegraph.cpp:226
SGVECTOR scale_axis
Definition: scenegraph.h:78
double rotation_angle
Definition: scenegraph.h:76
std::vector< SCENEGRAPH * > m_RTransforms
Definition: scenegraph.h:91
std::vector< SGSHAPE * > m_RShape
Definition: scenegraph.h:92
std::vector< SGSHAPE * > m_Shape
Definition: scenegraph.h:89
const char * GetName(void)
Definition: sg_node.cpp:146
bool m_written
Set to true when the object has been written after a ReNameNodes().
Definition: sg_node.h:230
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Write this node's data to a binary cache file.
Definition: scenegraph.cpp:332
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
virtual void unlinkChildNode(const SGNODE *aNode)=0
Remove references to an owned child.
bool WriteVector(std::ostream &aFile, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:165
bool AddChildNode(SGNODE *aNode) override
Definition: scenegraph.cpp:182
#define DROP_REFS(aType, aList)
Definition: sg_helpers.h:52
double scale_angle
Definition: scenegraph.h:79
void unlinkNode(const SGNODE *aNode, bool isChild)
Definition: scenegraph.cpp:123
bool WritePoint(std::ostream &aFile, const SGPOINT &aPoint)
Definition: sg_helpers.cpp:152
bool addNode(SGNODE *aNode, bool isChild)
Definition: scenegraph.cpp:162
std::vector< SCENEGRAPH * > m_Transforms
Definition: scenegraph.h:88
void ReNameNodes(void) override
Rename a node and all its child nodes in preparation for write operations.
Definition: scenegraph.cpp:188
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 * 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 WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
S3D::SGTYPES m_SGtype
Type of Scene Graph node.
Definition: sg_node.h:228
const int scale
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Set the parent SGNODE of this object.
Definition: scenegraph.cpp:74
const char * name
Definition: DXF_plotter.cpp:56
bool AddRefNode(SGNODE *aNode) override
Definition: scenegraph.cpp:176
bool ReadPoint(std::istream &aFile, SGPOINT &aPoint)
Definition: sg_helpers.cpp:266
#define ADD_NODE(aNodeID, aType, aNode, aOwnedList, aRefList, isChild)
Definition: sg_helpers.h:132
void unlinkChildNode(const SGNODE *aNode) override
Remove references to an owned child.
Definition: scenegraph.cpp:148
double z
Definition: sg_base.h:72
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
Define the basic data set required to represent a 3D model.
Definition: scenegraph.h:44
Define a number of macros to aid in repetitious code which is probably best expressed as a preprocess...
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: scenegraph.cpp:104
void GetVector(double &aXVal, double &aYVal, double &aZVal) const noexcept
Definition: sg_base.cpp:225
SCENEGRAPH(SGNODE *aParent)
Definition: scenegraph.cpp:38
SGPOINT scale
Definition: scenegraph.h:77
#define DEL_OBJS(aType, aList)
Definition: sg_helpers.h:69
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104
bool Prepare(const glm::dmat4 *aTransform, S3D::MATLIST &materials, std::vector< SMESH > &meshes)
Definition: scenegraph.cpp:639
#define FIND_NODE(aType, aName, aNodeList, aCallingNode)
Definition: sg_helpers.h:179