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