KiCad PCB EDA Suite
sg_node.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 Cirilo Bernardo <cirilo.bernardo@gmail.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <algorithm>
25 #include <cmath>
26 #include <cstring>
27 #include <iostream>
28 #include <sstream>
29 #include <wx/log.h>
30 
31 #include "3d_cache/sg/sg_node.h"
32 #include "plugins/3dapi/c3dmodel.h"
33 
34 static const std::string node_names[S3D::SGTYPE_END + 1] = {
35  "TXFM",
36  "APP",
37  "COL",
38  "COLIDX",
39  "FACE",
40  "COORD",
41  "COORDIDX",
42  "NORM",
43  "SHAPE",
44  "INVALID"
45 };
46 
47 
48 static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
49 
50 
51 char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
52 {
53  return node_names[aType].c_str();
54 }
55 
56 
57 static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
58 {
59  if( nodeType < 0 || nodeType >= S3D::SGTYPE_END )
60  {
61  aName = node_names[S3D::SGTYPE_END];
62  return;
63  }
64 
65  unsigned int seqNum = node_counts[nodeType];
66  ++node_counts[nodeType];
67 
68  std::ostringstream ostr;
69  ostr << node_names[nodeType] << "_" << seqNum;
70  aName = ostr.str();
71 
72  return;
73 }
74 
75 
77 {
78  m_Parent = aParent;
79  m_Association = NULL;
80  m_written = false;
82 
83  return;
84 }
85 
86 
88 {
89  if( m_Parent )
90  m_Parent->unlinkChildNode( this );
91 
92  if( m_Association )
93  *m_Association = NULL;
94 
95  std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
96  std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
97 
98  while( sBP != eBP )
99  {
100  (*sBP)->unlinkRefNode( this );
101  ++sBP;
102  }
103 
104  return;
105 }
106 
107 
109 {
110  return m_SGtype;
111 }
112 
113 
114 SGNODE* SGNODE::GetParent( void ) const
115 {
116  return m_Parent;
117 }
118 
119 
120 bool SGNODE::SwapParent( SGNODE* aNewParent )
121 {
122  if( aNewParent == m_Parent )
123  return true;
124 
125  if( NULL == aNewParent )
126  return false;
127 
128  if( NULL == m_Parent )
129  {
130  if( aNewParent->AddChildNode( this ) )
131  return true;
132 
133  return false;
134  }
135 
136  if( aNewParent->GetNodeType() != m_Parent->GetNodeType() )
137  return false;
138 
139  SGNODE* oldParent = m_Parent;
140  m_Parent->unlinkChildNode( this );
141  m_Parent = NULL;
142  aNewParent->unlinkRefNode( this );
143  aNewParent->AddChildNode( this );
144  oldParent->AddRefNode( this );
145 
146  return true;
147 }
148 
149 
150 const char* SGNODE::GetName( void )
151 {
152  if( m_Name.empty() )
154 
155  return m_Name.c_str();
156 }
157 
158 
159 void SGNODE::SetName( const char *aName )
160 {
161  if( NULL == aName || 0 == aName[0] )
163  else
164  m_Name = aName;
165 
166  return;
167 }
168 
169 
170 const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
171 {
172  return node_names[aNodeType].c_str();
173 }
174 
175 
177 {
178  if( NULL == aNode )
179  return;
180 
181  std::list< SGNODE* >::iterator np =
182  std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
183 
184  if( np != m_BackPointers.end() )
185  return;
186 
187  m_BackPointers.push_back( aNode );
188  return;
189 }
190 
191 
192 void SGNODE::delNodeRef( const SGNODE* aNode )
193 {
194  if( NULL == aNode )
195  return;
196 
197  std::list< SGNODE* >::iterator np =
198  std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
199 
200  if( np != m_BackPointers.end() )
201  {
202  m_BackPointers.erase( np );
203  return;
204  }
205 
206  #ifdef DEBUG
207  std::ostringstream ostr;
208  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
209  ostr << " * [BUG] delNodeRef() did not find its target\n";
210  ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
211  ostr << aNode->GetNodeType() << "\n";
212  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
213  #endif
214 
215  return;
216 }
217 
218 
219 void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
220 {
221  if( NULL == aWrapperRef )
222  {
223  #ifdef DEBUG
224  std::ostringstream ostr;
225  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
226  ostr << " * [BUG] NULL handle";
227  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
228  #endif
229 
230  return;
231  }
232 
233  if( *aWrapperRef != this )
234  {
235  #ifdef DEBUG
236  std::ostringstream ostr;
237  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
238  ostr << " * [BUG] handle value does not match this object's pointer";
239  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
240  #endif
241 
242  return;
243  }
244 
245  // if there is an existing association then break it and emit a warning
246  // just in case the behavior is undesired
247  if( m_Association )
248  {
249  *m_Association = NULL;
250 
251  #ifdef DEBUG
252  std::ostringstream ostr;
253  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
254  ostr << " * [WARNING] association being broken with previous wrapper";
255  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
256  #endif
257  }
258 
259  m_Association = aWrapperRef;
260 
261  return;
262 }
263 
264 void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
265 {
266  if( !m_Association )
267  return;
268 
269  if( !aWrapperRef )
270  {
271  #ifdef DEBUG
272  std::ostringstream ostr;
273  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
274  ostr << " * [BUG] invalid handle value aWrapperRef";
275  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
276  #endif
277 
278  return;
279  }
280 
281  if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
282  {
283  #ifdef DEBUG
284  std::ostringstream ostr;
285  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
286  ostr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
287  ostr << ") does not match *m_Association (" << *m_Association << ") in type ";
288  ostr << node_names[ m_SGtype] << "\n";
289  ostr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
290  ostr << m_Association << ")\n";
291  ostr << " * [INFO] node name: " << GetName();
292  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
293  #endif
294 
295  return;
296  }
297 
298  m_Association = NULL;
299 
300  return;
301 }
302 
303 
305 {
306  for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
307  node_counts[i] = 1;
308 
309  return;
310 }
311 
312 
313 bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
314 {
315  aIndex = 0;
316 
317  if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
318  {
319  #ifdef DEBUG
320  std::ostringstream ostr;
321  ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__;
322  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
323  ostr.str( "" );
324 
325  if( NULL == aNode )
326  {
327  wxLogTrace( MASK_3D_SG, " * [BUG] aNode is NULL\n" );
328  }
329  else
330  {
331  ostr << " * [BUG] invalid node type (" << aNode->GetNodeType();
332  ostr << "), expected " << S3D::SGTYPE_APPEARANCE;
333  wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
334  }
335  #endif
336 
337  return false;
338  }
339 
340  SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
341 
342  std::map< SGAPPEARANCE const*, int >::iterator it = aList.matmap.find( node );
343 
344  if( it != aList.matmap.end() )
345  {
346  aIndex = it->second;
347  return true;
348  }
349 
350  int idx = (int)aList.matorder.size();
351  aList.matorder.push_back( node );
352  aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
353  aIndex = idx;
354 
355  return true;
356 }
357 
358 
359 void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
360 {
361  memset( &aMaterial, 0, sizeof( aMaterial ) );
362  return;
363 }
364 
365 
366 void S3D::INIT_SMESH( SMESH& aMesh )
367 {
368  memset( &aMesh, 0, sizeof( aMesh ) );
369  return;
370 }
371 
372 
374 {
375  memset( &aModel, 0, sizeof( aModel ) );
376  return;
377 }
378 
379 
380 void S3D::FREE_SMESH( SMESH& aMesh)
381 {
382  if( NULL != aMesh.m_Positions )
383  {
384  delete [] aMesh.m_Positions;
385  aMesh.m_Positions = NULL;
386  }
387 
388  if( NULL != aMesh.m_Normals )
389  {
390  delete [] aMesh.m_Normals;
391  aMesh.m_Normals = NULL;
392  }
393 
394  if( NULL != aMesh.m_Texcoords )
395  {
396  delete [] aMesh.m_Texcoords;
397  aMesh.m_Texcoords = NULL;
398  }
399 
400  if( NULL != aMesh.m_Color )
401  {
402  delete [] aMesh.m_Color;
403  aMesh.m_Color = NULL;
404  }
405 
406  if( NULL != aMesh.m_FaceIdx )
407  {
408  delete [] aMesh.m_FaceIdx;
409  aMesh.m_FaceIdx = NULL;
410  }
411 
412  aMesh.m_VertexSize = 0;
413  aMesh.m_FaceIdxSize = 0;
414  aMesh.m_MaterialIdx = 0;
415 
416  return;
417 }
418 
419 
421 {
422  if( NULL != aModel.m_Materials )
423  {
424  delete [] aModel.m_Materials;
425  aModel.m_Materials = NULL;
426  }
427 
428  aModel.m_MaterialsSize = 0;
429 
430  if( NULL != aModel.m_Meshes )
431  {
432  for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
433  FREE_SMESH( aModel.m_Meshes[i] );
434 
435  delete [] aModel.m_Meshes;
436  aModel.m_Meshes = NULL;
437  }
438 
439  aModel.m_MeshesSize = 0;
440 
441  return;
442 }
define an internal structure to be used by the 3D renders
SFVEC3F * m_Normals
Vertex normals array.
Definition: c3dmodel.h:80
void addNodeRef(SGNODE *aNode)
Function addNodeRef adds a pointer to a node which references, but does not own, this node...
Definition: sg_node.cpp:176
virtual bool AddRefNode(SGNODE *aNode)=0
SGNODE * m_Parent
Definition: sg_node.h:83
void FREE_S3DMODEL(S3DMODEL &aModel)
Definition: sg_node.cpp:420
virtual ~SGNODE()
Definition: sg_node.cpp:87
SGNODE ** m_Association
Definition: sg_node.h:79
bool GetMatIndex(MATLIST &aList, SGNODE *aNode, int &aIndex)
Definition: sg_node.cpp:313
std::map< SGAPPEARANCE const *, int > matmap
Definition: sg_node.h:58
defines the base class of the intermediate scene graph NODE
Class SGNODE represents the base class of all Scene Graph nodes.
Definition: sg_node.h:76
SFVEC3F * m_Positions
Vertex position array.
Definition: c3dmodel.h:79
S3D::SGTYPES GetNodeType(void) const
Function GetNodeType returns the type of this node instance.
Definition: sg_node.cpp:108
static unsigned int node_counts[S3D::SGTYPE_END]
Definition: sg_node.cpp:48
void delNodeRef(const SGNODE *aNode)
Function delNodeRef removes a pointer to a node which references, but does not own, this node.
Definition: sg_node.cpp:192
Per-vertex normal/color/texcoors structure.
Definition: c3dmodel.h:76
SMESH * m_Meshes
The meshes list of this model.
Definition: c3dmodel.h:93
void FREE_SMESH(SMESH &aMesh)
Definition: sg_node.cpp:380
unsigned int m_FaceIdxSize
Number of elements of the m_FaceIdx array.
Definition: c3dmodel.h:83
virtual void unlinkRefNode(const SGNODE *aNode)=0
Function unlinkRef removes pointers to a referenced node; it is invoked by the referenced node upon d...
unsigned int m_VertexSize
Number of vertex in the arrays.
Definition: c3dmodel.h:78
const char * GetName(void)
Definition: sg_node.cpp:150
bool m_written
Definition: sg_node.h:86
SGNODE * GetParent(void) const
Function GetParent returns a pointer to the parent SGNODE of this object or NULL if the object has no...
Definition: sg_node.cpp:114
virtual void unlinkChildNode(const SGNODE *aNode)=0
Function unlinkChild removes references to an owned child; it is invoked by the child upon destructio...
SFVEC2F * m_Texcoords
Vertex texture coordinates array, can be NULL.
Definition: c3dmodel.h:81
bool SwapParent(SGNODE *aNewParent)
Function SwapParent swaps the ownership with the given parent.
Definition: sg_node.cpp:120
void AssociateWrapper(SGNODE **aWrapperRef)
Function AssociateWrapper associates this object with a handle to itself; this handle is typically he...
Definition: sg_node.cpp:219
SFVEC3F * m_Color
Vertex color array, can be NULL.
Definition: c3dmodel.h:82
SGNODE(SGNODE *aParent)
Definition: sg_node.cpp:76
unsigned int m_MaterialsSize
Number of materials in the material array.
Definition: c3dmodel.h:95
void SetName(const char *aName)
Definition: sg_node.cpp:159
std::string m_Name
Definition: sg_node.h:85
static const std::string node_names[S3D::SGTYPE_END+1]
Definition: sg_node.cpp:34
SGTYPES
Definition: sg_types.h:34
S3D::SGTYPES m_SGtype
Definition: sg_node.h:84
void INIT_SMESH(SMESH &aMesh)
Definition: sg_node.cpp:366
void DisassociateWrapper(SGNODE **aWrapperRef)
Function DisassociateWrapper removes the association between an IFSG* wrapper object and this object...
Definition: sg_node.cpp:264
void INIT_S3DMODEL(S3DMODEL &aModel)
Definition: sg_node.cpp:373
unsigned int m_MaterialIdx
Material Index to be used in this mesh (must be < m_MaterialsSize )
Definition: c3dmodel.h:85
std::vector< SGAPPEARANCE const * > matorder
Definition: sg_node.h:57
SMATERIAL * m_Materials
The materials list of this model.
Definition: c3dmodel.h:96
void INIT_SMATERIAL(SMATERIAL &aMaterial)
Definition: sg_node.cpp:359
virtual bool AddChildNode(SGNODE *aNode)=0
std::list< SGNODE * > m_BackPointers
Definition: sg_node.h:82
char const * GetNodeTypeName(S3D::SGTYPES aType)
Function GetNodeTypeName returns the name of the given type of node.
Definition: sg_node.cpp:51
Store the a model based on meshes and materials.
Definition: c3dmodel.h:90
unsigned int * m_FaceIdx
Triangle Face Indexes.
Definition: c3dmodel.h:84
unsigned int m_MeshesSize
Number of meshes in the array.
Definition: c3dmodel.h:92
const char * GetNodeTypeName(S3D::SGTYPES aNodeType) const
Definition: sg_node.cpp:170
void ResetNodeIndex(void)
Function ResetNodeIndex resets the global SG* node indices in preparation for Write() operations...
Definition: sg_node.cpp:304
static void getNodeName(S3D::SGTYPES nodeType, std::string &aName)
Definition: sg_node.cpp:57