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