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