KiCad PCB EDA Suite
vrml2_box.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 "vrml2_base.h"
30 #include "vrml2_box.h"
31 #include "plugins/3dapi/ifsg_all.h"
32 
33 
35 {
36  m_Type = WRL2_BOX;
37  size.x = 2.0;
38  size.y = 2.0;
39  size.z = 2.0;
40 
41  return;
42 }
43 
44 
46 {
47  m_Type = WRL2_BOX;
48  m_Parent = aParent;
49  size.x = 2.0;
50  size.y = 2.0;
51  size.z = 2.0;
52 
53  if( NULL != m_Parent )
54  m_Parent->AddChildNode( this );
55 
56  return;
57 }
58 
59 
61 {
62  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
63  wxLogTrace( MASK_VRML, " * [INFO] Destroying Box node\n" );
64  #endif
65 
66  return;
67 }
68 
69 
70 bool WRL2BOX::isDangling( void )
71 {
72  // this node is dangling unless it has a parent of type WRL2_SHAPE
73 
74  if( NULL == m_Parent || m_Parent->GetNodeType() != WRL2_SHAPE )
75  return true;
76 
77  return false;
78 }
79 
80 
81 bool WRL2BOX::Read( WRLPROC& proc, WRL2BASE* aTopNode )
82 {
83  size_t line, column;
84  proc.GetFilePosData( line, column );
85 
86  char tok = proc.Peek();
87 
88  if( proc.eof() )
89  {
90  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
91  do {
92  std::ostringstream ostr;
93  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
94  ostr << " * [INFO] bad file format; unexpected eof at line ";
95  ostr << line << ", column " << column;
96  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
97  } while( 0 );
98  #endif
99 
100  return false;
101  }
102 
103  if( '{' != tok )
104  {
105  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
106  do {
107  std::ostringstream ostr;
108  ostr << proc.GetError() << "\n";
109  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
110  ostr << " * [INFO] bad file format; expecting '{' but got '" << tok;
111  ostr << "' at line " << line << ", column " << column;
112  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
113  } while( 0 );
114  #endif
115 
116  return false;
117  }
118 
119  proc.Pop();
120  std::string glob;
121 
122  if( proc.Peek() == '}' )
123  {
124  proc.Pop();
125  return true;
126  }
127 
128  if( !proc.ReadName( glob ) )
129  {
130  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
131  do {
132  std::ostringstream ostr;
133  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
134  ostr << proc.GetError();
135  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
136  } while( 0 );
137  #endif
138 
139  return false;
140  }
141 
142  proc.GetFilePosData( line, column );
143 
144  // expecting 'size'
145  if( !glob.compare( "size" ) )
146  {
147  if( !proc.ReadSFVec3f( size ) )
148  {
149  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
150  do {
151  std::ostringstream ostr;
152  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
153  ostr << " * [INFO] invalid size at line " << line << ", column ";
154  ostr << column << "\n";
155  ostr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
156  ostr << " * [INFO] message: '" << proc.GetError() << "'";
157  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
158  } while( 0 );
159  #endif
160 
161  return false;
162  }
163 
164  // for legacy KiCad support we interpret units as 0.1 inch
165  size *= 2.54;
166  }
167  else
168  {
169  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
170  do {
171  std::ostringstream ostr;
172  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
173  ostr << " * [INFO] bad Box at line " << line << ", column ";
174  ostr << column << "\n";
175  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
176  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
177  } while( 0 );
178  #endif
179 
180  return false;
181  }
182 
183  if( size.x < 1e-6 || size.y < 1e-6 || size.z < 1e-6 )
184  {
185  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
186  do {
187  std::ostringstream ostr;
188  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
189  ostr << " * [INFO] bad Box (invalid size) at line " << line << ", column ";
190  ostr << column << "\n";
191  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
192  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
193  } while( 0 );
194  #endif
195  }
196 
197  if( proc.Peek() == '}' )
198  {
199  proc.Pop();
200  return true;
201  }
202 
203  proc.GetFilePosData( line, column );
204 
205  #if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
206  do {
207  std::ostringstream ostr;
208  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
209  ostr << " * [INFO] bad Box at line " << line << ", column ";
210  ostr << column << " (no closing brace)\n";
211  ostr << " * [INFO] file: '" << proc.GetFileName() << "'";
212  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
213  } while( 0 );
214  #endif
215 
216  return false;
217 }
218 
219 
221 {
222  // this node may not own or reference any other node
223 
224  #ifdef DEBUG_VRML2
225  do {
226  std::ostringstream ostr;
227  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
228  ostr << " * [BUG] AddRefNode is not applicable";
229  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
230  } while( 0 );
231  #endif
232 
233  return false;
234 }
235 
236 
238 {
239  // this node may not own or reference any other node
240 
241  #ifdef DEBUG_VRML2
242  do {
243  std::ostringstream ostr;
244  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
245  ostr << " * [BUG] AddChildNode is not applicable";
246  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
247  } while( 0 );
248  #endif
249 
250  return false;
251 }
252 
253 
255 {
256  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
257 
258  if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
259  {
260  #ifdef DEBUG_VRML2
261  do {
262  std::ostringstream ostr;
263  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
264  ostr << " * [BUG] Box does not have a Shape parent (parent ID: ";
265  ostr << ptype << ")";
266  wxLogTrace( MASK_VRML, "%s\n", ostr.str().c_str() );
267  } while( 0 );
268  #endif
269 
270  return NULL;
271  }
272 
273  // do not render a bad box
274  if( size.x < 1e-6 || size.y < 1e-6 || size.z < 1e-6 )
275  return NULL;
276 
277  if( m_sgNode )
278  {
279  if( NULL != aParent )
280  {
282  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
283  {
284  return NULL;
285  }
286  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
287  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
288  {
289  return NULL;
290  }
291  }
292 
293  return m_sgNode;
294  }
295 
296  // create the vertices, triangle indices, and normals
297  float x = size.x / 2.0;
298  float y = size.y / 2.0;
299  float z = size.z / 2.0;
300  std::vector< SGPOINT > vertices;
301  std::vector< SGVECTOR > norms;
302  std::vector< int > idx;
303  int base = 0;
304  // top
305  vertices.emplace_back( -x, -y, z );
306  vertices.emplace_back( x, -y, z );
307  vertices.emplace_back( x, y, z );
308  vertices.emplace_back( -x, y, z );
309  norms.emplace_back( 0.0, 0.0, 1.0 );
310  norms.emplace_back( 0.0, 0.0, 1.0 );
311  norms.emplace_back( 0.0, 0.0, 1.0 );
312  norms.emplace_back( 0.0, 0.0, 1.0 );
313  idx.push_back( base );
314  idx.push_back( base + 1 );
315  idx.push_back( base + 2 );
316  idx.push_back( base );
317  idx.push_back( base + 2 );
318  idx.push_back( base + 3 );
319  base += 4;
320  // bottom
321  vertices.emplace_back( -x, -y, -z );
322  vertices.emplace_back( x, -y, -z );
323  vertices.emplace_back( x, y, -z );
324  vertices.emplace_back( -x, y, -z );
325  norms.emplace_back( 0.0, 0.0, -1.0 );
326  norms.emplace_back( 0.0, 0.0, -1.0 );
327  norms.emplace_back( 0.0, 0.0, -1.0 );
328  norms.emplace_back( 0.0, 0.0, -1.0 );
329  idx.push_back( base );
330  idx.push_back( base + 2 );
331  idx.push_back( base + 1 );
332  idx.push_back( base );
333  idx.push_back( base + 3 );
334  idx.push_back( base + 2 );
335  base += 4;
336  // front
337  vertices.emplace_back( -x, -y, z );
338  vertices.emplace_back( -x, -y, -z );
339  vertices.emplace_back( x, -y, -z );
340  vertices.emplace_back( x, -y, z );
341  norms.emplace_back( 0.0, -1.0, 0.0 );
342  norms.emplace_back( 0.0, -1.0, 0.0 );
343  norms.emplace_back( 0.0, -1.0, 0.0 );
344  norms.emplace_back( 0.0, -1.0, 0.0 );
345  idx.push_back( base );
346  idx.push_back( base + 1 );
347  idx.push_back( base + 2 );
348  idx.push_back( base );
349  idx.push_back( base + 2 );
350  idx.push_back( base + 3 );
351  base += 4;
352  // back
353  vertices.emplace_back( -x, y, z );
354  vertices.emplace_back( -x, y, -z );
355  vertices.emplace_back( x, y, -z );
356  vertices.emplace_back( x, y, z );
357  norms.emplace_back( 0.0, 1.0, 0.0 );
358  norms.emplace_back( 0.0, 1.0, 0.0 );
359  norms.emplace_back( 0.0, 1.0, 0.0 );
360  norms.emplace_back( 0.0, 1.0, 0.0 );
361  idx.push_back( base );
362  idx.push_back( base + 2 );
363  idx.push_back( base + 1 );
364  idx.push_back( base );
365  idx.push_back( base + 3 );
366  idx.push_back( base + 2 );
367  base += 4;
368  // left
369  vertices.emplace_back( -x, -y, -z );
370  vertices.emplace_back( -x, -y, z );
371  vertices.emplace_back( -x, y, z );
372  vertices.emplace_back( -x, y, -z );
373  norms.emplace_back( -1.0, 0.0, 0.0 );
374  norms.emplace_back( -1.0, 0.0, 0.0 );
375  norms.emplace_back( -1.0, 0.0, 0.0 );
376  norms.emplace_back( -1.0, 0.0, 0.0 );
377  idx.push_back( base );
378  idx.push_back( base + 1 );
379  idx.push_back( base + 2 );
380  idx.push_back( base );
381  idx.push_back( base + 2 );
382  idx.push_back( base + 3 );
383  base += 4;
384  // right
385  vertices.emplace_back( x, -y, -z );
386  vertices.emplace_back( x, -y, z );
387  vertices.emplace_back( x, y, z );
388  vertices.emplace_back( x, y, -z );
389  norms.emplace_back( 1.0, 0.0, 0.0 );
390  norms.emplace_back( 1.0, 0.0, 0.0 );
391  norms.emplace_back( 1.0, 0.0, 0.0 );
392  norms.emplace_back( 1.0, 0.0, 0.0 );
393  idx.push_back( base );
394  idx.push_back( base + 2 );
395  idx.push_back( base + 1 );
396  idx.push_back( base );
397  idx.push_back( base + 3 );
398  idx.push_back( base + 2 );
399 
400  IFSG_FACESET fsNode( aParent );
401  IFSG_COORDS cpNode( fsNode );
402  cpNode.SetCoordsList( vertices.size(), &vertices[0] );
403  IFSG_COORDINDEX ciNode( fsNode );
404  ciNode.SetIndices( idx.size(), &idx[0] );
405  IFSG_NORMALS nmNode( fsNode );
406  nmNode.SetNormalList( norms.size(), &norms[0] );
407 
408  m_sgNode = fsNode.GetRawPtr();
409 
410  return m_sgNode;
411 }
void Pop(void)
Definition: wrlproc.cpp:2007
WRL2NODE represents the base class of all VRML2 nodes.
Definition: vrml2_node.h:58
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:40
bool isDangling(void) override
Function isDangling returns true if the object does not have a parent which is a logical container fo...
Definition: vrml2_box.cpp:70
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1951
bool ReadSFVec3f(WRLVEC3F &aSFVec3f)
Definition: wrlproc.cpp:1065
#define MASK_VRML
Definition: wrltypes.h:37
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:636
WRL2NODES m_Type
Definition: vrml2_node.h:62
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
bool AddChildNode(WRL2NODE *aNode) override
Definition: vrml2_box.cpp:237
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:66
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:645
IFSG_NORMALS is the wrapper for the SGNORMALS class.
Definition: ifsg_normals.h:40
#define NULL
WRL2NODE * m_Parent
Definition: vrml2_node.h:61
virtual ~WRL2BOX()
Definition: vrml2_box.cpp:60
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:654
SGNODE * m_sgNode
Definition: vrml2_node.h:70
WRLVEC3F size
Definition: vrml2_box.h:43
WRL2NODES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: vrml2_node.cpp:212
char Peek(void)
Definition: wrlproc.cpp:1979
std::string GetFileName(void)
Definition: wrlproc.cpp:1967
WRL2BASE represents the top node of a VRML2 model.
Definition: vrml2_base.h:59
SGTYPES
Definition: sg_types.h:34
bool SetIndices(size_t nIndices, int *aIndexList)
Function SetIndices sets the number of indices and creates a copy of the given index data.
Definition: ifsg_index.cpp:63
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:627
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:377
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:280
bool AddRefNode(WRL2NODE *aNode) override
Definition: vrml2_box.cpp:220
bool SetNormalList(size_t aListSize, const SGVECTOR *aNormalList)
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:40
std::string GetError(void)
Definition: wrlproc.cpp:1945
bool eof(void)
Definition: wrlproc.cpp:1939
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
Definition: vrml2_box.cpp:81
SGNODE * TranslateToSG(SGNODE *aParent) override
Function TranslateToSG produces a representation of the data using the intermediate scenegraph struct...
Definition: vrml2_box.cpp:254