KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vrml2_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) 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_shape.h"
33#include "vrml2_faceset.h"
34
35
37{
38 appearance = nullptr;
39 geometry = nullptr;
40 m_Type = WRL2NODES::WRL2_SHAPE;
41}
42
43
45{
46 appearance = nullptr;
47 geometry = nullptr;
48 m_Type = WRL2NODES::WRL2_SHAPE;
49 m_Parent = aParent;
50
51 if( nullptr != m_Parent )
52 m_Parent->AddChildNode( this );
53}
54
55
57{
58 wxLogTrace( traceVrmlPlugin,
59 wxT( " * [INFO] Destroying Shape node with %zu children, %zu"
60 "references, and %zu back pointers." ),
61 m_Children.size(), m_Refs.size(), m_BackPointers.size() );
62}
63
64
66{
67 // this node is dangling unless it has a parent of type:
68 // WRL2_TRANSFORM
69 // WRL2_SWITCH
70
71 if( nullptr == m_Parent
72 || ( m_Parent->GetNodeType() != WRL2NODES::WRL2_TRANSFORM
73 && m_Parent->GetNodeType() != WRL2NODES::WRL2_SWITCH ) )
74 return true;
75
76 return false;
77}
78
79
81{
82 wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
83
84 WRL2NODES type = aNode->GetNodeType();
85
86 if( !checkNodeType( type ) )
87 {
88 wxLogTrace( traceVrmlPlugin,
89 wxT( "%s:%s:%d\n"
90 " * [INFO] bad file format; unexpected child node '%s'." ),
91 __FILE__, __FUNCTION__, __LINE__, aNode->GetNodeTypeName( type ) );
92
93 return false;
94 }
95
96 if( WRL2NODES::WRL2_APPEARANCE == type )
97 {
98 if( nullptr != appearance )
99 {
100 wxLogTrace( traceVrmlPlugin,
101 wxT( "%s:%s:%d\n"
102 " * [INFO] bad file format; multiple appearance nodes." ),
103 __FILE__, __FUNCTION__, __LINE__ );
104
105 return false;
106 }
107
108 appearance = aNode;
109 return WRL2NODE::AddRefNode( aNode );
110 }
111
112 if( nullptr != geometry )
113 {
114 wxLogTrace( traceVrmlPlugin,
115 wxT( "%s:%s:%d\n"
116 " * [INFO] bad file format; multiple geometry nodes." ),
117 __FILE__, __FUNCTION__, __LINE__ );
118
119 return false;
120 }
121
122 geometry = aNode;
123 return WRL2NODE::AddRefNode( aNode );
124}
125
126
128{
129 wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
130
131 WRL2NODES type = aNode->GetNodeType();
132
133 if( !checkNodeType( type ) )
134 {
135 wxLogTrace( traceVrmlPlugin,
136 wxT( "%s:%s:%d\n"
137 " * [INFO] bad file format; unexpected child node '%s'." ),
138 __FILE__, __FUNCTION__, __LINE__, aNode->GetNodeTypeName( type ) );
139
140 return false;
141 }
142
143 if( WRL2NODES::WRL2_APPEARANCE == type )
144 {
145 if( nullptr != appearance )
146 {
147 wxLogTrace( traceVrmlPlugin,
148 wxT( "%s:%s:%d\n"
149 " * [INFO] bad file format; multiple appearance nodes." ),
150 __FILE__, __FUNCTION__, __LINE__ );
151
152 return false;
153 }
154
155 appearance = aNode;
156 return WRL2NODE::AddChildNode( aNode );
157 }
158
159 if( nullptr != geometry )
160 {
161 wxLogTrace( traceVrmlPlugin,
162 wxT( "%s:%s:%d\n"
163 " * [INFO] bad file format; multiple geometry nodes." ),
164 __FILE__, __FUNCTION__, __LINE__ );
165
166 return false;
167 }
168
169 geometry = aNode;
170 return WRL2NODE::AddChildNode( aNode );
171}
172
173
175{
176 switch( aType )
177 {
178 case WRL2NODES::WRL2_APPEARANCE:
179 case WRL2NODES::WRL2_BOX:
180 case WRL2NODES::WRL2_CONE:
181 case WRL2NODES::WRL2_CYLINDER:
182 case WRL2NODES::WRL2_ELEVATIONGRID:
183 case WRL2NODES::WRL2_EXTRUSION:
184 case WRL2NODES::WRL2_INDEXEDFACESET:
185 case WRL2NODES::WRL2_INDEXEDLINESET:
186 case WRL2NODES::WRL2_POINTSET:
187 case WRL2NODES::WRL2_SPHERE:
188 case WRL2NODES::WRL2_TEXT:
189 break;
190
191 default:
192 return false;
193 break;
194 }
195
196 return true;
197}
198
199
200bool WRL2SHAPE::Read( WRLPROC& proc, WRL2BASE* aTopNode )
201{
202 wxCHECK_MSG( aTopNode, false, wxT( "Invalid top node." ) );
203
204 char tok = proc.Peek();
205
206 if( proc.eof() )
207 {
208 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
209 " * [INFO] bad file format; unexpected eof %s." ),
210 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
211
212 return false;
213 }
214
215 if( '{' != tok )
216 {
217 wxLogTrace( traceVrmlPlugin,
218 wxT( "%s:%s:%d\n"
219 " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
220 __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
221
222 return false;
223 }
224
225 proc.Pop();
226 std::string glob;
227
228 while( true )
229 {
230 if( proc.Peek() == '}' )
231 {
232 proc.Pop();
233 break;
234 }
235
236 if( !proc.ReadName( glob ) )
237 {
238 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
239 "%s" ),
240 __FILE__, __FUNCTION__, __LINE__ , proc.GetError() );
241
242 return false;
243 }
244
245 // expecting one of:
246 // appearance
247 // geometry
248 if( !glob.compare( "appearance" ) )
249 {
250 if( !aTopNode->ReadNode( proc, this, nullptr ) )
251 {
252 wxLogTrace( traceVrmlPlugin,
253 wxT( "%s:%s:%d\n"
254 " * [INFO] could not read appearance node information." ),
255 __FILE__, __FUNCTION__, __LINE__ );
256
257 return false;
258 }
259 }
260 else if( !glob.compare( "geometry" ) )
261 {
262 if( !aTopNode->ReadNode( proc, this, nullptr ) )
263 {
264 wxLogTrace( traceVrmlPlugin,
265 wxT( "%s:%s:%d\n"
266 " * [INFO] could not read geometry node information." ),
267 __FILE__, __FUNCTION__, __LINE__ );
268
269 return false;
270 }
271 }
272 else
273 {
274 wxLogTrace( traceVrmlPlugin,
275 wxT( "%s:%s:%d\n"
276 " * [INFO] invalid Shape %s.\n"
277 " * [INFO] file: '%s'\n" ),
278 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
279 proc.GetFileName() );
280
281 return false;
282 }
283 } // while( true ) -- reading contents of Shape{}
284
285 return true;
286}
287
288
290{
291 if( nullptr == geometry )
292 return nullptr;
293
294 WRL2NODES geomType = geometry->GetNodeType();
295
296 switch( geomType )
297 {
298 case WRL2NODES::WRL2_INDEXEDLINESET:
299 case WRL2NODES::WRL2_POINTSET:
300 case WRL2NODES::WRL2_TEXT:
301 return nullptr;
302 break;
303
304 default:
305 break;
306 }
307
308 wxLogTrace( traceVrmlPlugin,
309 wxT( " * [INFO] Translating Shape with %zu children, %zu references, and"
310 "%zu back pointers." ),
311 m_Children.size(), m_Refs.size(), m_BackPointers.size() );
312
313 bool vcolors = false;
314
315 if( WRL2NODES::WRL2_INDEXEDFACESET == geometry->GetNodeType() )
316 vcolors = ((WRL2FACESET*)geometry)->HasColors();
317
318 // if there is no appearance, make use of the per vertex colors if available
319 if( nullptr == appearance )
320 {
321 if( WRL2NODES::WRL2_INDEXEDFACESET != geometry->GetNodeType() )
322 return nullptr;
323
324 if( !vcolors )
325 return nullptr;
326 }
327
328 S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
329
330 wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_TRANSFORM ), nullptr,
331 wxString::Format( wxT( "Shape does not have a Transform parent (parent "
332 "ID: %d)." ), ptype ) );
333
334 if( m_sgNode )
335 {
336 if( nullptr != aParent )
337 {
338 if( nullptr == S3D::GetSGNodeParent( m_sgNode )
339 && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
340 {
341 return nullptr;
342 }
343 else if( aParent != S3D::GetSGNodeParent( m_sgNode )
344 && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
345 {
346 return nullptr;
347 }
348 }
349
350 return m_sgNode;
351 }
352
353 IFSG_SHAPE shNode( aParent );
354
355 SGNODE* pShape = shNode.GetRawPtr();
356 SGNODE* pGeom = geometry->TranslateToSG( pShape );
357
358 if( nullptr == pGeom )
359 {
360 // this can happen if a VRML file contains
361 // empty point or index sets
362 shNode.Destroy();
363 return nullptr;
364 }
365
366 SGNODE* pApp = nullptr;
367
368 if( nullptr != appearance )
369 pApp = appearance->TranslateToSG( pShape );
370
371 if( nullptr != appearance && nullptr == pApp )
372 {
373 IFSG_FACESET tmp( false );
374 tmp.Attach( pGeom );
375 tmp.Destroy();
376 shNode.Destroy();
377 return nullptr;
378 }
379
380 m_sgNode = shNode.GetRawPtr();
381
382 return m_sgNode;
383}
384
385
387{
388 if( nullptr == aNode )
389 return;
390
391 if( aNode == appearance )
392 appearance = nullptr;
393 else if( aNode == geometry )
394 geometry = nullptr;
395
397}
398
399
401{
402 if( nullptr == aNode )
403 return;
404
405 if( aNode == appearance )
406 appearance = nullptr;
407 else if( aNode == geometry )
408 geometry = nullptr;
409
411}
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:41
bool Attach(SGNODE *aNode) override
Function Attach associates a given SGNODE* with this wrapper.
SGNODE * GetRawPtr(void) noexcept
Function GetRawPtr() returns the raw internal SGNODE pointer.
Definition: ifsg_node.cpp:65
void Destroy(void)
Function Destroy deletes the object held by this wrapper.
Definition: ifsg_node.cpp:55
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:41
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
The top node of a VRML2 model.
Definition: vrml2_base.h:60
bool ReadNode(WRLPROC &proc, WRL2NODE *aParent, WRL2NODE **aNode)
Definition: vrml2_base.cpp:277
SGNODE * m_sgNode
Definition: vrml2_node.h:178
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:173
virtual void unlinkChildNode(const WRL2NODE *aNode)
Remove references to an owned child.
Definition: vrml2_node.cpp:407
WRL2NODE * m_Parent
Definition: vrml2_node.h:169
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:174
virtual SGNODE * TranslateToSG(SGNODE *aParent)=0
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
WRL2NODES m_Type
Definition: vrml2_node.h:170
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:383
virtual void unlinkRefNode(const WRL2NODE *aNode)
Remove pointers to a referenced node.
Definition: vrml2_node.cpp:425
const char * GetNodeTypeName(WRL2NODES aNodeType) const
Definition: vrml2_node.cpp:273
WRL2NODES GetNodeType(void) const
Definition: vrml2_node.cpp:204
std::list< WRL2NODE * > m_Refs
Definition: vrml2_node.h:175
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:356
bool AddRefNode(WRL2NODE *aNode) override
Definition: vrml2_shape.cpp:80
bool checkNodeType(WRL2NODES aType)
virtual ~WRL2SHAPE()
Definition: vrml2_shape.cpp:56
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
bool AddChildNode(WRL2NODE *aNode) override
bool isDangling(void) override
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
Definition: vrml2_shape.cpp:65
void unlinkRefNode(const WRL2NODE *aNode) override
Remove pointers to a referenced node.
WRL2NODE * geometry
Definition: vrml2_shape.h:62
WRL2NODE * appearance
Definition: vrml2_shape.h:61
void unlinkChildNode(const WRL2NODE *aNode) override
Remove references to an owned child.
void Pop(void)
Definition: wrlproc.cpp:2035
char Peek(void)
Definition: wrlproc.cpp:2007
std::string GetFileName(void)
Definition: wrlproc.cpp:1995
std::string GetError(void)
Definition: wrlproc.cpp:1960
bool eof(void)
Definition: wrlproc.cpp:1954
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:289
std::string GetFilePosition() const
Definition: wrlproc.cpp:1982
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
collects header files for all SG* wrappers and the API
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:485
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:494
SGTYPES
Definition: sg_types.h:35
@ SGTYPE_TRANSFORM
Definition: sg_types.h:36
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:512
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:503
WRL2NODES
Definition: wrltypes.h:125