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