KiCad PCB EDA Suite
x3d_ifaceset.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-2022 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 <cmath>
29#include <wx/log.h>
30#include <wx/xml/xml.h>
31#include <wx/tokenzr.h>
32#include "x3d_ops.h"
33#include "x3d_ifaceset.h"
34#include "x3d_coords.h"
36#include "wrlfacet.h"
37
38
40{
42 coord = nullptr;
43 init();
44}
45
46
48{
50 coord = nullptr;
51 init();
52
53 if( nullptr != aParent )
54 {
55 X3DNODES ptype = aParent->GetNodeType();
56
57 if( X3D_SHAPE == ptype )
58 m_Parent = aParent;
59 }
60
61 if( nullptr != m_Parent )
62 m_Parent->AddChildNode( this );
63}
64
65
67{
68 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] Destroying IndexedFaceSet." ) );
69}
70
71
73{
74 coord = nullptr;
75
76 ccw = true;
77 creaseAngle = 0.733f; // approx 42 degrees; this is larger than VRML spec.
78 creaseLimit = 0.74317f; // cos( 0.733 )
79}
80
81
82void X3DIFACESET::readFields( wxXmlNode* aNode )
83{
84 // DEF
85 // ccw
86 // creaseAngle
87 // coordIndex
88
89 wxXmlAttribute* prop;
90
91 for( prop = aNode->GetAttributes(); prop != nullptr; prop = prop->GetNext() )
92 {
93 const wxString& pname = prop->GetName();
94
95 if( pname == wxT( "DEF" ) )
96 {
97 m_Name = prop->GetValue();
98 m_Dict->AddName( m_Name, this );
99 }
100 else if( pname == wxT( "ccw" ) )
101 {
102 X3D::ParseSFBool( prop->GetValue(), ccw );
103 }
104 else if( pname == wxT( "creaseAngle" ) )
105 {
106 X3D::ParseSFFloat( prop->GetValue(), creaseAngle );
107
108 if( creaseAngle < 0.0f )
109 creaseAngle = 0.0f;
110 else if( creaseAngle > static_cast<float>( M_PI * 0.34f ) )
111 creaseAngle = static_cast<float>( M_PI / 3.0f );
112
113 creaseLimit = cosf( creaseAngle );
114 }
115 else if( pname == wxT( "coordIndex" ) )
116 {
117 wxStringTokenizer indices( prop->GetValue() );
118
119 while( indices.HasMoreTokens() )
120 {
121 long index = 0;
122 indices.GetNextToken().ToLong( &index );
123 coordIndex.push_back( (int) index );
124 }
125 }
126 }
127}
128
129
130bool X3DIFACESET::Read( wxXmlNode* aNode, X3DNODE* aTopNode, X3D_DICT& aDict )
131{
132 if( nullptr == aTopNode || nullptr == aNode )
133 return false;
134
135 m_Dict = &aDict;
136 readFields( aNode );
137 bool ok = false;
138
139 for( wxXmlNode* child = aNode->GetChildren(); child != nullptr; child = child->GetNext() )
140 {
141 if( child->GetName() == wxT( "Coordinate" ) )
142 ok = X3D::ReadCoordinates( child, this, aDict );
143
144 }
145
146 if( false == ok )
147 return false;
148
149 if( !SetParent( aTopNode ) )
150 return false;
151
152 return true;
153}
154
155
156bool X3DIFACESET::SetParent( X3DNODE* aParent, bool doUnlink )
157{
158 if( aParent == m_Parent )
159 return true;
160
161 if( nullptr != aParent )
162 {
163 X3DNODES nt = aParent->GetNodeType();
164
165 if( nt != X3D_SHAPE )
166 return false;
167 }
168
169 if( nullptr != m_Parent && doUnlink )
170 m_Parent->unlinkChildNode( this );
171
172 m_Parent = aParent;
173
174 if( nullptr != m_Parent )
175 m_Parent->AddChildNode( this );
176
177 return true;
178}
179
180
182{
183 if( nullptr == aNode )
184 return false;
185
186 if( aNode->GetNodeType() != X3D_COORDINATE )
187 return false;
188
189 if( aNode == coord )
190 return true;
191
192 if( nullptr != coord )
193 return false;
194
195 m_Children.push_back( aNode );
196 coord = aNode;
197
198 if( aNode->GetParent() != this )
199 aNode->SetParent( this );
200
201 return true;
202}
203
204
206{
207 if( nullptr == aNode )
208 return false;
209
210 if( aNode->GetNodeType() != X3D_COORDINATE )
211 return false;
212
213 if( aNode == coord )
214 return true;
215
216 if( nullptr != coord )
217 return false;
218
219 m_Refs.push_back( aNode );
220 aNode->addNodeRef( this );
221 coord = aNode;
222 return true;
223}
224
225
227{
228 S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
229
230 if( nullptr != aParent && ptype != S3D::SGTYPE_SHAPE )
231 {
232 wxLogTrace( traceVrmlPlugin,
233 wxT( " * [BUG] IndexedFaceSet does not have a valid Shape parent "
234 "(parent ID: %d)" ), ptype );
235
236 return nullptr;
237 }
238
239 wxLogTrace( traceVrmlPlugin,
240 wxT( " * [INFO] Translating IndexedFaceSet with %zu children, %zu references, "
241 "%zu back pointers, and %zu coordinate indices." ),
242 m_Children.size(), m_Refs.size(), m_BackPointers.size(), coordIndex.size() );
243
244 if( m_sgNode )
245 {
246 if( nullptr != aParent )
247 {
248 if( nullptr == S3D::GetSGNodeParent( m_sgNode )
249 && !S3D::AddSGNodeChild( aParent, m_sgNode ) )
250 {
251 return nullptr;
252 }
253 else if( aParent != S3D::GetSGNodeParent( m_sgNode )
254 && !S3D::AddSGNodeRef( aParent, m_sgNode ) )
255 {
256 return nullptr;
257 }
258 }
259
260 return m_sgNode;
261 }
262
263 size_t vsize = coordIndex.size();
264
265 if( nullptr == coord || vsize < 3 )
266 return nullptr;
267
268 WRLVEC3F* pcoords;
269 size_t coordsize;
270 ((X3DCOORDS*) coord)->GetCoords( pcoords, coordsize );
271
272 if( coordsize < 3 )
273 return nullptr;
274
275 // check that all indices are valid
276 for( size_t idx = 0; idx < vsize; ++idx )
277 {
278 if( coordIndex[idx] < 0 )
279 continue;
280
281 if( coordIndex[idx] >= (int)coordsize )
282 return nullptr;
283 }
284
285 SHAPE lShape;
286 FACET* fp = nullptr;
287 size_t iCoord;
288 int idx; // coordinate index
289
290 // no per-vertex colors; we can save a few CPU cycles
291 for( iCoord = 0; iCoord < vsize; ++iCoord )
292 {
293 idx = coordIndex[iCoord];
294
295 if( idx < 0 )
296 {
297 if( nullptr != fp )
298 {
299 if( fp->HasMinPoints() )
300 fp = nullptr;
301 else
302 fp->Init();
303 }
304
305 continue;
306 }
307
308 // if the coordinate is bad then skip it
309 if( idx >= (int)coordsize )
310 continue;
311
312 if( nullptr == fp )
313 fp = lShape.NewFacet();
314
315 // push the vertex value and index
316 fp->AddVertex( pcoords[idx], idx );
317 }
318
319 SGNODE* np = nullptr;
320
321 if( ccw )
322 np = lShape.CalcShape( aParent, nullptr, WRL1_ORDER::ORD_CCW, creaseLimit, true );
323 else
324 np = lShape.CalcShape( aParent, nullptr, WRL1_ORDER::ORD_CLOCKWISE, creaseLimit, true );
325
326 return np;
327}
Definition: wrlfacet.h:43
bool HasMinPoints()
Definition: wrlfacet.cpp:173
void AddVertex(WRLVEC3F &aVertex, int aIndex)
Add the vertex and its associated index to the internal list of polygon vertices.
Definition: wrlfacet.cpp:191
void Init()
Definition: wrlfacet.cpp:158
The base class of all Scene Graph nodes.
Definition: sg_node.h:75
An abstract shape on 2D plane.
Definition: shape.h:123
FACET * NewFacet()
Definition: wrlfacet.cpp:695
SGNODE * CalcShape(SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
Definition: wrlfacet.cpp:703
void readFields(wxXmlNode *aNode)
bool AddChildNode(X3DNODE *aNode) override
float creaseLimit
Definition: x3d_ifaceset.h:57
bool AddRefNode(X3DNODE *aNode) override
std::vector< int > coordIndex
Definition: x3d_ifaceset.h:58
virtual ~X3DIFACESET()
SGNODE * TranslateToSG(SGNODE *aParent) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
bool SetParent(X3DNODE *aParent, bool doUnlink=true) override
Set the parent X3DNODE of this object.
float creaseAngle
Definition: x3d_ifaceset.h:56
bool Read(wxXmlNode *aNode, X3DNODE *aTopNode, X3D_DICT &aDict) override
X3DNODE * coord
Definition: x3d_ifaceset.h:53
The base class of all X3D nodes.
Definition: x3d_base.h:75
X3DNODES m_Type
Definition: x3d_base.h:160
void addNodeRef(X3DNODE *aNode)
Add a pointer to a node which references, but does not own, this node.
Definition: x3d_base.cpp:142
std::list< X3DNODE * > m_Children
Definition: x3d_base.h:164
SGNODE * m_sgNode
Definition: x3d_base.h:169
std::list< X3DNODE * > m_BackPointers
Definition: x3d_base.h:163
X3DNODE * m_Parent
Definition: x3d_base.h:159
virtual bool AddChildNode(X3DNODE *aNode)=0
std::list< X3DNODE * > m_Refs
Definition: x3d_base.h:165
X3DNODES GetNodeType(void) const
Return the type of this node instance.
Definition: x3d_base.cpp:184
X3DNODE * GetParent(void) const
Return a pointer to the parent node of this object or NULL if the object has no parent (ie.
Definition: x3d_base.cpp:190
wxString m_Name
Definition: x3d_base.h:168
virtual bool SetParent(X3DNODE *aParent, bool doUnlink=true)=0
Set the parent X3DNODE of this object.
virtual void unlinkChildNode(const X3DNODE *aNode)
Remove references to an owned child; it is invoked by the child upon destruction to ensure that the p...
Definition: x3d_base.cpp:102
X3D_DICT * m_Dict
Definition: x3d_base.h:161
bool AddName(const wxString &aName, X3DNODE *aNode)
Definition: x3d_base.cpp:35
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_SHAPE
Definition: sg_types.h:44
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
bool ParseSFBool(const wxString &aSource, bool &aResult)
Definition: x3d_ops.cpp:231
bool ReadCoordinates(wxXmlNode *aNode, X3DNODE *aParent, X3D_DICT &aDict)
Definition: x3d_ops.cpp:193
bool ParseSFFloat(const wxString &aSource, float &aResult)
Definition: x3d_ops.cpp:252
declares classes to help manage normals calculations from VRML files
glm::vec3 WRLVEC3F
Definition: wrltypes.h:188
X3DNODES
Definition: x3d_base.h:60
@ X3D_SHAPE
Definition: x3d_base.h:63
@ X3D_COORDINATE
Definition: x3d_base.h:66
@ X3D_INDEXED_FACE_SET
Definition: x3d_base.h:65