KiCad PCB EDA Suite
vrml2_appearance.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_appearance.h"
32 #include "plugins/3dapi/ifsg_all.h"
33 
34 
36 {
37  material = nullptr;
38  texture = nullptr;
39  textureTransform = nullptr;
41 }
42 
43 
45 {
46  material = nullptr;
47  texture = nullptr;
48  textureTransform = nullptr;
50  m_Parent = aParent;
51 
52  if( nullptr != m_Parent )
53  m_Parent->AddChildNode( this );
54 }
55 
56 
58 {
59  wxLogTrace( traceVrmlPlugin,
60  wxT( " * [INFO] Destroying Appearance node with %zu children, %zu"
61  "references, and %zu back pointers." ),
62  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
63 }
64 
65 
67 {
68  switch( aType )
69  {
75  break;
76 
77  default:
78  return false;
79  break;
80  }
81 
82  return true;
83 }
84 
85 
87 {
88  // this node is dangling unless it has a parent of type WRL2_SHAPE
89  if( nullptr == m_Parent || m_Parent->GetNodeType() != WRL2NODES::WRL2_SHAPE )
90  return true;
91 
92  return false;
93 }
94 
95 
97 {
98  wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
99 
100  WRL2NODES type = aNode->GetNodeType();
101 
102  if( !checkNodeType( type ) )
103  {
104  wxLogTrace( traceVrmlPlugin,
105  wxT( "%s:%s:%d\n"
106  " * [INFO] bad file format; unexpected child node '%s'." ),
107  __FILE__, __FUNCTION__, __LINE__, aNode->GetNodeTypeName( type ) );
108 
109  return false;
110  }
111 
112  if( WRL2NODES::WRL2_MATERIAL == type )
113  {
114  if( nullptr != material )
115  {
116  wxLogTrace( traceVrmlPlugin,
117  wxT( "%s:%s:%d\n"
118  " * [INFO] bad file format; multiple material nodes." ),
119  __FILE__, __FUNCTION__, __LINE__ );
120 
121  return false;
122  }
123 
124  material = aNode;
125  return WRL2NODE::AddRefNode( aNode );
126  }
127 
129  {
130  if( nullptr != textureTransform )
131  {
132  wxLogTrace( traceVrmlPlugin,
133  wxT( "%s:%s:%d\n"
134  " * [INFO] bad file format; multiple textureTransform nodes." ),
135  __FILE__, __FUNCTION__, __LINE__ );
136 
137  return false;
138  }
139 
140  textureTransform = aNode;
141  return WRL2NODE::AddRefNode( aNode );
142  }
143 
144  if( nullptr != texture )
145  {
146  wxLogTrace( traceVrmlPlugin,
147  wxT( "%s:%s:%d\n"
148  " * [INFO] bad file format; multiple texture nodes." ),
149  __FILE__, __FUNCTION__, __LINE__ );
150 
151  return false;
152  }
153 
154  texture = aNode;
155  return WRL2NODE::AddRefNode( aNode );
156 }
157 
158 
160 {
161  wxCHECK_MSG( aNode, false, wxT( "Invalid node." ) );
162 
163  WRL2NODES type = aNode->GetNodeType();
164 
165  if( !checkNodeType( type ) )
166  {
167  wxLogTrace( traceVrmlPlugin,
168  wxT( "%s:%s:%d\n"
169  " * [INFO] bad file format; unexpected child node '%s'." ),
170  __FILE__, __FUNCTION__, __LINE__, aNode->GetNodeTypeName( type ) );
171 
172  return false;
173  }
174 
175  if( WRL2NODES::WRL2_MATERIAL == type )
176  {
177  if( nullptr != material )
178  {
179  wxLogTrace( traceVrmlPlugin,
180  wxT( "%s:%s:%d\n"
181  " * [INFO] bad file format; multiple material nodes." ),
182  __FILE__, __FUNCTION__, __LINE__ );
183 
184  return false;
185  }
186 
187  material = aNode;
188  return WRL2NODE::AddChildNode( aNode );
189  }
190 
192  {
193  if( nullptr != textureTransform )
194  {
195  wxLogTrace( traceVrmlPlugin,
196  wxT( "%s:%s:%d\n"
197  " * [INFO] bad file format; multiple textureTransform nodes." ),
198  __FILE__, __FUNCTION__, __LINE__ );
199 
200  return false;
201  }
202 
203  textureTransform = aNode;
204  return WRL2NODE::AddChildNode( aNode );
205  }
206 
207  if( nullptr != texture )
208  {
209  wxLogTrace( traceVrmlPlugin,
210  wxT( "%s:%s:%d\n"
211  " * [INFO] bad file format; multiple texture nodes." ),
212  __FILE__, __FUNCTION__, __LINE__ );
213 
214  return false;
215  }
216 
217  texture = aNode;
218  return WRL2NODE::AddChildNode( aNode );
219 }
220 
221 
222 bool WRL2APPEARANCE::Read( WRLPROC& proc, WRL2BASE* aTopNode )
223 {
224  wxCHECK_MSG( aTopNode, false, wxT( "Invalid top node." ) );
225 
226  char tok = proc.Peek();
227 
228  if( proc.eof() )
229  {
230  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
231  " * [INFO] bad file format; unexpected eof %s." ),
232  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
233 
234  return false;
235  }
236 
237  if( '{' != tok )
238  {
239  wxLogTrace( traceVrmlPlugin,
240  wxT( "%s:%s:%d\n"
241  " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
242  __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
243 
244  return false;
245  }
246 
247  proc.Pop();
248  std::string glob;
249 
250  while( true )
251  {
252  if( proc.Peek() == '}' )
253  {
254  proc.Pop();
255  break;
256  }
257 
258  if( !proc.ReadName( glob ) )
259  {
260  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
261  "%s" ),
262  __FILE__, __FUNCTION__, __LINE__ , proc.GetError() );
263 
264  return false;
265  }
266 
267  // expecting one of:
268  // material
269  // texture
270  // textureTransform
271 
272  if( !glob.compare( "material" ) )
273  {
274  if( !aTopNode->ReadNode( proc, this, nullptr ) )
275  {
276  wxLogTrace( traceVrmlPlugin,
277  wxT( "%s:%s:%d\n"
278  " * [INFO] could not read material information." ),
279  __FILE__, __FUNCTION__, __LINE__ );
280 
281  return false;
282  }
283  }
284  else if( !glob.compare( "texture" ) )
285  {
286  if( !aTopNode->ReadNode( proc, this, nullptr ) )
287  {
288  wxLogTrace( traceVrmlPlugin,
289  wxT( "%s:%s:%d\n"
290  " * [INFO] could not read texture information." ),
291  __FILE__, __FUNCTION__, __LINE__ );
292 
293  return false;
294  }
295  }
296  else if( !glob.compare( "textureTransform" ) )
297  {
298  if( !aTopNode->ReadNode( proc, this, nullptr ) )
299  {
300  wxLogTrace( traceVrmlPlugin,
301  wxT( "%s:%s:%d\n"
302  " * [INFO] could not read textureTransform information." ),
303  __FILE__, __FUNCTION__, __LINE__ );
304 
305  return false;
306  }
307  }
308  else
309  {
310  wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n"
311  " * [INFO] bad Appearance %s.\n"
312  " * [INFO] file: '%s'" ),
313  __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
314  proc.GetFileName() );
315 
316  return false;
317  }
318  } // while( true ) -- reading contents of Appearance{}
319 
320  return true;
321 }
322 
323 
325 {
326  if( nullptr == material && nullptr == texture )
327  return nullptr;
328 
329  S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
330 
331  wxCHECK_MSG( aParent && ( ptype == S3D::SGTYPE_SHAPE ), nullptr,
332  wxString::Format( wxT( " * [BUG] Appearance does not have a Shape parent "
333  "(parent ID: %d)." ), ptype ) );
334 
335  wxLogTrace( traceVrmlPlugin,
336  wxT( " * [INFO] Translating Appearance node with %zu children, %zu"
337  "references, and %zu back pointers." ),
338  m_Children.size(), m_Refs.size(), m_BackPointers.size() );
339 
340  if( m_sgNode )
341  {
342  if( nullptr != aParent )
343  {
344  if( nullptr == S3D::GetSGNodeParent( m_sgNode )
345  && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
346  {
347  return nullptr;
348  }
349  else if( aParent != S3D::GetSGNodeParent( m_sgNode )
350  && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
351  {
352  return nullptr;
353  }
354  }
355 
356  return m_sgNode;
357  }
358 
359  if( nullptr != texture )
360  {
361  // use a default gray appearance
362  IFSG_APPEARANCE matNode( aParent );
363  matNode.SetEmissive( 0.0f, 0.0f, 0.0f );
364  matNode.SetSpecular( 0.65f, 0.65f, 0.65f );
365  matNode.SetDiffuse( 0.65f, 0.65f, 0.65f );
366 
367  // default ambient
368  matNode.SetShininess( 0.2f );
369  matNode.SetTransparency( 0.0f );
370  m_sgNode = matNode.GetRawPtr();
371 
372  return m_sgNode;
373  }
374 
375  m_sgNode = material->TranslateToSG( aParent );
376 
377  return m_sgNode;
378 }
379 
380 
382 {
383  if( nullptr == aNode )
384  return;
385 
386  if( aNode->GetParent() == this )
387  {
388  if( aNode == material )
389  material = nullptr;
390  else if( aNode == texture )
391  texture = nullptr;
392  else if( aNode == textureTransform )
393  textureTransform = nullptr;
394 
395  }
396 
397  WRL2NODE::unlinkChildNode( aNode );
398 }
399 
400 
402 {
403  if( nullptr == aNode )
404  return;
405 
406  if( aNode->GetParent() != this )
407  {
408  if( aNode == material )
409  material = nullptr;
410  else if( aNode == texture )
411  texture = nullptr;
412  else if( aNode == textureTransform )
413  textureTransform = nullptr;
414  }
415 
416  WRL2NODE::unlinkRefNode( aNode );
417 }
WRL2NODE * material
virtual SGNODE * TranslateToSG(SGNODE *aParent)=0
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
void Pop(void)
Definition: wrlproc.cpp:2035
bool checkNodeType(WRL2NODES aType)
Return true if the node type is a material description class.
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
std::list< WRL2NODE * > m_Children
Definition: vrml2_node.h:174
bool SetTransparency(float aTransparency) noexcept
bool SetDiffuse(float aRVal, float aGVal, float aBVal)
std::list< WRL2NODE * > m_Refs
Definition: vrml2_node.h:175
void unlinkRefNode(const WRL2NODE *aNode) override
Remove pointers to a referenced node.
void unlinkChildNode(const WRL2NODE *aNode) override
Remove references to an owned child.
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
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
bool ReadNode(WRLPROC &proc, WRL2NODE *aParent, WRL2NODE **aNode)
Definition: vrml2_base.cpp:276
bool AddRefNode(WRL2NODE *aNode) override
WRL2NODE * m_Parent
Definition: vrml2_node.h:169
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
std::list< WRL2NODE * > m_BackPointers
Definition: vrml2_node.h:173
WRL2NODES GetNodeType(void) const
Definition: vrml2_node.cpp:204
bool SetShininess(float aShininess) noexcept
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
WRL2NODE * texture
const wxChar *const traceVrmlPlugin
Flag to enable VRML plugin trace output.
Definition: vrml.cpp:63
virtual ~WRL2APPEARANCE()
bool SetEmissive(float aRVal, float aGVal, float aBVal)
const char * GetNodeTypeName(WRL2NODES aNodeType) const
Definition: vrml2_node.cpp:273
SGTYPES
Definition: sg_types.h:34
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
bool SetSpecular(float aRVal, float aGVal, float aBVal)
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:483
WRL2NODE * textureTransform
virtual bool AddChildNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:356
bool Read(WRLPROC &proc, WRL2BASE *aTopNode) override
bool ReadName(std::string &aName)
Definition: wrlproc.cpp:289
virtual void unlinkRefNode(const WRL2NODE *aNode)
Remove pointers to a referenced node.
Definition: vrml2_node.cpp:425
WRL2NODE * GetParent(void) const
Definition: vrml2_node.cpp:210
bool isDangling(void) override
Determine whether an object should be moved to a different parent during the VRML to SG* translation.
WRL2NODES
Definition: wrltypes.h:124
bool AddChildNode(WRL2NODE *aNode) override
std::string GetError(void)
Definition: wrlproc.cpp:1960
virtual void unlinkChildNode(const WRL2NODE *aNode)
Remove references to an owned child.
Definition: vrml2_node.cpp:407
virtual bool AddRefNode(WRL2NODE *aNode)
Definition: vrml2_node.cpp:383
bool eof(void)
Definition: wrlproc.cpp:1954