You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

765 lines
18 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2016 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. #include <iostream>
  24. #include "vrml1_base.h"
  25. #include "vrml1_group.h"
  26. #include "vrml1_separator.h"
  27. #include "vrml1_material.h"
  28. #include "vrml1_matbinding.h"
  29. #include "vrml1_coords.h"
  30. #include "vrml1_switch.h"
  31. #include "vrml1_faceset.h"
  32. #include "vrml1_transform.h"
  33. #include "vrml1_shapehints.h"
  34. #include "plugins/3dapi/ifsg_all.h"
  35. WRL1BASE::WRL1BASE() : WRL1NODE( NULL )
  36. {
  37. m_useInline = false;
  38. m_Type = WRL1_BASE;
  39. m_dictionary = new NAMEREGISTER;
  40. return;
  41. }
  42. WRL1BASE::~WRL1BASE()
  43. {
  44. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
  45. std::cerr << " * [INFO] Destroying virtual base node\n";
  46. #endif
  47. cancelDict();
  48. return;
  49. }
  50. // functions inherited from WRL1NODE
  51. bool WRL1BASE::SetParent( WRL1NODE* aParent )
  52. {
  53. #ifdef DEBUG_VRML1
  54. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  55. std::cerr << " * [BUG] attempting to set parent on WRL1BASE node\n";
  56. #endif
  57. return false;
  58. }
  59. void WRL1BASE::SetEnableInline( bool enable )
  60. {
  61. m_useInline = enable;
  62. return;
  63. }
  64. bool WRL1BASE::GetEnableInline( void )
  65. {
  66. return m_useInline;
  67. }
  68. SGNODE* WRL1BASE::AddInlineData( const std::string& aName, WRL1INLINE* aObject )
  69. {
  70. std::map< std::string, WRL1INLINE* >::iterator dp = m_inlineModels.find( aName );
  71. // XXX;
  72. // qwerty;
  73. return NULL;
  74. }
  75. SGNODE* WRL1BASE::GetInlineData( const std::string& aName, WRL1INLINE* aObject )
  76. {
  77. // XXX;
  78. // qwerty;
  79. return NULL;
  80. }
  81. void WRL1BASE::DelInlineData( const std::string& aName, WRL1INLINE* aObject )
  82. {
  83. // XXX;
  84. // qwerty;
  85. return;
  86. }
  87. std::string WRL1BASE::GetName( void )
  88. {
  89. #ifdef DEBUG_VRML1
  90. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  91. std::cerr << " * [BUG] attempting to extract name from virtual base node\n";
  92. #endif
  93. return std::string( "" );
  94. }
  95. bool WRL1BASE::SetName( const std::string& aName )
  96. {
  97. #ifdef DEBUG_VRML1
  98. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  99. std::cerr << " * [BUG] attempting to set name on virtual base node\n";
  100. #endif
  101. return false;
  102. }
  103. bool WRL1BASE::Read( WRLPROC& proc )
  104. {
  105. if( proc.GetVRMLType() != VRML_V1 )
  106. {
  107. #ifdef DEBUG_VRML1
  108. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  109. std::cerr << " * [BUG] no open file or file is not a VRML1 file\n";
  110. #endif
  111. return false;
  112. }
  113. std::string glob;
  114. WRL1NODES ntype;
  115. // Note: according to the VRML1 specification, a file may contain
  116. // only one grouping node at the top level. The following code
  117. // supports non-conformant VRML1 files by processing all top level
  118. // grouping nodes.
  119. while( proc.ReadName( glob ) )
  120. {
  121. // Process node name: only Separator, Switch and DEF are acceptable;
  122. // WWWAnchor and LOD will not be supported
  123. if( !glob.compare( "DEF" ) )
  124. {
  125. // read the name and discard it; we must not add it to the dictionary
  126. // because that invites the possibility of a circular reference
  127. for( int i = 0; i < 2; ++i )
  128. {
  129. if( !proc.ReadName( glob ) )
  130. {
  131. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  132. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  133. std::cerr << proc.GetError() << "\n";
  134. #endif
  135. return false;
  136. }
  137. }
  138. }
  139. ntype = getNodeTypeID( glob );
  140. size_t line = 0;
  141. size_t column = 0;
  142. proc.GetFilePosData( line, column );
  143. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
  144. std::cerr << " * [INFO] Processing node '" << glob << "' ID: " << ntype << "\n";
  145. #endif
  146. if( ntype != WRL1_SEPARATOR && ntype != WRL1_SWITCH && ntype != WRL1_GROUP )
  147. {
  148. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  149. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  150. std::cerr << " * [INFO] bad file - top node is not a Separator, Switch, or Group\n";
  151. #endif
  152. return false;
  153. }
  154. switch( ntype )
  155. {
  156. case WRL1_SEPARATOR:
  157. if( !readSeparator( proc, this, NULL ) )
  158. return false;
  159. break;
  160. case WRL1_GROUP:
  161. if( !readGroup( proc, this, NULL ) )
  162. return false;
  163. break;
  164. default:
  165. if( !readSwitch( proc, this, NULL ) )
  166. return false;
  167. }
  168. }
  169. if( !proc.eof() )
  170. {
  171. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  172. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  173. std::cerr << proc.GetError() << "\n";
  174. #endif
  175. return false;
  176. }
  177. return true;
  178. }
  179. bool WRL1BASE::implementUse( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  180. {
  181. if( NULL != aNode )
  182. *aNode = NULL;
  183. if( !aParent )
  184. {
  185. #ifdef DEBUG_VRML1
  186. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  187. std::cerr << " * [BUG] invoked with NULL parent\n";
  188. #endif
  189. return false;
  190. }
  191. std::string glob;
  192. if( !proc.ReadName( glob ) )
  193. {
  194. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  195. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  196. std::cerr << proc.GetError() << "\n";
  197. #endif
  198. return false;
  199. }
  200. WRL1NODE* ref = aParent->FindNode( glob );
  201. // return 'true' - the file may be defective but it may still be somewhat OK
  202. if( NULL == ref )
  203. {
  204. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  205. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  206. std::cerr << " * [INFO] node '" << glob << "' not found\n";
  207. #endif
  208. return true;
  209. }
  210. if( !aParent->AddRefNode( ref ) )
  211. {
  212. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  213. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  214. std::cerr << " * [INFO] failed to add node '" << glob << "' (";
  215. std::cerr << ref->GetNodeTypeName( ref->GetNodeType() ) << ") to parent of type ";
  216. std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() ) << "\n";
  217. #endif
  218. return false;
  219. }
  220. if( NULL != aNode )
  221. *aNode = ref;
  222. return true;
  223. }
  224. bool WRL1BASE::implementDef( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  225. {
  226. if( NULL != aNode )
  227. *aNode = NULL;
  228. if( NULL == aParent )
  229. {
  230. #ifdef DEBUG_VRML1
  231. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  232. std::cerr << " * [BUG] invalid parent pointer (NULL)\n";
  233. #endif
  234. return false;
  235. }
  236. std::string glob;
  237. WRL1NODE* lnode = NULL;
  238. if( !proc.ReadName( glob ) )
  239. {
  240. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  241. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  242. std::cerr << proc.GetError() << "\n";
  243. #endif
  244. return false;
  245. }
  246. size_t line, column;
  247. proc.GetFilePosData( line, column );
  248. if( ReadNode( proc, aParent, &lnode ) )
  249. {
  250. if( NULL != aNode )
  251. *aNode = lnode;
  252. if( lnode && !lnode->SetName( glob ) )
  253. {
  254. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  255. size_t line, column;
  256. proc.GetFilePosData( line, column );
  257. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  258. std::cerr << " * [INFO] bad formatting (invalid name) at line";
  259. std::cerr << line << ", column " << column << "\n";
  260. #endif
  261. return false;
  262. }
  263. if( !m_dictionary )
  264. return false;
  265. m_dictionary->AddName( glob, lnode );
  266. return true;
  267. }
  268. return false;
  269. }
  270. bool WRL1BASE::ReadNode( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  271. {
  272. // This function reads a node and stores a pointer to it in aNode.
  273. // A value 'true' is returned if a node is successfully read or,
  274. // if the node is not supported, successfully discarded. Callers
  275. // must always check the value of aNode when the function returns
  276. // 'true' since it will be NULL if the node type is not supported.
  277. if( NULL != aNode )
  278. *aNode = NULL;
  279. if( NULL == aParent )
  280. {
  281. #ifdef DEBUG_VRML1
  282. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  283. std::cerr << " * [BUG] invalid parent pointer (NULL)\n";
  284. #endif
  285. return false;
  286. }
  287. std::string glob;
  288. WRL1NODES ntype;
  289. if( !proc.ReadName( glob ) )
  290. {
  291. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  292. if( !proc.eof() )
  293. {
  294. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  295. std::cerr << proc.GetError() << "\n";
  296. }
  297. #endif
  298. return false;
  299. }
  300. // Process node name:
  301. // the names encountered at this point should be one of the
  302. // built-in node names or one of:
  303. // DEF, USE
  304. if( !glob.compare( "USE" ) )
  305. {
  306. if( !implementUse( proc, aParent, aNode ) )
  307. {
  308. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  309. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  310. std::cerr << proc.GetError() << "\n";
  311. #endif
  312. return false;
  313. }
  314. return true;
  315. }
  316. if( !glob.compare( "DEF" ) )
  317. {
  318. if( !implementDef( proc, aParent, aNode ) )
  319. {
  320. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  321. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  322. std::cerr << proc.GetError() << "\n";
  323. #endif
  324. return false;
  325. }
  326. return true;
  327. }
  328. ntype = getNodeTypeID( glob );
  329. size_t line = 0;
  330. size_t column = 0;
  331. proc.GetFilePosData( line, column );
  332. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
  333. std::cerr << " * [INFO] Processing node '" << glob << "' ID: " << ntype << "\n";
  334. #endif
  335. switch( ntype )
  336. {
  337. case WRL1_GROUP:
  338. if( !readGroup( proc, aParent, aNode ) )
  339. return false;
  340. break;
  341. case WRL1_SEPARATOR:
  342. if( !readSeparator( proc, aParent, aNode ) )
  343. return false;
  344. break;
  345. case WRL1_SWITCH:
  346. if( !readSwitch( proc, aParent, aNode ) )
  347. return false;
  348. break;
  349. case WRL1_MATERIAL:
  350. if( !readMaterial( proc, aParent, aNode ) )
  351. return false;
  352. break;
  353. case WRL1_MATERIALBINDING:
  354. if( !readMatBinding( proc, aParent, aNode ) )
  355. return false;
  356. break;
  357. case WRL1_COORDINATE3:
  358. if( !readCoords( proc, aParent, aNode ) )
  359. return false;
  360. break;
  361. case WRL1_INDEXEDFACESET:
  362. if( !readFaceSet( proc, aParent, aNode ) )
  363. return false;
  364. break;
  365. case WRL1_TRANSFORM:
  366. case WRL1_TRANSLATION:
  367. case WRL1_ROTATION:
  368. case WRL1_SCALE:
  369. if( !readTransform( proc, aParent, aNode ) )
  370. return false;
  371. break;
  372. case WRL1_SHAPEHINTS:
  373. if( !readShapeHints( proc, aParent, aNode ) )
  374. return false;
  375. break;
  376. //
  377. // items not implemented or for optional future implementation:
  378. //
  379. default:
  380. proc.GetFilePosData( line, column );
  381. if( !proc.DiscardNode() )
  382. {
  383. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  384. std::cerr << proc.GetError() << "\n";
  385. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  386. std::cerr << " * [INFO] could not discard node at line " << line;
  387. std::cerr << ", column " << column << "\n";
  388. #endif
  389. return false;
  390. }
  391. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
  392. else
  393. {
  394. std::cerr << " * [INFO] discarded node '" << glob << "' at line ";
  395. std::cerr << line << ", col " << column << " (currently unsupported)\n";
  396. }
  397. #endif
  398. break;
  399. }
  400. return true;
  401. }
  402. bool WRL1BASE::Read( WRLPROC& proc, WRL1BASE* aTopNode )
  403. {
  404. // this function makes no sense in the base node
  405. #ifdef DEBUG_VRML1
  406. std::cerr << proc.GetError() << "\n";
  407. std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
  408. std::cerr << " * [BUG] this method must never be invoked on a WRL1BASE object\n";
  409. #endif
  410. return false;
  411. }
  412. bool WRL1BASE::readGroup( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  413. {
  414. if( NULL != aNode )
  415. *aNode = NULL;
  416. WRL1GROUP* np = new WRL1GROUP( m_dictionary, aParent );
  417. if( !np->Read( proc, this ) )
  418. {
  419. delete np;
  420. return false;
  421. }
  422. if( NULL != aNode )
  423. *aNode = (WRL1NODE*) np;
  424. return true;
  425. }
  426. bool WRL1BASE::readSeparator( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  427. {
  428. if( NULL != aNode )
  429. *aNode = NULL;
  430. WRL1SEPARATOR* np = new WRL1SEPARATOR( m_dictionary, aParent );
  431. if( !np->Read( proc, this ) )
  432. {
  433. delete np;
  434. return false;
  435. }
  436. if( NULL != aNode )
  437. *aNode = (WRL1NODE*) np;
  438. return true;
  439. }
  440. bool WRL1BASE::readSwitch( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  441. {
  442. WRL1SWITCH* np = new WRL1SWITCH( m_dictionary, aParent );
  443. if( !np->Read( proc, this ) )
  444. {
  445. delete np;
  446. return false;
  447. }
  448. if( NULL != aNode )
  449. *aNode = (WRL1NODE*) np;
  450. return true;
  451. }
  452. bool WRL1BASE::readMaterial( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  453. {
  454. if( NULL != aNode )
  455. *aNode = NULL;
  456. WRL1MATERIAL* np = new WRL1MATERIAL( m_dictionary, aParent );
  457. if( !np->Read( proc, this ) )
  458. {
  459. delete np;
  460. return false;
  461. }
  462. if( NULL != aNode )
  463. *aNode = (WRL1NODE*) np;
  464. return true;
  465. }
  466. bool WRL1BASE::readMatBinding( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  467. {
  468. if( NULL != aNode )
  469. *aNode = NULL;
  470. WRL1MATBINDING* np = new WRL1MATBINDING( m_dictionary, aParent );
  471. if( !np->Read( proc, this ) )
  472. {
  473. delete np;
  474. return false;
  475. }
  476. if( NULL != aNode )
  477. *aNode = (WRL1NODE*) np;
  478. return true;
  479. }
  480. bool WRL1BASE::readCoords( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  481. {
  482. if( NULL != aNode )
  483. *aNode = NULL;
  484. WRL1COORDS* np = new WRL1COORDS( m_dictionary, aParent );
  485. if( !np->Read( proc, this ) )
  486. {
  487. delete np;
  488. return false;
  489. }
  490. if( NULL != aNode )
  491. *aNode = (WRL1NODE*) np;
  492. return true;
  493. }
  494. bool WRL1BASE::readFaceSet( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  495. {
  496. if( NULL != aNode )
  497. *aNode = NULL;
  498. WRL1FACESET* np = new WRL1FACESET( m_dictionary, aParent );
  499. if( !np->Read( proc, this ) )
  500. {
  501. delete np;
  502. return false;
  503. }
  504. if( NULL != aNode )
  505. *aNode = (WRL1NODE*) np;
  506. return true;
  507. }
  508. bool WRL1BASE::readTransform( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  509. {
  510. if( NULL != aNode )
  511. *aNode = NULL;
  512. WRL1TRANSFORM* np = new WRL1TRANSFORM( m_dictionary, aParent );
  513. if( !np->Read( proc, this ) )
  514. {
  515. delete np;
  516. return false;
  517. }
  518. if( NULL != aNode )
  519. *aNode = (WRL1NODE*) np;
  520. return true;
  521. }
  522. bool WRL1BASE::readShapeHints( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
  523. {
  524. if( NULL != aNode )
  525. *aNode = NULL;
  526. WRL1SHAPEHINTS* np = new WRL1SHAPEHINTS( m_dictionary, aParent );
  527. if( !np->Read( proc, this ) )
  528. {
  529. delete np;
  530. return false;
  531. }
  532. if( NULL != aNode )
  533. *aNode = (WRL1NODE*) np;
  534. return true;
  535. }
  536. SGNODE* WRL1BASE::TranslateToSG( SGNODE* aParent, WRL1STATUS* /*sp*/ )
  537. {
  538. #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
  539. std::cerr << " * [INFO] Translating VRML1 Base with " << m_Items.size();
  540. std::cerr << " items\n";
  541. #endif
  542. if( m_Items.empty() )
  543. return NULL;
  544. if( m_Items.size() == 1 )
  545. return (*m_Items.begin())->TranslateToSG( NULL, NULL );
  546. // Note: according to the VRML1 specification, a file may contain
  547. // only one grouping node at the top level. The following code
  548. // supports non-conformant VRML1 files.
  549. m_current.Init();
  550. IFSG_TRANSFORM txNode( true );
  551. bool hasContent = false;
  552. std::list< WRL1NODE* >::iterator sI = m_Items.begin();
  553. std::list< WRL1NODE* >::iterator eI = m_Items.end();
  554. SGNODE* node = txNode.GetRawPtr();
  555. while( sI != eI )
  556. {
  557. if( NULL != (*sI)->TranslateToSG( node, &m_current ) )
  558. hasContent = true;
  559. ++sI;
  560. }
  561. if( !hasContent )
  562. {
  563. txNode.Destroy();
  564. return NULL;
  565. }
  566. return node;
  567. }