KiCad PCB EDA Suite
Loading...
Searching...
No Matches
vrml1_faceset.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 <wx/log.h>
25
26#include "vrml1_base.h"
27#include "vrml1_faceset.h"
28#include "vrml1_coords.h"
29#include "vrml1_material.h"
30#include "wrlfacet.h"
32
33
38
39
41 WRL1NODE( aDictionary )
42{
44 m_Parent = aParent;
45
46 if( nullptr != m_Parent )
47 m_Parent->AddChildNode( this );
48}
49
50
52{
53 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] Destroying IndexedFaceSet with %zu children, "
54 "%zu references, and %zu back pointers." ),
55 m_Children.size(), m_Refs.size(), m_BackPointers.size() );
56}
57
58
60{
61 // this node may not own or reference any other node
62 wxCHECK_MSG( false, false, wxT( "AddRefNode is not applicable." ) );
63}
64
65
67{
68 // this node may not own or reference any other node
69 wxCHECK_MSG( false, false, wxT( "AddChildNode is not applicable." ) );
70}
71
72
73bool WRL1FACESET::Read( WRLPROC& proc, WRL1BASE* aTopNode )
74{
75 char tok = proc.Peek();
76
77 if( proc.eof() )
78 {
79 wxLogTrace( traceVrmlPlugin,
80 wxT( "%s:%s:%d\n"
81 " * [INFO] bad file format; unexpected eof %s." ),
82 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition() );
83
84 return false;
85 }
86
87 if( '{' != tok )
88 {
89 wxLogTrace( traceVrmlPlugin,
90 wxT( "%s:%s:%d\n"
91 " * [INFO] bad file format; expecting '{' but got '%s' %s." ),
92 __FILE__, __FUNCTION__, __LINE__, tok, proc.GetFilePosition() );
93
94 return false;
95 }
96
97 proc.Pop();
98 std::string glob;
99
100 while( true )
101 {
102 if( proc.Peek() == '}' )
103 {
104 proc.Pop();
105 break;
106 }
107
108 if( !proc.ReadName( glob ) )
109 {
110 wxLogTrace( traceVrmlPlugin, wxT( "%s:%s:%d\n%s" ),
111 __FILE__, __FUNCTION__, __LINE__, proc.GetError() );
112
113 return false;
114 }
115
116 // expecting one of:
117 // coordIndex[]
118 // materialIndex[]
119
120 if( !glob.compare( "coordIndex" ) )
121 {
122 if( !proc.ReadMFInt( coordIndex ) )
123 {
124 wxLogTrace( traceVrmlPlugin,
125 wxT( "%s:%s:%d\n"
126 " * [INFO] invalid coordIndex %s.\n"
127 " * [INFO] file: '%s'\n"
128 "%s" ),
129 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
130 proc.GetFileName(), proc.GetError() );
131
132 return false;
133 }
134 }
135 else if( !glob.compare( "materialIndex" ) )
136 {
137 if( !proc.ReadMFInt( matIndex ) )
138 {
139 wxLogTrace( traceVrmlPlugin,
140 wxT( "%s:%s:%d\n"
141 " * [INFO] invalid materialIndex %s.\n"
142 " * [INFO] file: '%s'\n"
143 "%s" ),
144 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
145 proc.GetFileName(), proc.GetError() );
146
147 return false;
148 }
149 }
150 else if( !glob.compare( "normalIndex" ) )
151 {
152 if( !proc.ReadMFInt( normIndex ) )
153 {
154 wxLogTrace( traceVrmlPlugin,
155 wxT( "%s:%s:%d\n"
156 " * [INFO] invalid normalIndex %s\n"
157 " * [INFO] file: '%s'\n"
158 "%s" ),
159 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
160 proc.GetFileName(), proc.GetError() );
161
162 return false;
163 }
164 }
165 else if( !glob.compare( "textureCoordIndex" ) )
166 {
167 if( !proc.ReadMFInt( texIndex ) )
168 {
169 wxLogTrace( traceVrmlPlugin,
170 wxT( "%s:%s:%d\n"
171 " * [INFO] invalid textureCoordIndex %s.\n"
172 " * [INFO] file: '%s'\n"
173 "%s" ),
174 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
175 proc.GetFileName(), proc.GetError() );
176
177 return false;
178 }
179 }
180 else
181 {
182 wxLogTrace( traceVrmlPlugin,
183 wxT( "%s:%s:%d\n"
184 " * [INFO] invalid IndexedFaceSet %s.\n"
185 " * [INFO] file: '%s'" ),
186 __FILE__, __FUNCTION__, __LINE__, proc.GetFilePosition(),
187 proc.GetFileName() );
188
189 return false;
190 }
191 } // while( true ) -- reading contents of IndexedFaceSet{}
192
193 return true;
194}
195
196
198{
199 // note: m_sgNode is unused because we cannot manage everything
200 // with a single reused transform due to the fact that VRML1
201 // may use a MatrixTransformation entity which is impossible to
202 // decompose into Rotate,Scale,Transform via an analytic expression.
203 if( !m_Parent )
204 {
205 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] bad model: no parent node." ) );
206
207 return nullptr;
208 }
209 else
210 {
211 if( nullptr == sp )
212 {
213 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] bad model: no base data given." ) );
214
215 return nullptr;
216 }
217 }
218
219 m_current = *sp;
220
221 if( nullptr == m_current.coord )
222 {
223 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] bad model: no vertex set." ) );
224 return nullptr;
225 }
226
227 if( nullptr == m_current.mat )
228 {
229 wxLogTrace( traceVrmlPlugin, wxT( " * [INFO] bad model: no material set." ) );
230 return nullptr;
231 }
232
233 WRLVEC3F* pcoords;
234 size_t coordsize;
235
236 m_current.coord->GetCoords( pcoords, coordsize );
237 size_t vsize = coordIndex.size();
238
239 if( coordsize < 3 || vsize < 3 )
240 {
241 wxLogTrace( traceVrmlPlugin,
242 wxT( " * [INFO] bad model: coordsize = %zu, indexsize = %zu" ),
243 coordsize, vsize );
244
245 return nullptr;
246 }
247
248 // 1. create the vertex/normals/colors lists
249 SGNODE* sgcolor = nullptr;
250 WRL1_BINDING mbind = m_current.matbind;
251 size_t matSize = matIndex.size();
252
253 switch( mbind )
254 {
258 break;
259
261
262 if( matIndex.empty() )
263 {
264 wxLogTrace( traceVrmlPlugin,
265 wxT( " * [INFO] bad model: per face indexed but no indices" ) );
266
267 // support bad models by temporarily switching bindings
269 sgcolor = m_current.mat->GetAppearance( 0 );
270 }
271
272 break;
273
274 default:
275
276 // use the first appearance definition
277 sgcolor = m_current.mat->GetAppearance( 0 );
278 break;
279 }
280
281 // copy the data into FACET structures
282
283 SHAPE lShape;
284 FACET* fp = nullptr;
285 size_t iCoord;
286 int idx; // coordinate index
287 size_t cidx = 0; // color index
288 SGCOLOR pc1;
289
291 {
292 // no per-vertex colors; we can save a few CPU cycles
293 for( iCoord = 0; iCoord < vsize; ++iCoord )
294 {
295 idx = coordIndex[iCoord];
296
297 if( idx < 0 )
298 {
299 if( nullptr != fp )
300 {
301 if( fp->HasMinPoints() )
302 fp = nullptr;
303 else
304 fp->Init();
305 }
306
307 continue;
308 }
309
310 // if the coordinate is bad then skip it
311 if( idx >= (int)coordsize )
312 continue;
313
314 if( nullptr == fp )
315 fp = lShape.NewFacet();
316
317 // push the vertex value and index
318 WRLVEC3F vf;
319 glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
320 pt = m_current.txmatrix * pt;
321 vf.x = pt.x;
322 vf.y = pt.y;
323 vf.z = pt.z;
324
325 fp->AddVertex( vf, idx );
326 }
327 }
328 else
329 {
330 for( iCoord = 0; iCoord < vsize; ++iCoord )
331 {
332 idx = coordIndex[iCoord];
333
334 if( idx < 0 )
335 {
336 if( nullptr != fp )
337 {
338 if( fp->HasMinPoints() )
339 fp = nullptr;
340 else
341 fp->Init();
342 }
343
344 if( mbind == WRL1_BINDING::BIND_PER_FACE
346 ++cidx;
347
348 continue;
349 }
350
351 // if the coordinate is bad then skip it
352 if( idx >= (int)coordsize )
353 continue;
354
355 if( nullptr == fp )
356 fp = lShape.NewFacet();
357
358 // push the vertex value and index
359 WRLVEC3F vf;
360 glm::vec4 pt = glm::vec4( pcoords[idx].x, pcoords[idx].y, pcoords[idx].z, 1.0 );
361 pt = m_current.txmatrix * pt;
362 vf.x = pt.x;
363 vf.y = pt.y;
364 vf.z = pt.z;
365
366 fp->AddVertex( vf, idx );
367
368 // push the color if appropriate
369 switch( mbind )
370 {
372
373 if( !fp->HasColors() )
374 {
375 m_current.mat->GetColor( &pc1, cidx );
376 fp->AddColor( pc1 );
377 }
378
379 break;
380
382 m_current.mat->GetColor( &pc1, idx );
383 fp->AddColor( pc1 );
384 break;
385
387
388 if( !fp->HasColors() )
389 {
390 if( cidx >= matSize )
391 m_current.mat->GetColor( &pc1, matIndex.back() );
392 else
393 m_current.mat->GetColor( &pc1, matIndex[cidx] );
394
395 fp->AddColor( pc1 );
396 }
397
398 break;
399
401
402 if( matIndex.empty() )
403 {
404 m_current.mat->GetColor( &pc1, idx );
405 }
406 else
407 {
408 if( iCoord >= matSize )
409 m_current.mat->GetColor( &pc1, matIndex.back() );
410 else
411 m_current.mat->GetColor( &pc1, matIndex[iCoord] );
412 }
413
414 fp->AddColor( pc1 );
415
416 break;
417
418 default:
419 break;
420 }
421 }
422 }
423
424 // extract the final data set
425 SGNODE* np = lShape.CalcShape( aParent, sgcolor, m_current.order, m_current.creaseLimit );
426
427 return np;
428}
bool HasMinPoints()
Definition wrlfacet.cpp:169
bool HasColors()
Definition wrlfacet.cpp:178
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 AddColor(const SGCOLOR &aColor)
Add the given RGB color to the internal list.
Definition wrlfacet.cpp:200
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
Represent the top node of a VRML1 model.
Definition vrml1_base.h:42
SGNODE * TranslateToSG(SGNODE *aParent, WRL1STATUS *sp) override
Produce a representation of the data using the intermediate scenegraph structures of the kicad_3dsg l...
std::vector< int > normIndex
WRL1FACESET(NAMEREGISTER *aDictionary)
bool AddChildNode(WRL1NODE *aNode) override
bool Read(WRLPROC &proc, WRL1BASE *aTopNode) override
bool AddRefNode(WRL1NODE *aNode) override
virtual ~WRL1FACESET()
std::vector< int > texIndex
std::vector< int > matIndex
std::vector< int > coordIndex
WRL1NODE(NAMEREGISTER *aDictionary)
WRL1NODES m_Type
Definition vrml1_node.h:223
WRL1STATUS m_current
Definition vrml1_node.h:232
std::list< WRL1NODE * > m_BackPointers
Definition vrml1_node.h:226
std::list< WRL1NODE * > m_Children
Definition vrml1_node.h:227
WRL1NODE * m_Parent
Definition vrml1_node.h:222
std::list< WRL1NODE * > m_Refs
Definition vrml1_node.h:228
void Pop(void)
Definition wrlproc.cpp:2031
char Peek(void)
Definition wrlproc.cpp:2003
std::string GetFileName(void)
Definition wrlproc.cpp:1991
bool ReadMFInt(std::vector< int > &aMFInt32)
Definition wrlproc.cpp:1500
std::string GetError(void)
Definition wrlproc.cpp:1956
bool eof(void)
Definition wrlproc.cpp:1950
bool ReadName(std::string &aName)
Definition wrlproc.cpp:285
std::string GetFilePosition() const
Definition wrlproc.cpp:1978
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
declares classes to help manage normals calculations from VRML files
@ WRL1_INDEXEDFACESET
Definition wrltypes.h:63
WRL1_BINDING
Definition wrltypes.h:97
@ BIND_PER_VERTEX_INDEXED
Definition wrltypes.h:105
@ BIND_PER_FACE_INDEXED
Definition wrltypes.h:103
glm::vec3 WRLVEC3F
Definition wrltypes.h:184