KiCad PCB EDA Suite
ifsg_api.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-2017 Cirilo Bernardo <cirilo.bernardo@gmail.com>
5  * Copyright (C) 2020 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 <fstream>
28 #include <wx/filename.h>
29 #include <wx/log.h>
30 #include "plugins/3dapi/ifsg_api.h"
32 #include "streamwrapper.h"
33 #include "3d_cache/sg/sg_node.h"
34 #include "3d_cache/sg/scenegraph.h"
36 #include "3d_cache/sg/sg_shape.h"
37 #include "3d_cache/sg/sg_helpers.h"
38 
39 
40 // version format of the cache file
41 #define SG_VERSION_TAG "VERSION:2"
42 
43 
44 static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
45 {
46  float v0, v1, v2;
47 
48  app->ambient.GetColor( v0, v1, v2 );
49  mat.m_Ambient.x = v0;
50  mat.m_Ambient.y = v1;
51  mat.m_Ambient.z = v2;
52 
53  app->diffuse.GetColor( v0, v1, v2 );
54  mat.m_Diffuse.x = v0;
55  mat.m_Diffuse.y = v1;
56  mat.m_Diffuse.z = v2;
57  mat.m_Ambient.x *= v0;
58  mat.m_Ambient.y *= v1;
59  mat.m_Ambient.z *= v2;
60 
61  app->emissive.GetColor( v0, v1, v2 );
62  mat.m_Emissive.x = v0;
63  mat.m_Emissive.y = v1;
64  mat.m_Emissive.z = v2;
65 
66  app->specular.GetColor( v0, v1, v2 );
67  mat.m_Specular.x = v0;
68  mat.m_Specular.y = v1;
69  mat.m_Specular.z = v2;
70 
71  mat.m_Shininess = app->shininess;
72  mat.m_Transparency = app->transparency;
73 }
74 
75 
76 bool S3D::WriteVRML( const char* filename, bool overwrite, SGNODE* aTopNode,
77  bool reuse, bool renameNodes )
78 {
79  if( nullptr == filename || filename[0] == 0 )
80  return false;
81 
82  wxString ofile = wxString::FromUTF8Unchecked( filename );
83 
84  if( wxFileName::Exists( ofile ) )
85  {
86  if( !overwrite )
87  return false;
88 
89  // make sure we make no attempt to write a directory
90  if( !wxFileName::FileExists( ofile ) )
91  return false;
92  }
93 
94  wxCHECK( aTopNode && aTopNode->GetNodeType() == S3D::SGTYPE_TRANSFORM, false );
95 
96  OPEN_OSTREAM( op, filename );
97 
98  if( op.fail() )
99  {
100  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] failed to open file '%s'",
101  __FILE__, __FUNCTION__, __LINE__, filename );
102 
103  return false;
104  }
105 
106  op.imbue( std::locale( "C" ) );
107  op << "#VRML V2.0 utf8\n";
108 
109  if( renameNodes )
110  {
111  aTopNode->ResetNodeIndex();
112  aTopNode->ReNameNodes();
113  }
114 
115  aTopNode->WriteVRML( op, reuse );
116 
117  if( !op.fail() )
118  {
119  CLOSE_STREAM( op );
120  return true;
121  }
122 
123  CLOSE_STREAM( op );
124 
125  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] problems encountered writing file '%s'",
126  __FILE__, __FUNCTION__, __LINE__, filename );
127 
128  return false;
129 }
130 
131 
133 {
134  wxCHECK( aNode, /* void */ );
135 
136  aNode->ResetNodeIndex();
137 }
138 
139 
140 void S3D::RenameNodes( SGNODE* aNode )
141 {
142  wxCHECK( aNode, /* void */ );
143 
144  aNode->ReNameNodes();
145 }
146 
147 
148 void S3D::DestroyNode( SGNODE* aNode ) noexcept
149 {
150  wxCHECK( aNode, /* void */ );
151 
152  delete aNode;
153 }
154 
155 
156 bool S3D::WriteCache( const char* aFileName, bool overwrite, SGNODE* aNode,
157  const char* aPluginInfo )
158 {
159  if( nullptr == aFileName || aFileName[0] == 0 )
160  return false;
161 
162  wxString ofile = wxString::FromUTF8Unchecked( aFileName );
163 
164  wxCHECK( aNode, false );
165 
166  if( wxFileName::Exists( ofile ) )
167  {
168  if( !overwrite )
169  {
170  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] file exists not overwriting '%s'",
171  __FILE__, __FUNCTION__, __LINE__, aFileName );
172 
173  return false;
174  }
175 
176  // make sure we make no attempt to write a directory
177  if( !wxFileName::FileExists( aFileName ) )
178  {
179  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] specified path is a directory '%s'",
180  __FILE__, __FUNCTION__, __LINE__, aFileName );
181 
182  return false;
183  }
184  }
185 
186  OPEN_OSTREAM( output, aFileName );
187 
188  if( output.fail() )
189  {
190  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] failed to open file '%s'",
191  __FILE__, __FUNCTION__, __LINE__, aFileName );
192 
193  return false;
194  }
195 
196  output << "(" << SG_VERSION_TAG << ")";
197 
198  if( nullptr != aPluginInfo && aPluginInfo[0] != 0 )
199  output << "(" << aPluginInfo << ")";
200  else
201  output << "(INTERNAL:0.0.0.0)";
202 
203  bool rval = aNode->WriteCache( output, nullptr );
204  CLOSE_STREAM( output );
205 
206  if( !rval )
207  {
208  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] problems encountered writing cache file '%s'",
209  __FILE__, __FUNCTION__, __LINE__, aFileName );
210 
211  // delete the defective file
212  wxRemoveFile( ofile );
213  }
214 
215  return rval;
216 }
217 
218 
219 SGNODE* S3D::ReadCache( const char* aFileName, void* aPluginMgr,
220  bool (*aTagCheck)( const char*, void* ) )
221 {
222  if( nullptr == aFileName || aFileName[0] == 0 )
223  return nullptr;
224 
225  wxString ofile = wxString::FromUTF8Unchecked( aFileName );
226 
227  if( !wxFileName::FileExists( aFileName ) )
228  {
229  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] no such file '%s'",
230  __FILE__, __FUNCTION__, __LINE__, aFileName );
231 
232  return nullptr;
233  }
234 
235  SGNODE* np = new SCENEGRAPH( nullptr );
236 
237  if( nullptr == np )
238  {
239  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] failed to instantiate SCENEGRAPH",
240  __FILE__, __FUNCTION__, __LINE__ );
241 
242  return nullptr;
243  }
244 
245  OPEN_ISTREAM( file, aFileName );
246 
247  if( file.fail() )
248  {
249  delete np;
250 
251  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] failed to open file '%s'",
252  __FILE__, __FUNCTION__, __LINE__, aFileName );
253 
254  return nullptr;
255  }
256 
257  // from SG_VERSION_TAG 1, read the version tag; if it's not the expected tag
258  // then we fail to read the cache file
259  do
260  {
261  std::string name;
262  char schar;
263  file.get( schar );
264 
265  if( '(' != schar )
266  {
267  wxLogTrace( MASK_3D_SG,
268  "%s:%s:%d * [INFO] corrupt data; missing left parenthesis at position '%d'",
269  __FILE__, __FUNCTION__, __LINE__, static_cast<int>( file.tellg() ) );
270 
271  CLOSE_STREAM( file );
272  return nullptr;
273  }
274 
275  file.get( schar );
276 
277  while( ')' != schar && file.good() )
278  {
279  name.push_back( schar );
280  file.get( schar );
281  }
282 
283  if( name.compare( SG_VERSION_TAG ) )
284  {
285  CLOSE_STREAM( file );
286  return nullptr;
287  }
288 
289  } while( 0 );
290 
291  // from SG_VERSION_TAG 2, read the PluginInfo string and check that it matches
292  // version tag; if it's not the expected tag then we fail to read the file
293  do
294  {
295  std::string name;
296  char schar;
297  file.get( schar );
298 
299  if( '(' != schar )
300  {
301  wxLogTrace( MASK_3D_SG,
302  "%s:%s:%d * [INFO] corrupt data; missing left parenthesis at position '%d'",
303  __FILE__, __FUNCTION__, __LINE__, static_cast<int>( file.tellg() ) );
304 
305  CLOSE_STREAM( file );
306  return nullptr;
307  }
308 
309  file.get( schar );
310 
311  while( ')' != schar && file.good() )
312  {
313  name.push_back( schar );
314  file.get( schar );
315  }
316 
317  // check the plugin tag
318  if( nullptr != aTagCheck && nullptr != aPluginMgr
319  && !aTagCheck( name.c_str(), aPluginMgr ) )
320  {
321  CLOSE_STREAM( file );
322  return nullptr;
323  }
324 
325  } while( 0 );
326 
327  bool rval = np->ReadCache( file, nullptr );
328  CLOSE_STREAM( file );
329 
330  if( !rval )
331  {
332  delete np;
333 
334  wxLogTrace( MASK_3D_SG, "%s:%s:%d * [INFO] problems encountered reading cache file '%s'",
335  __FILE__, __FUNCTION__, __LINE__, aFileName );
336 
337  return nullptr;
338  }
339 
340  return np;
341 }
342 
343 
345 {
346  if( nullptr == aNode )
347  return nullptr;
348 
349  if( aNode->GetNodeType() != S3D::SGTYPE_TRANSFORM )
350  return nullptr;
351 
352  S3D::MATLIST materials;
353  std::vector< SMESH > meshes;
354 
355  // the materials list shall have a default color; although the VRML
356  // default is an opaque black, the default used here shall be a median
357  // gray in hopes that it may help highlight faulty models; this color is
358  // also typical of MCAD applications. When a model has no associated
359  // material color it shall be assigned the index 0.
360  SGAPPEARANCE app( nullptr );
361  app.ambient = SGCOLOR( 0.6f, 0.6f, 0.6f );
362  app.diffuse = SGCOLOR( 0.6f, 0.6f, 0.6f );
363  app.specular = app.diffuse;
364  app.shininess = 0.05f;
365  app.transparency = 0.0f;
366 
367  materials.matorder.push_back( &app );
368  materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
369 
370  if( aNode->Prepare( nullptr, materials, meshes ) )
371  {
372  if( meshes.empty() )
373  return nullptr;
374 
375  S3DMODEL* model = S3D::New3DModel();
376 
377  // add all the materials
378  size_t j = materials.matorder.size();
379  SMATERIAL* lmat = new SMATERIAL[j];
380 
381  for( size_t i = 0; i < j; ++i )
382  formatMaterial( lmat[i], materials.matorder[i] );
383 
384  model->m_Materials = lmat;
385  model->m_MaterialsSize = j;
386 
387  // add all the meshes
388  j = meshes.size();
389  SMESH* lmesh = new SMESH[j];
390 
391  for( size_t i = 0; i < j; ++i )
392  lmesh[i] = meshes[i];
393 
394  model->m_Meshes = lmesh;
395  model->m_MeshesSize = j;
396 
397  return model;
398  }
399 
400  size_t j = meshes.size();
401 
402  for( size_t i = 0; i < j; ++i )
403  S3D::Free3DMesh( meshes[i] );
404 
405  return nullptr;
406 }
407 
408 
410 {
411  if( nullptr == aModel || nullptr == *aModel )
412  return;
413 
414  S3DMODEL* m = *aModel;
415  S3D::FREE_S3DMODEL( *m );
416  delete m;
417  *aModel = nullptr;
418 }
419 
420 
421 void Free3DModel( S3DMODEL& aModel )
422 {
423  S3D::FREE_S3DMODEL( aModel );
424 }
425 
426 
427 void S3D::Free3DMesh( SMESH& aMesh )
428 {
429  S3D::FREE_SMESH( aMesh );
430 }
431 
432 
434 {
435  S3DMODEL* mp = new S3DMODEL;
436  S3D::INIT_S3DMODEL( *mp );
437  return mp;
438 }
439 
440 
442 {
443  S3D::INIT_SMATERIAL( aMat );
444 }
445 
446 
447 void S3D::Init3DMesh( SMESH& aMesh )
448 {
449  S3D::INIT_SMESH( aMesh );
450 }
451 
452 
453 void S3D::GetLibVersion( unsigned char* Major, unsigned char* Minor, unsigned char* Patch,
454  unsigned char* Revision ) noexcept
455 {
456  if( Major )
457  *Major = KICADSG_VERSION_MAJOR;
458 
459  if( Minor )
460  *Minor = KICADSG_VERSION_MINOR;
461 
462  if( Revision )
463  *Revision = KICADSG_VERSION_REVISION;
464 
465  if( Patch )
466  *Patch = KICADSG_VERSION_PATCH;
467 }
468 
469 
470 SGVECTOR S3D::CalcTriNorm( const SGPOINT& p1, const SGPOINT& p2, const SGPOINT& p3 )
471 {
472  glm::dvec3 tri = glm::dvec3( 0.0, 0.0, 0.0 );
473  glm::dvec3 pts[3];
474 
475  pts[0] = glm::dvec3( p1.x, p1.y, p1.z );
476  pts[1] = glm::dvec3( p2.x, p2.y, p2.z );
477  pts[2] = glm::dvec3( p3.x, p3.y, p3.z );
478 
479  // degenerate points are given a default 0, 0, 1 normal
480  if( S3D::degenerate( pts ) )
481  return SGVECTOR( 0.0, 0.0, 1.0 );
482 
483  // normal
484  tri = glm::cross( pts[1] - pts[0], pts[2] - pts[0] );
485  glm::normalize( tri );
486 
487  return SGVECTOR( tri.x, tri.y, tri.z );
488 }
489 
490 
492 {
493  if( nullptr == aNode )
494  return SGTYPE_END;
495 
496  return aNode->GetNodeType();
497 }
498 
499 
501 {
502  if( nullptr == aNode )
503  return nullptr;
504 
505  return aNode->GetParent();
506 }
507 
508 
509 bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
510 {
511  if( nullptr == aParent || nullptr == aChild )
512  return false;
513 
514  return aParent->AddRefNode( aChild );
515 }
516 
517 
518 bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
519 {
520  if( nullptr == aParent || nullptr == aChild )
521  return false;
522 
523  return aParent->AddChildNode( aChild );
524 }
525 
526 
527 void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
528 {
529  if( nullptr == aObject || nullptr == aRefPtr || aObject != *aRefPtr )
530  return;
531 
532  aObject->AssociateWrapper( aRefPtr );
533 }
#define KICADSG_VERSION_MAJOR
Definition: sg_version.h:33
virtual void ReNameNodes(void)=0
Rename a node and all its child nodes in preparation for write operations.
SGCOLOR diffuse
Definition: sg_appearance.h:77
#define KICADSG_VERSION_REVISION
Definition: sg_version.h:36
SGLIB_API void RenameNodes(SGNODE *aNode)
Function RenameNodes renames a node and all children nodes based on the current values of the global ...
Definition: ifsg_api.cpp:140
SFVEC3F m_Ambient
Definition: c3dmodel.h:39
VECTOR2I v2(1, 0)
Test suite for KiCad math code.
SGLIB_API S3DMODEL * New3DModel(void)
Function New3DModel creates and initializes an S3DMODEL struct.
Definition: ifsg_api.cpp:433
double x
Definition: sg_base.h:70
bool degenerate(glm::dvec3 *pts) noexcept
Definition: sg_helpers.cpp:309
#define KICADSG_VERSION_PATCH
Definition: sg_version.h:35
SGLIB_API void Init3DMaterial(SMATERIAL &aMat)
Function Init3DMaterial initializes an SMATERIAL struct.
Definition: ifsg_api.cpp:441
virtual bool AddRefNode(SGNODE *aNode)=0
void ResetNodeIndex(void) noexcept
Reset the global SG* node indices in preparation for write operations.
Definition: sg_node.cpp:236
SGLIB_API SGNODE * ReadCache(const char *aFileName, void *aPluginMgr, bool(*aTagCheck)(const char *, void *))
Function ReadCache reads a binary cache file and creates an SGNODE tree.
Definition: ifsg_api.cpp:219
SGLIB_API void ResetNodeIndex(SGNODE *aNode)
Function ResetNodeIndex resets the global SG* class indices.
Definition: ifsg_api.cpp:132
SGLIB_API void AssociateSGNodeWrapper(SGNODE *aObject, SGNODE **aRefPtr)
Definition: ifsg_api.cpp:527
void FREE_S3DMODEL(S3DMODEL &aModel)
Definition: sg_node.cpp:324
SGLIB_API void Destroy3DModel(S3DMODEL **aModel)
Function Destroy3DModel frees memory used by an S3DMODEL structure and sets the pointer to the struct...
Definition: ifsg_api.cpp:409
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:500
void AssociateWrapper(SGNODE **aWrapperRef) noexcept
Associate this object with a handle to itself.
Definition: sg_node.cpp:205
float m_Transparency
1.0 is completely transparent, 0.0 completely opaque
Definition: c3dmodel.h:44
#define KICADSG_VERSION_MINOR
Definition: sg_version.h:34
double y
Definition: sg_base.h:71
std::map< SGAPPEARANCE const *, int > matmap
Definition: sg_node.h:57
The base class of all Scene Graph nodes.
Definition: sg_node.h:74
SGCOLOR emissive
Definition: sg_appearance.h:78
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
void GetColor(float &aRedVal, float &aGreenVal, float &aBlueVal) const noexcept
Definition: sg_base.cpp:59
SGLIB_API bool AddSGNodeRef(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:509
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
SGLIB_API bool WriteVRML(const char *filename, bool overwrite, SGNODE *aTopNode, bool reuse, bool renameNodes)
Function WriteVRML writes out the given node and its subnodes to a VRML2 file.
Definition: ifsg_api.cpp:76
virtual bool ReadCache(std::istream &aFile, SGNODE *parentNode)=0
Reads binary format data from a cache file.
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Function DestroyNode deletes the given SG* class node.
Definition: ifsg_api.cpp:148
SGCOLOR ambient
Definition: sg_appearance.h:76
static void formatMaterial(SMATERIAL &mat, SGAPPEARANCE const *app)
Definition: ifsg_api.cpp:44
float transparency
Definition: sg_appearance.h:75
#define OPEN_OSTREAM(var, name)
SGLIB_API bool AddSGNodeChild(SGNODE *aParent, SGNODE *aChild)
Definition: ifsg_api.cpp:518
void INIT_SMESH(SMESH &aMesh) noexcept
Definition: sg_node.cpp:274
void INIT_S3DMODEL(S3DMODEL &aModel) noexcept
Definition: sg_node.cpp:280
defines the library version of the intermediate scenegraph (SG) implementation
float m_Shininess
Definition: c3dmodel.h:43
SGLIB_API void Init3DMesh(SMESH &aMesh)
Function Init3DMesh creates and initializes an SMESH struct.
Definition: ifsg_api.cpp:447
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
defines the API calls for the manipulation of SG* classes
#define SG_VERSION_TAG
Definition: ifsg_api.cpp:41
SGNODE * GetParent(void) const noexcept
Returns a pointer to the parent SGNODE of this object or NULL if the object has no parent (ie.
Definition: sg_node.cpp:110
SGTYPES
Definition: sg_types.h:34
virtual bool WriteCache(std::ostream &aFile, SGNODE *parentNode)=0
Write this node's data to a binary cache file.
SGLIB_API SGVECTOR CalcTriNorm(const SGPOINT &p1, const SGPOINT &p2, const SGPOINT &p3)
Function CalcTriNorm returns the normal vector of a triangle described by vertices p1,...
Definition: ifsg_api.cpp:470
SGLIB_API S3D::SGTYPES GetSGNodeType(SGNODE *aNode)
Definition: ifsg_api.cpp:491
void Free3DModel(S3DMODEL &aModel)
Function Free3DModel frees memory used internally by an S3DMODEL structure.
Definition: ifsg_api.cpp:421
const char * name
Definition: DXF_plotter.cpp:59
#define OPEN_ISTREAM(var, name)
SFVEC3F m_Emissive
Definition: c3dmodel.h:41
std::vector< SGAPPEARANCE const * > matorder
Definition: sg_node.h:56
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
double z
Definition: sg_base.h:72
SGCOLOR specular
Definition: sg_appearance.h:79
void INIT_SMATERIAL(SMATERIAL &aMaterial)
Definition: sg_node.cpp:268
virtual bool AddChildNode(SGNODE *aNode)=0
Define the basic data set required to represent a 3D model.
Definition: scenegraph.h:44
SGLIB_API bool WriteCache(const char *aFileName, bool overwrite, SGNODE *aNode, const char *aPluginInfo)
Function WriteCache writes the SGNODE tree to a binary cache file.
Definition: ifsg_api.cpp:156
SFVEC3F m_Diffuse
Default diffuse color if m_Color is NULL.
Definition: c3dmodel.h:40
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
Define a number of macros to aid in repetitious code which is probably best expressed as a preprocess...
#define CLOSE_STREAM(var)
void FREE_SMESH(SMESH &aMesh) noexcept
Definition: sg_node.cpp:286
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Function GetModel creates an S3DMODEL representation of aNode (raw data, no transforms)
Definition: ifsg_api.cpp:344
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
SGLIB_API void GetLibVersion(unsigned char *Major, unsigned char *Minor, unsigned char *Patch, unsigned char *Revision) noexcept
Function GetLibVersion retrieves version information of the kicad_3dsg library.
Definition: ifsg_api.cpp:453
Defines the generic material appearance of a scenegraph object.
Definition: sg_appearance.h:37
SFVEC3F m_Specular
Definition: c3dmodel.h:42
virtual bool WriteVRML(std::ostream &aFile, bool aReuseFlag)=0
Writes this node's data to a VRML file.
S3D::SGTYPES GetNodeType(void) const noexcept
Return the type of this node instance.
Definition: sg_node.cpp:104
bool Prepare(const glm::dmat4 *aTransform, S3D::MATLIST &materials, std::vector< SMESH > &meshes)
Definition: scenegraph.cpp:639
SGLIB_API void Free3DMesh(SMESH &aMesh)
Function Free3DMesh frees memory used internally by an SMESH structure.
Definition: ifsg_api.cpp:427