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  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #define GLM_FORCE_RADIANS
25 
26 #include <iostream>
27 #include <sstream>
28 #include <glm/glm.hpp>
29 #include <glm/ext.hpp>
30 #include <wx/log.h>
31 
32 #include "3d_cache/sg/scenegraph.h"
33 #include "3d_cache/sg/sg_shape.h"
34 #include "3d_cache/sg/sg_helpers.h"
35 
36 
37 SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
38 {
40  rotation_angle = 0.0;
41  scale_angle = 0.0;
42 
43  scale.x = 1.0;
44  scale.y = 1.0;
45  scale.z = 1.0;
46 
47  if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
48  {
49  m_Parent = NULL;
50 
51 #ifdef DEBUG
52  std::ostringstream ostr;
53  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
54  ostr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
55  ostr << aParent->GetNodeType() << ")";
56  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
57 #endif
58  }
59  else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
60  {
61  m_Parent->AddChildNode( this );
62  }
63 
64  return;
65 }
66 
67 
69 {
70  // drop references
73 
74  // delete owned objects
77 
78  return;
79 }
80 
81 
82 bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
83 {
84  if( NULL != m_Parent )
85  {
86  if( aParent == m_Parent )
87  return true;
88 
89  // handle the change in parents
90  if( notify )
91  m_Parent->unlinkChildNode( this );
92 
93  m_Parent = NULL;
94 
95  if( NULL == aParent )
96  return true;
97  }
98 
99  // only a transform may be parent to a transform
100  if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
101  return false;
102 
103  m_Parent = aParent;
104 
105  if( m_Parent )
106  m_Parent->AddChildNode( this );
107 
108  return true;
109 }
110 
111 
112 SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
113 {
114  if( NULL == aNodeName || 0 == aNodeName[0] )
115  return NULL;
116 
117  if( !m_Name.compare( aNodeName ) )
118  return this;
119 
120  FIND_NODE( SCENEGRAPH, aNodeName, m_Transforms, aCaller );
121  FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
122 
123  // query the parent if appropriate
124  if( aCaller == m_Parent || NULL == m_Parent )
125  return NULL;
126 
127  return m_Parent->FindNode( aNodeName, this );
128 }
129 
130 
131 void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
132 {
133  if( NULL == aNode )
134  return;
135 
136  switch( aNode->GetNodeType() )
137  {
140  break;
141 
142  case S3D::SGTYPE_SHAPE:
143  UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
144  break;
145 
146  default:
147  break;
148  }
149 
150  #ifdef DEBUG
151  do {
152  std::ostringstream ostr;
153  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
154  ostr << " * [BUG] unlinkNode() did not find its target";
155  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
156  } while( 0 );
157  #endif
158 
159  return;
160 }
161 
162 
164 {
165  unlinkNode( aNode, true );
166  return;
167 }
168 
169 
170 void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
171 {
172  unlinkNode( aNode, false );
173  return;
174 }
175 
176 
177 bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
178 {
179  if( NULL == aNode )
180  {
181  #ifdef DEBUG
182  std::ostringstream ostr;
183  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
184  ostr << " * [BUG] NULL pointer passed for aNode";
185  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
186  #endif
187 
188  return false;
189  }
190 
192  ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
193 
194  #ifdef DEBUG
195  do {
196  std::ostringstream ostr;
197  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
198  ostr << " * [BUG] object '" << aNode->GetName();
199  ostr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")";
200  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
201  } while( 0 );
202  #endif
203 
204  return false;
205 }
206 
207 
209 {
210  return addNode( aNode, false );
211 }
212 
213 
215 {
216  return addNode( aNode, true );
217 }
218 
219 
221 {
222  m_written = false;
223 
224  // rename this node
225  m_Name.clear();
226  GetName();
227 
228  // rename all shapes
229  do
230  {
231  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
232  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
233 
234  while( sL != eL )
235  {
236  (*sL)->ReNameNodes();
237  ++sL;
238  }
239 
240  } while(0);
241 
242  // rename all transforms
243  do
244  {
245  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
246  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
247 
248  while( sL != eL )
249  {
250  (*sL)->ReNameNodes();
251  ++sL;
252  }
253 
254  } while(0);
255 
256  return;
257 }
258 
259 
260 bool SCENEGRAPH::WriteVRML( std::ostream& aFile, bool aReuseFlag )
261 {
262  if( m_Transforms.empty() && m_RTransforms.empty()
263  && m_Shape.empty() && m_RShape.empty() )
264  {
265  return false;
266  }
267 
268  std::string tmp;
269 
270  if( aReuseFlag )
271  {
272  if( !m_written )
273  {
274  aFile << "DEF " << GetName() << " Transform {\n";
275  m_written = true;
276  }
277  else
278  {
279  aFile << "USE " << GetName() << "\n";
280  return true;
281  }
282  }
283  else
284  {
285  aFile << " Transform {\n";
286  }
287 
288  // convert center to 1VRML unit = 0.1 inch
289  SGPOINT pt = center;
290  pt.x /= 2.54;
291  pt.y /= 2.54;
292  pt.z /= 2.54;
293 
294  S3D::FormatPoint( tmp, pt );
295  aFile << " center " << tmp << "\n";
297  aFile << " rotation " << tmp << "\n";
298  S3D::FormatPoint( tmp, scale );
299  aFile << " scale " << tmp << "\n";
301  aFile << " scaleOrientation " << tmp << "\n";
302 
303  // convert translation to 1VRML unit = 0.1 inch
304  pt = translation;
305  pt.x /= 2.54;
306  pt.y /= 2.54;
307  pt.z /= 2.54;
308  S3D::FormatPoint( tmp, pt );
309  aFile << " translation " << tmp << "\n";
310 
311  aFile << " children [\n";
312 
313  if( !m_Transforms.empty() )
314  {
315  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
316  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
317 
318  while( sL != eL )
319  {
320  (*sL)->WriteVRML( aFile, aReuseFlag );
321  ++sL;
322  }
323  }
324 
325  if( !m_RTransforms.empty() )
326  {
327  std::vector< SCENEGRAPH* >::iterator sL = m_RTransforms.begin();
328  std::vector< SCENEGRAPH* >::iterator eL = m_RTransforms.end();
329 
330  while( sL != eL )
331  {
332  (*sL)->WriteVRML( aFile, aReuseFlag );
333  ++sL;
334  }
335  }
336 
337  if( !m_Shape.empty() )
338  {
339  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
340  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
341 
342  while( sL != eL )
343  {
344  (*sL)->WriteVRML( aFile, aReuseFlag );
345  ++sL;
346  }
347  }
348 
349  if( !m_RShape.empty() )
350  {
351  std::vector< SGSHAPE* >::iterator sL = m_RShape.begin();
352  std::vector< SGSHAPE* >::iterator eL = m_RShape.end();
353 
354  while( sL != eL )
355  {
356  (*sL)->WriteVRML( aFile, aReuseFlag );
357  ++sL;
358  }
359  }
360 
361  aFile << "] }\n";
362 
363  return true;
364 }
365 
366 
367 bool SCENEGRAPH::WriteCache( std::ostream& aFile, SGNODE* parentNode )
368 {
369  if( NULL == parentNode && NULL != m_Parent )
370  {
371  SGNODE* np = m_Parent;
372 
373  while( NULL != np->GetParent() )
374  np = np->GetParent();
375 
376  if( np->WriteCache( aFile, NULL ) )
377  {
378  m_written = true;
379  return true;
380  }
381 
382  return false;
383  }
384 
385  if( parentNode != m_Parent )
386  {
387  #ifdef DEBUG
388  std::ostringstream ostr;
389  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
390  ostr << " * [BUG] corrupt data; parentNode != m_aParent";
391  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
392  #endif
393 
394  return false;
395  }
396 
397  if( NULL == m_Parent )
398  {
399  // ensure unique node names
400  ResetNodeIndex();
401  ReNameNodes();
402  }
403 
404  if( aFile.fail() )
405  {
406  #ifdef DEBUG
407  std::ostringstream ostr;
408  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
409  ostr << " * [INFO] bad stream";
410  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
411  #endif
412 
413  return false;
414  }
415 
416  aFile << "[" << GetName() << "]";
417  S3D::WritePoint( aFile, center );
418  S3D::WritePoint( aFile, translation );
420  aFile.write( (char*)&rotation_angle, sizeof( rotation_angle ) );
421  S3D::WritePoint( aFile, scale );
422  S3D::WriteVector( aFile, scale_axis );
423  aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
424 
425  // Transfer ownership of any Transform references which hadn't been written
426  size_t asize = m_RTransforms.size();
427  size_t i;
428 
429  for( i = 0; i < asize; ++i )
430  {
431  if( !m_RTransforms[i]->isWritten() )
432  {
433  m_RTransforms[i]->SwapParent( this );
434  --asize;
435  --i;
436  }
437  }
438 
439  // Transfer ownership of any Shape references which hadn't been written
440  asize = m_RShape.size();
441 
442  for( i = 0; i < asize; ++i )
443  {
444  if( !m_RShape[i]->isWritten() )
445  {
446  m_RShape[i]->SwapParent( this );
447  --asize;
448  --i;
449  }
450  }
451 
452  asize = m_Transforms.size();
453  aFile.write( (char*)&asize, sizeof( size_t ) );
454  asize = m_RTransforms.size();
455  aFile.write( (char*)&asize, sizeof( size_t ) );
456  asize = m_Shape.size();
457  aFile.write( (char*)&asize, sizeof( size_t ) );
458  asize = m_RShape.size();
459  aFile.write( (char*)&asize, sizeof( size_t ) );
460  asize = m_Transforms.size();
461 
462  // write child transforms
463  for( i = 0; i < asize; ++i )
464  {
465  if( !m_Transforms[i]->WriteCache( aFile, this ) )
466  {
467  #ifdef DEBUG
468  std::ostringstream ostr;
469  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
470  ostr << " * [INFO] bad stream while writing child transforms";
471  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
472  #endif
473 
474  return false;
475  }
476  }
477 
478  // write referenced transform names
479  asize = m_RTransforms.size();
480  for( i = 0; i < asize; ++i )
481  aFile << "[" << m_RTransforms[i]->GetName() << "]";
482 
483  // write child shapes
484  asize = m_Shape.size();
485  for( i = 0; i < asize; ++i )
486  {
487  if( !m_Shape[i]->WriteCache( aFile, this ) )
488  {
489  #ifdef DEBUG
490  std::ostringstream ostr;
491  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
492  ostr << " * [INFO] bad stream while writing child shapes";
493  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
494  #endif
495 
496  return false;
497  }
498  }
499 
500  // write referenced transform names
501  asize = m_RShape.size();
502  for( i = 0; i < asize; ++i )
503  aFile << "[" << m_RShape[i]->GetName() << "]";
504 
505  if( aFile.fail() )
506  return false;
507 
508  m_written = true;
509  return true;
510 }
511 
512 
513 bool SCENEGRAPH::ReadCache( std::istream& aFile, SGNODE* parentNode )
514 {
515  if( !m_Transforms.empty() || !m_RTransforms.empty()
516  || !m_Shape.empty() || !m_RShape.empty() )
517  {
518  #ifdef DEBUG
519  std::ostringstream ostr;
520  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
521  ostr << " * [BUG] non-empty node";
522  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
523  #endif
524 
525  return false;
526  }
527 
528  std::string name; // name of the node
529 
530  if( NULL == parentNode )
531  {
532  // we need to read the tag and verify its type
533  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
534  {
535  #ifdef DEBUG
536  std::ostringstream ostr;
537  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
538  ostr << " * [INFO] corrupt data; tag mismatch at position ";
539  ostr << aFile.tellg();
540  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
541  #endif
542 
543  return false;
544  }
545 
546  m_Name = name;
547  }
548 
549  // read fixed member data
550  S3D::ReadPoint( aFile, center );
551  S3D::ReadPoint( aFile, translation );
552  S3D::ReadVector( aFile, rotation_axis );
553  aFile.read( (char*)&rotation_angle, sizeof( rotation_angle ) );
554  S3D::ReadPoint( aFile, scale );
555  S3D::ReadVector( aFile, scale_axis );
556  aFile.read( (char*)&scale_angle, sizeof( scale_angle ) );
557 
558  size_t sizeCT = 0; // child transforms
559  size_t sizeRT = 0; // referenced transforms
560  size_t sizeCS = 0; // child shapes
561  size_t sizeRS = 0; // referenced shapes
562 
563  aFile.read( (char*)&sizeCT, sizeof( size_t ) );
564  aFile.read( (char*)&sizeRT, sizeof( size_t ) );
565  aFile.read( (char*)&sizeCS, sizeof( size_t ) );
566  aFile.read( (char*)&sizeRS, sizeof( size_t ) );
567 
568  size_t i;
569 
570  // read child transforms
571  for( i = 0; i < sizeCT; ++i )
572  {
573  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
574  {
575  #ifdef DEBUG
576  std::ostringstream ostr;
577  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
578  ostr << " * [INFO] corrupt data; bad child transform tag at position ";
579  ostr << aFile.tellg();
580  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
581  #endif
582 
583  return false;
584  }
585 
586  SCENEGRAPH* sp = new SCENEGRAPH( this );
587  sp->SetName( name.c_str() );
588 
589  if( !sp->ReadCache( aFile, this ) )
590  {
591  #ifdef DEBUG
592  std::ostringstream ostr;
593  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
594  ostr << " * [INFO] corrupt data while reading transform '";
595  ostr << name << "' pos " << aFile.tellg();
596  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
597  #endif
598 
599  return false;
600  }
601  }
602 
603  // read referenced transforms
604  for( i = 0; i < sizeRT; ++i )
605  {
606  if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
607  {
608  #ifdef DEBUG
609  std::ostringstream ostr;
610  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
611  ostr << " * [INFO] corrupt data; bad ref transform tag at position ";
612  ostr << aFile.tellg();
613  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
614  #endif
615 
616  return false;
617  }
618 
619  SGNODE* sp = FindNode( name.c_str(), this );
620 
621  if( !sp )
622  {
623  #ifdef DEBUG
624  std::ostringstream ostr;
625  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
626  ostr << " * [INFO] corrupt data: cannot find ref transform '";
627  ostr << name << "' pos " << aFile.tellg();
628  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
629  #endif
630 
631  return false;
632  }
633 
634  if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
635  {
636  #ifdef DEBUG
637  std::ostringstream ostr;
638  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
639  ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
640  ostr << name << "' pos " << aFile.tellg();
641  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
642  #endif
643 
644  return false;
645  }
646 
647  AddRefNode( sp );
648  }
649 
650  // read child shapes
651  for( i = 0; i < sizeCS; ++i )
652  {
653  if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
654  {
655  #ifdef DEBUG
656  std::ostringstream ostr;
657  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
658  ostr << " * [INFO] corrupt data; bad child shape tag at position ";
659  ostr << aFile.tellg();
660  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
661  #endif
662 
663  return false;
664  }
665 
666  SGSHAPE* sp = new SGSHAPE( this );
667  sp->SetName( name.c_str() );
668 
669  if( !sp->ReadCache( aFile, this ) )
670  {
671  #ifdef DEBUG
672  std::ostringstream ostr;
673  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
674  ostr << " * [INFO] corrupt data while reading shape '";
675  ostr << name << "' pos " << aFile.tellg();
676  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
677  #endif
678 
679  return false;
680  }
681  }
682 
683  // read referenced shapes
684  for( i = 0; i < sizeRS; ++i )
685  {
686  if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
687  {
688  #ifdef DEBUG
689  std::ostringstream ostr;
690  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
691  ostr << " * [INFO] corrupt data; bad ref shape tag at position ";
692  ostr << aFile.tellg();
693  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
694  #endif
695 
696  return false;
697  }
698 
699  SGNODE* sp = FindNode( name.c_str(), this );
700 
701  if( !sp )
702  {
703  #ifdef DEBUG
704  std::ostringstream ostr;
705  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
706  ostr << " * [INFO] corrupt data: cannot find ref shape '";
707  ostr << name << "' pos " << aFile.tellg();
708  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
709  #endif
710 
711  return false;
712  }
713 
714  if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
715  {
716  #ifdef DEBUG
717  std::ostringstream ostr;
718  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
719  ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
720  ostr << name << "' pos " << aFile.tellg();
721  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
722  #endif
723 
724  return false;
725  }
726 
727  AddRefNode( sp );
728  }
729 
730  if( aFile.fail() )
731  return false;
732 
733  return true;
734 }
735 
736 
737 bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
738  S3D::MATLIST& materials, std::vector< SMESH >& meshes )
739 {
740  // calculate the accumulated transform
741  double rX, rY, rZ;
742  // rotation
743  rotation_axis.GetVector( rX, rY, rZ );
744  glm::dmat4 rM = glm::rotate( rotation_angle, glm::dvec3( rX, rY, rZ ) );
745  // translation
746  glm::dmat4 tM = glm::translate( glm::dvec3( translation.x, translation.y, translation.z ) );
747  // center
748  glm::dmat4 cM = glm::translate( glm::dvec3( center.x, center.y, center.z ) );
749  glm::dmat4 ncM = glm::translate( glm::dvec3( -center.x, -center.y, -center.z ) );
750  // scale
751  glm::dmat4 sM = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( scale.x, scale.y, scale.z ) );
752  // scaleOrientation
753  scale_axis.GetVector( rX, rY, rZ );
754  glm::dmat4 srM = glm::rotate( scale_angle, glm::dvec3( rX, rY, rZ ) );
755  glm::dmat4 nsrM = glm::rotate( -scale_angle, glm::dvec3( rX, rY, rZ ) );
756 
757  // resultant point:
758  // P' = T x C x R x SR x S x -SR x -C x P
759  // resultant transform:
760  // tx0 = tM * cM * rM * srM * sM * nsrM * ncM
761  glm::dmat4 tx0;
762 
763  if( NULL != aTransform )
764  tx0 = (*aTransform) * tM * cM * rM * srM * sM * nsrM * ncM;
765  else
766  tx0 = tM * cM * rM * srM * sM * nsrM * ncM;
767 
768  bool ok = true;
769 
770  // prepare all shapes
771  do
772  {
773  std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
774  std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
775 
776  while( sL != eL && ok )
777  {
778  ok = (*sL)->Prepare( &tx0, materials, meshes );
779  ++sL;
780  }
781 
782  sL = m_RShape.begin();
783  eL = m_RShape.end();
784 
785  while( sL != eL && ok )
786  {
787  ok = (*sL)->Prepare( &tx0, materials, meshes );
788  ++sL;
789  }
790 
791  } while(0);
792 
793  // prepare all transforms
794  do
795  {
796  std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
797  std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
798 
799  while( sL != eL && ok )
800  {
801  ok = (*sL)->Prepare( &tx0, materials, meshes );
802  ++sL;
803  }
804 
805  sL = m_RTransforms.begin();
806  eL = m_RTransforms.end();
807 
808  while( sL != eL && ok )
809  {
810  ok = (*sL)->Prepare( &tx0, materials, meshes );
811  ++sL;
812  }
813 
814  } while(0);
815 
816  return ok;
817 }
void FormatOrientation(std::string &result, const SGVECTOR &axis, double rotation)
Definition: sg_helpers.cpp:85
SGVECTOR rotation_axis
Definition: scenegraph.h:67
double x
Definition: sg_base.h:70
SGNODE * m_Parent
Definition: sg_node.h:83
void FormatPoint(std::string &result, const SGPOINT &point)
Definition: sg_helpers.cpp:108
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Function ReadCache Reads binary format data from a cache file.
Definition: sg_shape.cpp:511
bool ReadVector(std::istream &aFile, SGVECTOR &aVector)
Definition: sg_helpers.cpp:309
#define UNLINK_NODE(aNodeID, aType, aNode, aOwnedList, aRefList, isChild)
Definition: sg_helpers.h:78
SGPOINT center
Definition: scenegraph.h:65
void unlinkRefNode(const SGNODE *aNode) override
Function unlinkRef removes pointers to a referenced node; it is invoked by the referenced node upon d...
Definition: scenegraph.cpp:170
virtual ~SCENEGRAPH()
Definition: scenegraph.cpp:68
double y
Definition: sg_base.h:71
Class SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
S3D::SGTYPES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: sg_node.cpp:108
SGPOINT translation
Definition: scenegraph.h:66
bool ReadCache(std::istream &aFile, SGNODE *parentNode) override
Function ReadCache Reads binary format data from a cache file.
Definition: scenegraph.cpp:513
bool WriteVRML(std::ostream &aFile, bool aReuseFlag) override
Function WriteVRML writes this node's data to a VRML file; this includes all data of child and refere...
Definition: scenegraph.cpp:260
defines the basic data set required to represent a 3D model; this model must remain compatible with V...
SGVECTOR scale_axis
Definition: scenegraph.h:70
double rotation_angle
Definition: scenegraph.h:68
std::vector< SCENEGRAPH * > m_RTransforms
Definition: scenegraph.h:53
std::vector< SGSHAPE * > m_RShape
Definition: scenegraph.h:54
std::vector< SGSHAPE * > m_Shape
Definition: scenegraph.h:51
const char * GetName(void)
Definition: sg_node.cpp:150
bool m_written
Definition: sg_node.h:86
defines a complex 3D shape for a scenegraph object
bool WriteCache(std::ostream &aFile, SGNODE *parentNode) override
Function WriteCache write's this node's data to a binary cache file; the data includes all data of ch...
Definition: scenegraph.cpp:367
S3D::SGTYPES ReadTag(std::istream &aFile, std::string &aName)
Function ReadTag reads the text tag of a binary cache file which is the NodeTag and unique ID number ...
Definition: sg_helpers.cpp:208
SGNODE * GetParent(void) const
Function GetParent returns a pointer to the parent SGNODE of this object or NULL if the object has no...
Definition: sg_node.cpp:114
virtual void unlinkChildNode(const SGNODE *aNode)=0
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
bool WriteVector(std::ostream &aFile, const SGVECTOR &aVector)
Definition: sg_helpers.cpp:178
bool AddChildNode(SGNODE *aNode) override
Definition: scenegraph.cpp:214
#define DROP_REFS(aType, aList)
Definition: sg_helpers.h:50
double scale_angle
Definition: scenegraph.h:71
void unlinkNode(const SGNODE *aNode, bool isChild)
Definition: scenegraph.cpp:131
bool WritePoint(std::ostream &aFile, const SGPOINT &aPoint)
Definition: sg_helpers.cpp:165
bool addNode(SGNODE *aNode, bool isChild)
Definition: scenegraph.cpp:177
std::vector< SCENEGRAPH * > m_Transforms
Definition: scenegraph.h:50
void ReNameNodes(void) override
Function ReNameNodes renames a node and all its child nodes in preparation for Write() operations...
Definition: scenegraph.cpp:220
virtual SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller)=0
Function FindNode searches the tree of linked nodes and returns a reference to the first node found w...
void SetName(const char *aName)
Definition: sg_node.cpp:159
std::string m_Name
Definition: sg_node.h:85
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Function WriteCache write's this node's data to a binary cache file; the data includes all data of ch...
S3D::SGTYPES m_SGtype
Definition: sg_node.h:84
const int scale
virtual bool SetParent(SGNODE *aParent, bool notify=true) override
Function SetParent sets the parent SGNODE of this object.
Definition: scenegraph.cpp:82
bool AddRefNode(SGNODE *aNode) override
Definition: scenegraph.cpp:208
bool ReadPoint(std::istream &aFile, SGPOINT &aPoint)
Definition: sg_helpers.cpp:296
#define ADD_NODE(aNodeID, aType, aNode, aOwnedList, aRefList, isChild)
Definition: sg_helpers.h:113
void unlinkChildNode(const SGNODE *aNode) override
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
Definition: scenegraph.cpp:163
double z
Definition: sg_base.h:72
virtual bool AddChildNode(SGNODE *aNode)=0
const char * name
void GetVector(double &aXVal, double &aYVal, double &aZVal) const
Definition: sg_base.cpp:283
defines a number of macro functions to aid in repetitious code which is probably best expressed as a ...
SGNODE * FindNode(const char *aNodeName, const SGNODE *aCaller) override
Function FindNode searches the tree of linked nodes and returns a reference to the first node found w...
Definition: scenegraph.cpp:112
SCENEGRAPH(SGNODE *aParent)
Definition: scenegraph.cpp:37
SGPOINT scale
Definition: scenegraph.h:69
void ResetNodeIndex(void)
Function ResetNodeIndex resets the global SG* node indices in preparation for Write() operations...
Definition: sg_node.cpp:304
#define DEL_OBJS(aType, aList)
Definition: sg_helpers.h:64
bool isWritten(void)
Function IsWritten returns true if the object had already been written to a cache file or VRML file; ...
Definition: sg_node.h:130
bool Prepare(const glm::dmat4 *aTransform, S3D::MATLIST &materials, std::vector< SMESH > &meshes)
Definition: scenegraph.cpp:737
#define FIND_NODE(aType, aName, aNodeList, aCallingNode)
Definition: sg_helpers.h:149