KiCad PCB EDA Suite
vrml1_faceset.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) 2016 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 "vrml1_base.h"
30 #include "vrml1_faceset.h"
31 #include "vrml1_coords.h"
32 #include "vrml1_material.h"
33 #include "wrlfacet.h"
34 #include "plugins/3dapi/ifsg_all.h"
35 
36 
37 WRL1FACESET::WRL1FACESET( NAMEREGISTER* aDictionary ) : WRL1NODE( aDictionary )
38 {
40 
41  return;
42 }
43 
44 
45 WRL1FACESET::WRL1FACESET( NAMEREGISTER* aDictionary, WRL1NODE* aParent ) :
46  WRL1NODE( aDictionary )
47 {
49  m_Parent = aParent;
50 
51  if( NULL != m_Parent )
52  m_Parent->AddChildNode( this );
53 
54  return;
55 }
56 
57 
59 {
60  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
61  do {
62  std::ostringstream ostr;
63  ostr << " * [INFO] Destroying IndexedFaceSet with " << m_Children.size();
64  ostr << " children, " << m_Refs.size() << " references and ";
65  ostr << m_BackPointers.size() << " backpointers";
66  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
67  } while( 0 );
68  #endif
69 
70  return;
71 }
72 
73 
75 {
76  // this node may not own or reference any other node
77 
78  #ifdef DEBUG_VRML1
79  do {
80  std::ostringstream ostr;
81  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
82  ostr << " * [BUG] AddRefNode is not applicable";
83  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
84  } while( 0 );
85  #endif
86 
87  return false;
88 }
89 
90 
92 {
93  // this node may not own or reference any other node
94 
95  #ifdef DEBUG_VRML1
96  do {
97  std::ostringstream ostr;
98  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
99  ostr << " * [BUG] AddChildNode is not applicable";
100  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
101  } while( 0 );
102  #endif
103 
104  return false;
105 }
106 
107 
108 bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
109 {
110  size_t line, column;
111  proc.GetFilePosData( line, column );
112 
113  char tok = proc.Peek();
114 
115  if( proc.eof() )
116  {
117  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
118  do {
119  std::ostringstream ostr;
120  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
121  ostr << " * [INFO] bad file format; unexpected eof at line ";
122  ostr << line << ", column " << column;
123  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
124  } while( 0 );
125  #endif
126 
127  return false;
128  }
129 
130  if( '{' != tok )
131  {
132  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
133  do {
134  std::ostringstream ostr;
135  ostr << proc.GetError() << "\n";
136  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
137  ostr << " * [INFO] bad file format; expecting '{' but got '" << tok;
138  ostr << "' at line " << line << ", column " << column;
139  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
140  } while( 0 );
141  #endif
142 
143  return false;
144  }
145 
146  proc.Pop();
147  std::string glob;
148 
149  while( true )
150  {
151  if( proc.Peek() == '}' )
152  {
153  proc.Pop();
154  break;
155  }
156 
157  if( !proc.ReadName( glob ) )
158  {
159  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
160  do {
161  std::ostringstream ostr;
162  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
163  ostr << proc.GetError();
164  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
165  } while( 0 );
166  #endif
167 
168  return false;
169  }
170 
171  // expecting one of:
172  // coordIndex[]
173  // materialIndex[]
174 
175  proc.GetFilePosData( line, column );
176 
177  if( !glob.compare( "coordIndex" ) )
178  {
179  if( !proc.ReadMFInt( coordIndex ) )
180  {
181  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
182  do {
183  std::ostringstream ostr;
184  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
185  ostr << " * [INFO] invalid coordIndex at line " << line << ", column ";
186  ostr << column << "\n";
187  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
188  ostr << " * [INFO] message: '" << proc.GetError();
189  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
190  } while( 0 );
191  #endif
192 
193  return false;
194  }
195  }
196  else if( !glob.compare( "materialIndex" ) )
197  {
198  if( !proc.ReadMFInt( matIndex ) )
199  {
200  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
201  do {
202  std::ostringstream ostr;
203  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
204  ostr << " * [INFO] invalid materialIndex at line " << line << ", column ";
205  ostr << column << "\n";
206  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
207  ostr << " * [INFO] message: '" << proc.GetError();
208  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
209  } while( 0 );
210  #endif
211 
212  return false;
213  }
214  }
215  else if( !glob.compare( "normalIndex" ) )
216  {
217  if( !proc.ReadMFInt( normIndex ) )
218  {
219  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
220  do {
221  std::ostringstream ostr;
222  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
223  ostr << " * [INFO] invalid normalIndex at line " << line << ", column ";
224  ostr << column << "\n";
225  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
226  ostr << " * [INFO] message: '" << proc.GetError();
227  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
228  } while( 0 );
229  #endif
230 
231  return false;
232  }
233  }
234  else if( !glob.compare( "textureCoordIndex" ) )
235  {
236  if( !proc.ReadMFInt( texIndex ) )
237  {
238  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
239  do {
240  std::ostringstream ostr;
241  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
242  ostr << " * [INFO] invalid textureCoordIndex at line " << line << ", column ";
243  ostr << column << "\n";
244  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
245  ostr << " * [INFO] message: '" << proc.GetError();
246  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
247  } while( 0 );
248  #endif
249 
250  return false;
251  }
252  }
253  else
254  {
255  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
256  do {
257  std::ostringstream ostr;
258  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
259  ostr << " * [INFO] bad IndexedFaceSet at line " << line << ", column ";
260  ostr << column << "\n";
261  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
262  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
263  } while( 0 );
264  #endif
265 
266  return false;
267  }
268  } // while( true ) -- reading contents of IndexedFaceSet{}
269 
270  return true;
271 }
272 
273 
275 {
276  // note: m_sgNode is unused because we cannot manage everything
277  // with a single reused transform due to the fact that VRML1
278  // may use a MatrixTransformation entity which is impossible to
279  // decompose into Rotate,Scale,Transform via an anlytic expression.
280  if( !m_Parent )
281  {
282  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
283  wxLogTrace( MASK_VRML, " * [INFO] bad model: no parent node\n" );
284  #endif
285 
286  return NULL;
287  }
288  else
289  {
290  if( NULL == sp )
291  {
292  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
293  wxLogTrace( MASK_VRML, " * [INFO] bad model: no base data given\n" );
294  #endif
295 
296  return NULL;
297  }
298  }
299 
300  m_current = *sp;
301 
302  if( NULL == m_current.coord || NULL == m_current.mat )
303  {
304  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
305  if( NULL == m_current.coord )
306  {
307  wxLogTrace( MASK_VRML, " * [INFO] bad model: no vertex set\n" );
308  }
309 
310  if( NULL == m_current.mat )
311  {
312  wxLogTrace( MASK_VRML, " * [INFO] bad model: no material set\n" );
313  }
314  #endif
315 
316  return NULL;
317  }
318 
319  WRLVEC3F* pcoords;
320  size_t coordsize;
321 
322  m_current.coord->GetCoords( pcoords, coordsize );
323  size_t vsize = coordIndex.size();
324 
325  if( coordsize < 3 || vsize < 3 )
326  {
327  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
328  do {
329  std::ostringstream ostr;
330  ostr << " * [INFO] bad model: coordsize, indexsize = " << coordsize;
331  ostr << ", " << vsize;
332  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
333  } while( 0 );
334  #endif
335 
336  return NULL;
337  }
338 
339  // 1. create the vertex/normals/colors lists
340  SGNODE* sgcolor = NULL;
342  size_t matSize = matIndex.size();
343 
344  switch( mbind )
345  {
346  case BIND_PER_FACE:
347  case BIND_PER_VERTEX:
349  break;
350 
352 
353  if( matIndex.empty() )
354  {
355  #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
356  wxLogTrace( MASK_VRML, " * [INFO] bad model: per face indexed but no indices\n" );
357  #endif
358 
359  // support bad models by temporarily switching bindings
360  mbind = BIND_OVERALL;
361  sgcolor = m_current.mat->GetAppearance( 0 );
362  }
363 
364  break;
365 
366  default:
367 
368  // use the first appearance definition
369  sgcolor = m_current.mat->GetAppearance( 0 );
370  break;
371  }
372 
373  // copy the data into FACET structures
374 
375  SHAPE lShape;
376  FACET* fp = NULL;
377  size_t iCoord;
378  int idx; // coordinate index
379  size_t cidx = 0; // color index
380  SGCOLOR pc1;
381 
382  if( mbind == BIND_OVERALL || mbind == BIND_DEFAULT )
383  {
384  // no per-vertex colors; we can save a few CPU cycles
385  for( iCoord = 0; iCoord < vsize; ++iCoord )
386  {
387  idx = coordIndex[iCoord];
388 
389  if( idx < 0 )
390  {
391  if( NULL != fp )
392  {
393  if( fp->HasMinPoints() )
394  fp = NULL;
395  else
396  fp->Init();
397  }
398 
399  continue;
400  }
401 
402  // if the coordinate is bad then skip it
403  if( idx >= (int)coordsize )
404  continue;
405 
406  if( NULL == fp )
407  fp = lShape.NewFacet();
408 
409  // push the vertex value and index
410  WRLVEC3F vf;
411  glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
412  pt = m_current.txmatrix * pt;
413  vf.x = pt.x;
414  vf.y = pt.y;
415  vf.z = pt.z;
416 
417  fp->AddVertex( vf, idx );
418  }
419  }
420  else
421  {
422  for( iCoord = 0; iCoord < vsize; ++iCoord )
423  {
424  idx = coordIndex[iCoord];
425 
426  if( idx < 0 )
427  {
428  if( NULL != fp )
429  {
430  if( fp->HasMinPoints() )
431  fp = NULL;
432  else
433  fp->Init();
434  }
435 
436  if( mbind == BIND_PER_FACE || mbind == BIND_PER_FACE_INDEXED )
437  ++cidx;
438 
439  continue;
440  }
441 
442  // if the coordinate is bad then skip it
443  if( idx >= (int)coordsize )
444  continue;
445 
446  if( NULL == fp )
447  fp = lShape.NewFacet();
448 
449  // push the vertex value and index
450  WRLVEC3F vf;
451  glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
452  pt = m_current.txmatrix * pt;
453  vf.x = pt.x;
454  vf.y = pt.y;
455  vf.z = pt.z;
456 
457  fp->AddVertex( vf, idx );
458 
459  // push the color if appropriate
460  switch( mbind )
461  {
462  case BIND_PER_FACE:
463 
464  if( !fp->HasColors() )
465  {
466  m_current.mat->GetColor( &pc1, cidx );
467  fp->AddColor( pc1 );
468  }
469 
470  break;
471 
472  case BIND_PER_VERTEX:
473  m_current.mat->GetColor( &pc1, idx );
474  fp->AddColor( pc1 );
475  break;
476 
478  if( !fp->HasColors() )
479  {
480  if( cidx >= matSize )
481  m_current.mat->GetColor( &pc1, matIndex.back() );
482  else
483  m_current.mat->GetColor( &pc1, matIndex[cidx] );
484 
485  fp->AddColor( pc1 );
486  }
487 
488  break;
489 
491 
492  if( matIndex.empty() )
493  {
494  int ic = coordIndex[iCoord];
495 
496  if( ic >= (int)matSize )
497  m_current.mat->GetColor( &pc1, matIndex.back() );
498  else
499  m_current.mat->GetColor( &pc1, matIndex[ic] );
500  }
501  else
502  {
503  if( iCoord >= matSize )
504  m_current.mat->GetColor( &pc1, matIndex.back() );
505  else
506  m_current.mat->GetColor( &pc1, matIndex[iCoord] );
507  }
508 
509  fp->AddColor( pc1 );
510 
511  break;
512 
513  default:
514  break;
515  }
516  }
517  }
518 
519  // extract the final data set
520  SGNODE* np = lShape.CalcShape( aParent, sgcolor, m_current.order, m_current.creaseLimit );
521 
522  return np;
523 }
WRL1BASE represents the top node of a VRML1 model.
Definition: vrml1_base.h:45
SGNODE * TranslateToSG(SGNODE *aParent, WRL1STATUS *sp) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
SGNODE * CalcShape(SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
Definition: wrlfacet.cpp:713
bool AddRefNode(WRL1NODE *aNode) override
void Pop(void)
Definition: wrlproc.cpp:2007
glm::vec3 WRLVEC3F
Definition: wrltypes.h:185
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1951
#define MASK_VRML
Definition: wrltypes.h:37
WRL1_BINDING matbind
Definition: vrml1_node.h:75
WRL1STATUS m_current
Definition: vrml1_node.h:128
WRL1COORDS * coord
Definition: vrml1_node.h:73
float creaseLimit
Definition: vrml1_node.h:84
void AddVertex(WRLVEC3F &aVertex, int aIndex)
Function AddVertex adds the vertex and its associated index to the internal list of polygon vertices.
Definition: wrlfacet.cpp:193
void Init()
Definition: wrlfacet.cpp:158
std::vector< int > texIndex
Definition: vrml1_faceset.h:48
bool ReadMFInt(std::vector< int > &aMFInt32)
Definition: wrlproc.cpp:1488
SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
collects header files for all SG* wrappers and the API
std::list< WRL1NODE * > m_BackPointers
Definition: vrml1_node.h:122
glm::mat4 txmatrix
Definition: vrml1_node.h:79
declares classes to help manage normals calculations from VRML files
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
void AddColor(const SGCOLOR &aColor)
Function AddColor adds the given RGB color to the internal list.
Definition: wrlfacet.cpp:208
std::vector< int > normIndex
Definition: vrml1_faceset.h:47
WRL1_BINDING
Definition: wrltypes.h:97
#define NULL
std::list< WRL1NODE * > m_Refs
Definition: vrml1_node.h:124
bool HasColors()
Definition: wrlfacet.cpp:184
bool AddChildNode(WRL1NODE *aNode) override
WRL1NODE represents the base class of all VRML1 nodes.
Definition: vrml1_node.h:111
std::vector< int > matIndex
Definition: vrml1_faceset.h:46
SHAPE.
Definition: shape.h:122
std::vector< int > coordIndex
Definition: vrml1_faceset.h:45
char Peek(void)
Definition: wrlproc.cpp:1979
std::string GetFileName(void)
Definition: wrlproc.cpp:1967
virtual bool AddChildNode(WRL1NODE *aNode)
Definition: vrml1_node.cpp:442
SGNODE * GetAppearance(int aIndex)
Function GetAppearance returns an SGAPPEARANCE node representing the appearance for an IndexedFaceSet...
virtual ~WRL1FACESET()
WRL1NODES m_Type
Definition: vrml1_node.h:119
FACET * NewFacet()
Definition: wrlfacet.cpp:705
Definition: wrlfacet.h:41
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:280
void GetColor(SGCOLOR *aColor, int aIndex)
Function GetColor computes an SGCOLOR representing the appearance of a vertex or face.
WRL1FACESET(NAMEREGISTER *aDictionary)
WRL1NODE * m_Parent
Definition: vrml1_node.h:118
std::string GetError(void)
Definition: wrlproc.cpp:1945
void GetCoords(WRLVEC3F *&aCoordList, size_t &aListSize)
bool eof(void)
Definition: wrlproc.cpp:1939
WRL1_ORDER order
Definition: vrml1_node.h:81
WRL1MATERIAL * mat
Definition: vrml1_node.h:69
bool HasMinPoints()
Definition: wrlfacet.cpp:175
std::list< WRL1NODE * > m_Children
Definition: vrml1_node.h:123