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 <[email protected]>
5  * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <iostream>
27 #include <sstream>
28 #include <wx/log.h>
29 
30 #include "vrml2_base.h"
31 #include "vrml2_box.h"
32 #include "plugins/3dapi/ifsg_all.h"
33 
34 
36 {
38  size.x = 2.0;
39  size.y = 2.0;
40  size.z = 2.0;
41 }
42 
43 
45 {
47  m_Parent = aParent;
48  size.x = 2.0;
49  size.y = 2.0;
50  size.z = 2.0;
51 
52  if( nullptr != m_Parent )
53  m_Parent->AddChildNode( this );
54 }
55 
56 
58 {
59  wxLogTrace( traceVrmlPlugin, " * [INFO] Destroying Box node." );
60 }
61 
62 
63 bool WRL2BOX::isDangling( void )
64 {
65  // this node is dangling unless it has a parent of type WRL2_SHAPE
66 
67  if( nullptr == m_Parent || m_Parent->GetNodeType() != WRL2NODES::WRL2_SHAPE )
68  return true;
69 
70  return false;
71 }
72 
73 
74 bool WRL2BOX::Read( WRLPROC& proc, WRL2BASE* aTopNode )
75 {
76  char tok = proc.Peek();
77 
78  if( proc.eof() )
79  {
80  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
81  " * [INFO] bad file format; unexpected eof %s." ),
82  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
83 
84  return false;
85  }
86 
87  if( '{' != tok )
88  {
89  wxLogTrace( traceVrmlPlugin,
90  wxT( "%s:%s:%d\n"
91  " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
92  __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
93 
94  return false;
95  }
96 
97  proc.Pop();
98  std::string glob;
99 
100  if( proc.Peek() == '}' )
101  {
102  proc.Pop();
103  return true;
104  }
105 
106  if( !proc.ReadName( glob ) )
107  {
108  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
109  "%s" ),
110  __FILE__, __FUNCTION__, __LINE__ , proc.GetError() );
111 
112  return false;
113  }
114 
115  // expecting 'size'
116  if( !glob.compare( "size" ) )
117  {
118  if( !proc.ReadSFVec3f( size ) )
119  {
120  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d"
121  " * [INFO] invalid size %s\n"
122  " * [INFO] file: '%s'\n"
123  "%s" ),
124  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
125  proc.GetFileName(), proc.GetError() );
126 
127  return false;
128  }
129 
130  // for legacy KiCad support we interpret units as 0.1 inch
131  size *= 2.54;
132  }
133  else
134  {
135  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d"
136  " * [INFO] invalid Box %s\n"
137  " * [INFO] file: '%s'\n" ),
138  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
139  proc.GetFileName() );
140 
141  return false;
142  }
143 
144  if( size.x < 1e-6 || size.y < 1e-6 || size.z < 1e-6 )
145  {
146  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d"
147  " * [INFO] invalid Box size %s\n"
148  " * [INFO] file: '%s'\n" ),
149  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
150  proc.GetFileName() );
151 
153  }
154 
155  if( proc.Peek() == '}' )
156  {
157  proc.Pop();
158  return true;
159  }
160 
161  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d"
162  " * [INFO] invalid size %s (no closing brace).\n"
163  " * [INFO] file: '%s'\n" ),
164  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(), proc.GetFileName() );
165 
166  return false;
167 }
168 
169 
171 {
172  // this node may not own or reference any other node
173  wxCHECK_MSG( false, false, wxT( "AddRefNode is not applicable." ) );
174 }
175 
176 
178 {
179  // this node may not own or reference any other node
180  wxCHECK_MSG( false, false, wxT( "AddChildNode is not applicable." ) );
181 }
182 
183 
185 {
186  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
187 
188  wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_SHAPE ), nullptr,
189  wxString::Format( wxT( "Box does not have a Shape parent (parent ID: %s)" ),
190  ptype ) );
191 
192  // do not render a bad box
193  if( size.x < 1e-6 || size.y < 1e-6 || size.z < 1e-6 )
194  return nullptr;
195 
196  if( m_sgNode )
197  {
198  if( nullptr != aParent )
199  {
200  if( nullptr == S3D::GetSGNodeParent( m_sgNode )
201  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
202  {
203  return nullptr;
204  }
205  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
206  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
207  {
208  return nullptr;
209  }
210  }
211 
212  return m_sgNode;
213  }
214 
215  // create the vertices, triangle indices, and normals
216  float x = size.x / 2.0;
217  float y = size.y / 2.0;
218  float z = size.z / 2.0;
219  std::vector< SGPOINT > vertices;
220  std::vector< SGVECTOR > norms;
221  std::vector< int > idx;
222  int base = 0;
223 
224  // top
225  vertices.emplace_back( -x, -y, z );
226  vertices.emplace_back( x, -y, z );
227  vertices.emplace_back( x, y, z );
228  vertices.emplace_back( -x, y, z );
229  norms.emplace_back( 0.0, 0.0, 1.0 );
230  norms.emplace_back( 0.0, 0.0, 1.0 );
231  norms.emplace_back( 0.0, 0.0, 1.0 );
232  norms.emplace_back( 0.0, 0.0, 1.0 );
233  idx.push_back( base );
234  idx.push_back( base + 1 );
235  idx.push_back( base + 2 );
236  idx.push_back( base );
237  idx.push_back( base + 2 );
238  idx.push_back( base + 3 );
239  base += 4;
240 
241  // bottom
242  vertices.emplace_back( -x, -y, -z );
243  vertices.emplace_back( x, -y, -z );
244  vertices.emplace_back( x, y, -z );
245  vertices.emplace_back( -x, y, -z );
246  norms.emplace_back( 0.0, 0.0, -1.0 );
247  norms.emplace_back( 0.0, 0.0, -1.0 );
248  norms.emplace_back( 0.0, 0.0, -1.0 );
249  norms.emplace_back( 0.0, 0.0, -1.0 );
250  idx.push_back( base );
251  idx.push_back( base + 2 );
252  idx.push_back( base + 1 );
253  idx.push_back( base );
254  idx.push_back( base + 3 );
255  idx.push_back( base + 2 );
256  base += 4;
257 
258  // front
259  vertices.emplace_back( -x, -y, z );
260  vertices.emplace_back( -x, -y, -z );
261  vertices.emplace_back( x, -y, -z );
262  vertices.emplace_back( x, -y, z );
263  norms.emplace_back( 0.0, -1.0, 0.0 );
264  norms.emplace_back( 0.0, -1.0, 0.0 );
265  norms.emplace_back( 0.0, -1.0, 0.0 );
266  norms.emplace_back( 0.0, -1.0, 0.0 );
267  idx.push_back( base );
268  idx.push_back( base + 1 );
269  idx.push_back( base + 2 );
270  idx.push_back( base );
271  idx.push_back( base + 2 );
272  idx.push_back( base + 3 );
273  base += 4;
274 
275  // back
276  vertices.emplace_back( -x, y, z );
277  vertices.emplace_back( -x, y, -z );
278  vertices.emplace_back( x, y, -z );
279  vertices.emplace_back( x, y, z );
280  norms.emplace_back( 0.0, 1.0, 0.0 );
281  norms.emplace_back( 0.0, 1.0, 0.0 );
282  norms.emplace_back( 0.0, 1.0, 0.0 );
283  norms.emplace_back( 0.0, 1.0, 0.0 );
284  idx.push_back( base );
285  idx.push_back( base + 2 );
286  idx.push_back( base + 1 );
287  idx.push_back( base );
288  idx.push_back( base + 3 );
289  idx.push_back( base + 2 );
290  base += 4;
291 
292  // left
293  vertices.emplace_back( -x, -y, -z );
294  vertices.emplace_back( -x, -y, z );
295  vertices.emplace_back( -x, y, z );
296  vertices.emplace_back( -x, y, -z );
297  norms.emplace_back( -1.0, 0.0, 0.0 );
298  norms.emplace_back( -1.0, 0.0, 0.0 );
299  norms.emplace_back( -1.0, 0.0, 0.0 );
300  norms.emplace_back( -1.0, 0.0, 0.0 );
301  idx.push_back( base );
302  idx.push_back( base + 1 );
303  idx.push_back( base + 2 );
304  idx.push_back( base );
305  idx.push_back( base + 2 );
306  idx.push_back( base + 3 );
307  base += 4;
308 
309  // right
310  vertices.emplace_back( x, -y, -z );
311  vertices.emplace_back( x, -y, z );
312  vertices.emplace_back( x, y, z );
313  vertices.emplace_back( x, y, -z );
314  norms.emplace_back( 1.0, 0.0, 0.0 );
315  norms.emplace_back( 1.0, 0.0, 0.0 );
316  norms.emplace_back( 1.0, 0.0, 0.0 );
317  norms.emplace_back( 1.0, 0.0, 0.0 );
318  idx.push_back( base );
319  idx.push_back( base + 2 );
320  idx.push_back( base + 1 );
321  idx.push_back( base );
322  idx.push_back( base + 3 );
323  idx.push_back( base + 2 );
324 
325  IFSG_FACESET fsNode( aParent );
326  IFSG_COORDS cpNode( fsNode );
327  cpNode.SetCoordsList( vertices.size(), &vertices[0] );
328  IFSG_COORDINDEX ciNode( fsNode );
329  ciNode.SetIndices( idx.size(), &idx[0] );
330  IFSG_NORMALS nmNode( fsNode );
331  nmNode.SetNormalList( norms.size(), &norms[0] );
332 
333  m_sgNode = fsNode.GetRawPtr();
334 
335  return m_sgNode;
336 }
void Pop(void)
Definition: wrlproc.cpp:2035
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:40
bool isDangling(void) override
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
Definition: vrml2_box.cpp:63
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
bool ReadSFVec3f(WRLVEC3F &aSFVec3f)
Definition: wrlproc.cpp:1082
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:492
WRL2NODES m_Type
Definition: vrml2_node.h:170
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
collects header files for all SG* wrappers and the API
bool AddChildNode(WRL2NODE *aNode) override
Definition: vrml2_box.cpp:177
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:65
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:501
IFSG_NORMALS is the wrapper for the SGNORMALS class.
Definition: ifsg_normals.h:40
WRL2NODE * m_Parent
Definition: vrml2_node.h:169
virtual ~WRL2BOX()
Definition: vrml2_box.cpp:57
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:510
std::string GetFilePosition() const
Definition: wrlproc.cpp:1982
SGNODE * m_sgNode
Definition: vrml2_node.h:178
WRLVEC3F size
Definition: vrml2_box.h:53
WRL2NODES GetNodeType(void) const
Definition: vrml2_node.cpp:204
char Peek(void)
Definition: wrlproc.cpp:2007
std::string GetFileName(void)
Definition: wrlproc.cpp:1995
The top node of a VRML2 model.
Definition: vrml2_base.h:59
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
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:47
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:483
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:356
bool SetCoordsList(size_t aListSize, const SGPOINT *aCoordsList)
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:289
bool AddRefNode(WRL2NODE *aNode) override
Definition: vrml2_box.cpp:170
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:1960
bool eof(void)
Definition: wrlproc.cpp:1954
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
Definition: vrml2_box.cpp:74
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
Definition: vrml2_box.cpp:184