KiCad PCB EDA Suite
vrml2_transform.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) 2015-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#include <iostream>
26#include <sstream>
27#include <wx/log.h>
28
29#include "vrml2_base.h"
30#include "vrml2_transform.h"
32
33
35{
37}
38
39
41{
43 m_Parent = aParent;
44
45 if( nullptr != m_Parent )
46 m_Parent->AddChildNode( this );
47}
48
49
51{
52 wxLogTrace( traceVrmlPlugin,
53 wxT( " * [INFO] Destroying Transform node with %zu children, %zu"
54 "references, and %zu back pointers." ),
55 m_Children.size(), m_Refs.size(), m_BackPointers.size() );
56}
57
58
60{
61 // a Transform node is never dangling
62 return false;
63}
64
65
66bool WRL2TRANSFORM::Read( WRLPROC& proc, WRL2BASE* aTopNode )
67{
68 /*
69 * Structure of a Transform node (p.120):
70 *
71 * Transform {
72 * eventIn MFNode addChildren
73 * eventIn MFNode removeChildren
74 * exposedField SFVec3f center 0 0 0
75 * exposedField MFNode children []
76 * exposedField SFRotation rotation 0 0 1 0
77 * exposedField SFVec3f scale 1 1 1
78 * exposedField SFRotation scaleOrientation 0 0 1 0
79 * exposedField SFVec3f translation 0 0 0
80 * field SFVec3f bboxCenter 0 0 0
81 * field SFVec3f bboxSize 0 0 0
82 * }
83 */
84
85 wxCHECK_MSG( aTopNode, false, wxT( "Invalid top node." ) );
86
87 center.x = 0.0;
88 center.y = 0.0;
89 center.z = 0.0;
90
94
95 rotation.x = 0.0;
96 rotation.y = 0.0;
97 rotation.z = 1.0;
98 rotation.w = 0.0;
99
101
102 scale.x = 1.0;
103 scale.y = 1.0;
104 scale.z = 1.0;
105
106 size_t line, column;
107 proc.GetFilePosData( line, column );
108
109 char tok = proc.Peek();
110
111 if( proc.eof() )
112 {
113 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
114 " * [INFO] bad file format; unexpected eof %s." ),
115 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
116
117 return false;
118 }
119
120 if( '{' != tok )
121 {
122 wxLogTrace( traceVrmlPlugin,
123 wxT( "%s:%s:%d\n"
124 " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
125 __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
126
127 return false;
128 }
129
130 proc.Pop();
131 std::string glob;
132
133 while( true )
134 {
135 if( proc.Peek() == '}' )
136 {
137 proc.Pop();
138 break;
139 }
140
141 if( !proc.ReadName( glob ) )
142 {
143 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
144 "%s" ),
145 __FILE__, __FUNCTION__, __LINE__ , proc.GetError() );
146
147 return false;
148 }
149
150 // expecting one of:
151 // center
152 // children
153 // rotation
154 // scale
155 // ScaleOrientation
156 // translation
157 if( !glob.compare( "center" ) )
158 {
159 if( !proc.ReadSFVec3f( center ) )
160 {
161 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
162 " * [INFO] invalid center %s\n"
163 " * [INFO] file: '%s'\n"
164 "%s" ),
165 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
166 proc.GetFileName(), proc.GetError() );
167
168 return false;
169 }
170
171 // convert from 1 VRML Unit = 0.1 inch to 1 VRML Unit = 1 mm
172 center.x *= 2.54f;
173 center.y *= 2.54f;
174 center.z *= 2.54f;
175 }
176 else if( !glob.compare( "rotation" ) )
177 {
178 if( !proc.ReadSFRotation( rotation ) )
179 {
180 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
181 " * [INFO] invalid rotation %s\n"
182 " * [INFO] file: '%s'\n"
183 "%s" ),
184 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
185 proc.GetFileName(), proc.GetError() );
186
187 return false;
188 }
189 }
190 else if( !glob.compare( "scale" ) )
191 {
192 if( !proc.ReadSFVec3f( scale ) )
193 {
194 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
195 " * [INFO] invalid scale %s\n"
196 " * [INFO] file: '%s'\n"
197 "%s" ),
198 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
199 proc.GetFileName(), proc.GetError() );
200
201 return false;
202 }
203 }
204 else if( !glob.compare( "scaleOrientation" ) )
205 {
206 if( !proc.ReadSFRotation( scaleOrientation ) )
207 {
208 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
209 " * [INFO] invalid scaleOrientation %s\n"
210 " * [INFO] file: '%s'\n"
211 "%s" ),
212 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
213 proc.GetFileName(), proc.GetError() );
214
215 return false;
216 }
217 }
218 else if( !glob.compare( "translation" ) )
219 {
220 if( !proc.ReadSFVec3f( translation ) )
221 {
222 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
223 " * [INFO] invalid translation %s\n"
224 " * [INFO] file: '%s'\n"
225 "%s" ),
226 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
227 proc.GetFileName(), proc.GetError() );
228
229 return false;
230 }
231
232 // convert from 1 VRML Unit = 0.1 inch to 1 VRML Unit = 1 mm
233 translation.x *= 2.54f;
234 translation.y *= 2.54f;
235 translation.z *= 2.54f;
236 }
237 else if( !glob.compare( "children" ) )
238 {
239 if( !readChildren( proc, aTopNode ) )
240 return false;
241 }
242 else
243 {
244 wxLogTrace( traceVrmlPlugin,
245 wxT( "%s:%s:%d\n"
246 " * [INFO] invalid Transform %s.\n"
247 " * [INFO] file: '%s'\n" ),
248 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
249 proc.GetFileName() );
250
251 return false;
252 }
253 } // while( true ) -- reading contents of Transform{}
254
255 return true;
256}
257
258
260{
261 wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
262
263 // take possession if the node is dangling WRL2_SHAPE
264
265 if( WRL2NODES::WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
266 {
267 WRL2NODE* np = aNode->GetParent();
268
269 if( nullptr != np )
270 aNode->SetParent( this );
271
272
273 if( !WRL2NODE::AddChildNode( aNode ) )
274 {
275 aNode->SetParent( nullptr );
276 return false;
277 }
278 }
279
280 if( !WRL2NODE::AddRefNode( aNode ) )
281 return false;
282
283 return true;
284}
285
286
288{
289 char tok = proc.Peek();
290
291 if( proc.eof() )
292 {
293 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
294 " * [INFO] bad file format; unexpected eof %s." ),
295 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
296
297 return false;
298 }
299
300 if( '[' != tok )
301 {
302 // since there are no delimiters we expect a single child
303 if( !aTopNode->ReadNode( proc, this, nullptr ) )
304 return false;
305
306 if( proc.Peek() == ',' )
307 proc.Pop();
308
309 return true;
310 }
311
312 proc.Pop();
313
314 while( true )
315 {
316 if( proc.Peek() == ']' )
317 {
318 proc.Pop();
319 break;
320 }
321
322 if( !aTopNode->ReadNode( proc, this, nullptr ) )
323 return false;
324
325 if( proc.Peek() == ',' )
326 proc.Pop();
327 }
328
329 return true;
330}
331
332
334{
335 wxLogTrace( traceVrmlPlugin,
336 wxT( " * [INFO] Translating Switch with %zu children, %zu references, and"
337 "%zu back pointers." ),
338 m_Children.size(), m_Refs.size(), m_BackPointers.size() );
339
340 if( m_Children.empty() && m_Refs.empty() )
341 return nullptr;
342
343 S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
344
345 wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_TRANSFORM ), nullptr,
346 wxString::Format( wxT( "Transform does not have a Transform parent (parent "
347 "ID: %d)." ), ptype ) );
348
349 if( m_sgNode )
350 {
351 if( nullptr != aParent )
352 {
353 if( nullptr == S3D::GetSGNodeParent( m_sgNode )
354 && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
355 {
356 return nullptr;
357 }
358 else if( aParent != S3D::GetSGNodeParent( m_sgNode )
359 && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
360 {
361 return nullptr;
362 }
363 }
364
365 return m_sgNode;
366 }
367
368 IFSG_TRANSFORM txNode( aParent );
369
370 std::list< WRL2NODE* >::iterator sC = m_Children.begin();
371 std::list< WRL2NODE* >::iterator eC = m_Children.end();
372 WRL2NODES type;
373
374 // Include only the following in a Transform node:
375 // Shape
376 // Switch
377 // Transform
378 // Inline
379 bool test = false; // set to true if there are any subnodes for display
380
381 for( int i = 0; i < 2; ++i )
382 {
383 while( sC != eC )
384 {
385 type = (*sC)->GetNodeType();
386
387 switch( type )
388 {
393
394 if( nullptr != (*sC)->TranslateToSG( txNode.GetRawPtr() ) )
395 test = true;
396
397 break;
398
399 default:
400 break;
401 }
402
403 ++ sC;
404 }
405
406 sC = m_Refs.begin();
407 eC = m_Refs.end();
408 }
409
410 if( false == test )
411 {
412 txNode.Destroy();
413 return nullptr;
414 }
415
416 txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) );
417 txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
421 txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
422
423 m_sgNode = txNode.GetRawPtr();
424
425 return m_sgNode;
426}
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_TRANSFORM is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH.
bool SetTranslation(const SGPOINT &aTranslation) noexcept
bool SetScaleOrientation(const SGVECTOR &aScaleAxis, double aAngle)
bool SetCenter(const SGPOINT &aCenter) noexcept
bool SetRotation(const SGVECTOR &aRotationAxis, double aAngle)
bool SetScale(const SGPOINT &aScale) noexcept
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
virtual bool isDangling(void)=0
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
SGNODE * m_sgNode
Definition: vrml2_node.h:178
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:173
WRL2NODE * GetParent(void) const
Definition: vrml2_node.cpp:210
virtual bool SetParent(WRL2NODE *aParent, bool doUnlink=true)
Set the parent WRL2NODE of this object.
Definition: vrml2_node.cpp:339
WRL2NODE * m_Parent
Definition: vrml2_node.h:169
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:174
WRL2NODES m_Type
Definition: vrml2_node.h:170
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:383
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
WRLROTATION scaleOrientation
WRLVEC3F translation
virtual ~WRL2TRANSFORM()
bool readChildren(WRLPROC &proc, WRL2BASE *aTopNode)
WRLVEC3F bboxCenter
WRLROTATION rotation
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
bool AddRefNode(WRL2NODE *aNode) override
bool isDangling(void) override
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
WRLVEC3F bboxSize
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
void Pop(void)
Definition: wrlproc.cpp:2035
char Peek(void)
Definition: wrlproc.cpp:2007
std::string GetFileName(void)
Definition: wrlproc.cpp:1995
bool GetFilePosData(size_t &line, size_t &column)
Definition: wrlproc.cpp:1966
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
bool ReadSFRotation(WRLROTATION &aSFRotation)
Definition: wrlproc.cpp:937
bool ReadSFVec3f(WRLVEC3F &aSFVec3f)
Definition: wrlproc.cpp:1082
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
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
WRL2NODES
Definition: wrltypes.h:125