KiCad PCB EDA Suite
x3d_ifaceset.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 <cmath>
28 #include <wx/log.h>
29 #include <wx/xml/xml.h>
30 #include <wx/tokenzr.h>
31 #include "x3d_ops.h"
32 #include "x3d_ifaceset.h"
33 #include "x3d_coords.h"
34 #include "plugins/3dapi/ifsg_all.h"
35 #include "wrlfacet.h"
36 
37 
39 {
41  coord = NULL;
42  init();
43 
44  return;
45 }
46 
47 
49 {
51  coord = NULL;
52  init();
53 
54  if( NULL != aParent )
55  {
56  X3DNODES ptype = aParent->GetNodeType();
57 
58  if( X3D_SHAPE == ptype )
59  m_Parent = aParent;
60  }
61 
62  if( NULL != m_Parent )
63  m_Parent->AddChildNode( this );
64 
65  return;
66 }
67 
68 
70 {
71  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
72  wxLogTrace( MASK_VRML, " * [INFO] Destroying IndexedFaceSet\n" );
73  #endif
74 
75  return;
76 }
77 
78 
80 {
81  coord = NULL;
82 
83  ccw = true;
84  creaseAngle = 0.733f; // approx 42 degrees; this is larger than VRML spec.
85  creaseLimit = 0.74317f; // cos( 0.733 )
86  return;
87 }
88 
89 
90 void X3DIFACESET::readFields( wxXmlNode* aNode )
91 {
92  // DEF
93  // ccw
94  // creaseAngle
95  // coordIndex
96 
97  wxXmlAttribute* prop;
98 
99  for( prop = aNode->GetAttributes();
100  prop != NULL;
101  prop = prop->GetNext() )
102  {
103  const wxString& pname = prop->GetName();
104 
105  if( pname == "DEF" )
106  {
107  m_Name = prop->GetValue();
108  m_Dict->AddName( m_Name, this );
109  }
110  else if( pname == "ccw" )
111  X3D::ParseSFBool( prop->GetValue(), ccw );
112  else if( pname == "creaseAngle" )
113  {
114  X3D::ParseSFFloat( prop->GetValue(), creaseAngle );
115 
116  if( creaseAngle < 0.0f )
117  creaseAngle = 0.0f;
118  else if( creaseAngle > static_cast<float>( M_PI * 0.34f ) )
119  creaseAngle = static_cast<float>( M_PI / 3.0f );
120 
121  creaseLimit = cosf( creaseAngle );
122  }
123  else if( pname == "coordIndex" )
124  {
125  wxStringTokenizer indices( prop->GetValue() );
126 
127  while( indices.HasMoreTokens() )
128  {
129  long index = 0;
130  indices.GetNextToken().ToLong( &index );
131  coordIndex.push_back( (int) index );
132  }
133  }
134  }
135 
136  return;
137 }
138 
139 
140 bool X3DIFACESET::Read( wxXmlNode* aNode, X3DNODE* aTopNode, X3D_DICT& aDict )
141 {
142  if( NULL == aTopNode || NULL == aNode )
143  return false;
144 
145  m_Dict = &aDict;
146  readFields( aNode );
147  bool ok = false;
148 
149  for( wxXmlNode* child = aNode->GetChildren();
150  child != NULL;
151  child = child->GetNext() )
152  {
153  if( child->GetName() == "Coordinate" )
154  ok = X3D::ReadCoordinates( child, this, aDict );
155 
156  }
157 
158  if( false == ok )
159  return false;
160 
161 
162  if( !SetParent( aTopNode ) )
163  return false;
164 
165  return true;
166 }
167 
168 
169 bool X3DIFACESET::SetParent( X3DNODE* aParent, bool doUnlink )
170 {
171  if( aParent == m_Parent )
172  return true;
173 
174  if( NULL != aParent )
175  {
176  X3DNODES nt = aParent->GetNodeType();
177 
178  if( nt != X3D_SHAPE )
179  return false;
180  }
181 
182  if( NULL != m_Parent && doUnlink )
183  m_Parent->unlinkChildNode( this );
184 
185  m_Parent = aParent;
186 
187  if( NULL != m_Parent )
188  m_Parent->AddChildNode( this );
189 
190  return true;
191 }
192 
193 
195 {
196  if( NULL == aNode )
197  return false;
198 
199  if( aNode->GetNodeType() != X3D_COORDINATE )
200  return false;
201 
202  if( aNode == coord )
203  return true;
204 
205  if( NULL != coord )
206  return false;
207 
208  m_Children.push_back( aNode );
209  coord = aNode;
210 
211  if( aNode->GetParent() != this )
212  aNode->SetParent( this );
213 
214  return true;
215 }
216 
217 
219 {
220  if( NULL == aNode )
221  return false;
222 
223  if( aNode->GetNodeType() != X3D_COORDINATE )
224  return false;
225 
226  if( aNode == coord )
227  return true;
228 
229  if( NULL != coord )
230  return false;
231 
232  m_Refs.push_back( aNode );
233  aNode->addNodeRef( this );
234  coord = aNode;
235  return true;
236 }
237 
238 
240 {
241  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
242 
243  if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
244  {
245  #ifdef DEBUG_X3D
246  do {
247  std::ostringstream ostr;
248  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
249  ostr << " * [BUG] IndexedFaceSet does not have a Shape parent (parent ID: ";
250  ostr << ptype << ")";
251  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
252  } while( 0 );
253  #endif
254 
255  return NULL;
256  }
257 
258  #if defined( DEBUG_X3D ) && ( DEBUG_X3D > 2 )
259  do {
260  std::ostringstream ostr;
261  ostr << " * [INFO] Translating IndexedFaceSet with " << m_Children.size();
262  ostr << " children, " << m_Refs.size() << " references, ";
263  ostr << m_BackPointers.size() << " backpointers and ";
264  ostr << coordIndex.size() << " coord indices";
265  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
266  } while( 0 );
267  #endif
268 
269  if( m_sgNode )
270  {
271  if( NULL != aParent )
272  {
274  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
275  {
276  return NULL;
277  }
278  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
279  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
280  {
281  return NULL;
282  }
283  }
284 
285  return m_sgNode;
286  }
287 
288  size_t vsize = coordIndex.size();
289 
290  if( NULL == coord || vsize < 3 )
291  return NULL;
292 
293  WRLVEC3F* pcoords;
294  size_t coordsize;
295  ((X3DCOORDS*) coord)->GetCoords( pcoords, coordsize );
296 
297  if( coordsize < 3 )
298  return NULL;
299 
300  // check that all indices are valid
301  for( size_t idx = 0; idx < vsize; ++idx )
302  {
303  if( coordIndex[idx] < 0 )
304  continue;
305 
306  if( coordIndex[idx] >= (int)coordsize )
307  return NULL;
308  }
309 
310  SHAPE lShape;
311  FACET* fp = NULL;
312  size_t iCoord;
313  int idx; // coordinate index
314 
315  // no per-vertex colors; we can save a few CPU cycles
316  for( iCoord = 0; iCoord < vsize; ++iCoord )
317  {
318  idx = coordIndex[iCoord];
319 
320  if( idx < 0 )
321  {
322  if( NULL != fp )
323  {
324  if( fp->HasMinPoints() )
325  fp = NULL;
326  else
327  fp->Init();
328  }
329 
330  continue;
331  }
332 
333  // if the coordinate is bad then skip it
334  if( idx >= (int)coordsize )
335  continue;
336 
337  if( NULL == fp )
338  fp = lShape.NewFacet();
339 
340  // push the vertex value and index
341  fp->AddVertex( pcoords[idx], idx );
342  }
343 
344  SGNODE* np = NULL;
345 
346  if( ccw )
347  np = lShape.CalcShape( aParent, NULL, ORD_CCW, creaseLimit, true );
348  else
349  np = lShape.CalcShape( aParent, NULL, ORD_CLOCKWISE, creaseLimit, true );
350 
351  return np;
352 }
void readFields(wxXmlNode *aNode)
float creaseLimit
Definition: x3d_ifaceset.h:48
SGNODE * CalcShape(SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
Definition: wrlfacet.cpp:713
virtual bool SetParent(X3DNODE *aParent, bool doUnlink=true)=0
Function SetParent sets the parent X3DNODE of this object.
X3DNODE * coord
Definition: x3d_ifaceset.h:44
glm::vec3 WRLVEC3F
Definition: wrltypes.h:185
std::list< X3DNODE * > m_BackPointers
Definition: x3d_base.h:82
#define MASK_VRML
Definition: wrltypes.h:37
X3DNODES m_Type
Definition: x3d_base.h:79
X3DNODE * GetParent(void) const
Function GetParent returns a pointer to the parent node of this object or NULL if the object has no p...
Definition: x3d_base.cpp:192
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
wxString m_Name
Definition: x3d_base.h:87
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
void addNodeRef(X3DNODE *aNode)
Function addNodeRef adds a pointer to a node which references, but does not own, this node.
Definition: x3d_base.cpp:141
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
X3DCOORDS.
Definition: x3d_coords.h:41
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
std::list< X3DNODE * > m_Children
Definition: x3d_base.h:83
bool AddChildNode(X3DNODE *aNode) override
X3DNODE represents the base class of all X3D nodes.
Definition: x3d_base.h:75
declares classes to help manage normals calculations from VRML files
#define NULL
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
bool SetParent(X3DNODE *aParent, bool doUnlink=true) override
Function SetParent sets the parent X3DNODE of this object.
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
bool ParseSFFloat(const wxString &aSource, float &aResult)
Definition: x3d_ops.cpp:261
SHAPE.
Definition: shape.h:122
virtual bool AddChildNode(X3DNODE *aNode)=0
X3DNODES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: x3d_base.cpp:186
virtual void unlinkChildNode(const X3DNODE *aNode)
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
Definition: x3d_base.cpp:101
std::vector< int > coordIndex
Definition: x3d_ifaceset.h:49
bool AddName(const wxString &aName, X3DNODE *aNode)
Definition: x3d_base.cpp:34
bool AddRefNode(X3DNODE *aNode) override
SGTYPES
Definition: sg_types.h:34
SGNODE * m_sgNode
Definition: x3d_base.h:88
bool ParseSFBool(const wxString &aSource, bool &aResult)
Definition: x3d_ops.cpp:240
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:627
X3DNODE * m_Parent
Definition: x3d_base.h:78
FACET * NewFacet()
Definition: wrlfacet.cpp:705
Definition: wrlfacet.h:41
virtual ~X3DIFACESET()
float creaseAngle
Definition: x3d_ifaceset.h:47
X3DNODES
Definition: x3d_base.h:59
X3D_DICT * m_Dict
Definition: x3d_base.h:80
bool ReadCoordinates(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:200
bool Read(wxXmlNode *aNode, X3DNODE *aTopNode, X3D_DICT &aDict) override
bool HasMinPoints()
Definition: wrlfacet.cpp:175
std::list< X3DNODE * > m_Refs
Definition: x3d_base.h:84