Added support for FreeCAD VRML files

This commit is contained in:
Cirilo Bernardo 2016-01-04 18:10:15 +11:00
parent 97d4c33a9f
commit c798f8b545
16 changed files with 631 additions and 28 deletions

View File

@ -486,3 +486,23 @@ bool S3D::AddSGNodeRef( SGNODE* aParent, SGNODE* aChild )
return aParent->AddRefNode( aChild ); return aParent->AddRefNode( aChild );
} }
bool S3D::AddSGNodeChild( SGNODE* aParent, SGNODE* aChild )
{
if( NULL == aParent || NULL == aChild )
return false;
return aParent->AddChildNode( aChild );
}
void S3D::AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr )
{
if( NULL == aObject || NULL == aRefPtr || aObject != *aRefPtr )
return;
aObject->AssociateWrapper( aRefPtr );
return;
}

View File

@ -46,6 +46,8 @@ namespace S3D
SGLIB_API S3D::SGTYPES GetSGNodeType( SGNODE* aNode ); SGLIB_API S3D::SGTYPES GetSGNodeType( SGNODE* aNode );
SGLIB_API SGNODE* GetSGNodeParent( SGNODE* aNode ); SGLIB_API SGNODE* GetSGNodeParent( SGNODE* aNode );
SGLIB_API bool AddSGNodeRef( SGNODE* aParent, SGNODE* aChild ); SGLIB_API bool AddSGNodeRef( SGNODE* aParent, SGNODE* aChild );
SGLIB_API bool AddSGNodeChild( SGNODE* aParent, SGNODE* aChild );
SGLIB_API void AssociateSGNodeWrapper( SGNODE* aObject, SGNODE** aRefPtr );
/** /**
* Function CalcTriNorm * Function CalcTriNorm

View File

@ -19,6 +19,7 @@ add_library( s3d_plugin_vrml MODULE
v2/vrml2_norms.cpp v2/vrml2_norms.cpp
v2/vrml2_color.cpp v2/vrml2_color.cpp
v2/vrml2_box.cpp v2/vrml2_box.cpp
v2/vrml2_switch.cpp
) )
target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} ) target_link_libraries( s3d_plugin_vrml kicad_3dsg ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} )

View File

@ -369,10 +369,18 @@ SGNODE* WRL2APPEARANCE::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;

View File

@ -33,11 +33,13 @@
#include "vrml2_norms.h" #include "vrml2_norms.h"
#include "vrml2_color.h" #include "vrml2_color.h"
#include "vrml2_box.h" #include "vrml2_box.h"
#include "vrml2_switch.h"
#include "plugins/3dapi/ifsg_all.h" #include "plugins/3dapi/ifsg_all.h"
WRL2BASE::WRL2BASE() : WRL2NODE() WRL2BASE::WRL2BASE() : WRL2NODE()
{ {
m_useInline = false;
m_Type = WRL2_BASE; m_Type = WRL2_BASE;
return; return;
} }
@ -61,6 +63,44 @@ bool WRL2BASE::SetParent( WRL2NODE* aParent )
} }
void WRL2BASE::SetEnableInline( bool enable )
{
m_useInline = enable;
return;
}
bool WRL2BASE::GetEnableInline( void )
{
return m_useInline;
}
SGNODE* WRL2BASE::AddInlineData( const std::string& aName, WRL2INLINE* aObject )
{
std::map< std::string, WRL2INLINE* >::iterator dp = m_inlineModels.find( aName );
// XXX;
// qwerty;
return NULL;
}
SGNODE* WRL2BASE::GetInlineData( const std::string& aName, WRL2INLINE* aObject )
{
// XXX;
// qwerty;
return NULL;
}
void WRL2BASE::DelInlineData( const std::string& aName, WRL2INLINE* aObject )
{
// XXX;
// qwerty;
return;
}
std::string WRL2BASE::GetName( void ) std::string WRL2BASE::GetName( void )
{ {
#ifdef DEBUG_VRML2 #ifdef DEBUG_VRML2
@ -508,6 +548,13 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
break; break;
case WRL2_SWITCH:
if( !readSwitch( proc, aParent, aNode ) )
return false;
break;
case WRL2_TRANSFORM: case WRL2_TRANSFORM:
case WRL2_GROUP: case WRL2_GROUP:
@ -549,7 +596,6 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
case WRL2_SOUND: case WRL2_SOUND:
case WRL2_SPHERESENSOR: case WRL2_SPHERESENSOR:
case WRL2_SPOTLIGHT: case WRL2_SPOTLIGHT:
case WRL2_SWITCH:
case WRL2_TEXT: case WRL2_TEXT:
case WRL2_TEXTURECOORDINATE: case WRL2_TEXTURECOORDINATE:
case WRL2_TEXTURETRANSFORM: case WRL2_TEXTURETRANSFORM:
@ -775,13 +821,62 @@ bool WRL2BASE::readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
} }
bool WRL2BASE::readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
{
if( NULL != aNode )
*aNode = NULL;
WRL2SWITCH* np = new WRL2SWITCH( aParent );
if( !np->Read( proc, this ) )
{
delete np;
return false;
}
if( NULL != aNode )
*aNode = (WRL2NODE*) np;
return true;
}
SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals ) SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
{ {
if( m_Children.empty() ) if( m_Children.empty() )
return NULL; return NULL;
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_SHAPE )
{
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] WRL2BASE does not have a Transform parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
return NULL;
}
if( m_sgNode ) if( m_sgNode )
{
if( NULL != aParent )
{
if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
}
return m_sgNode; return m_sgNode;
}
IFSG_TRANSFORM topNode( aParent ); IFSG_TRANSFORM topNode( aParent );
@ -815,6 +910,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
break; break;
case WRL2_TRANSFORM: case WRL2_TRANSFORM:
case WRL2_SWITCH:
if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr(), calcNormals ) ) if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr(), calcNormals ) )
test = true; test = true;

View File

@ -45,9 +45,12 @@
#include <list> #include <list>
#include <string> #include <string>
#include <map>
#include "vrml2_node.h" #include "vrml2_node.h"
class SGNODE;
class WRL2INLINE;
/** /**
* Class WRL2BASE * Class WRL2BASE
@ -56,6 +59,8 @@
class WRL2BASE : public WRL2NODE class WRL2BASE : public WRL2NODE
{ {
private: private:
bool m_useInline;
// handle cases of USE / DEF // handle cases of USE / DEF
bool implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); bool implementUse( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); bool implementDef( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
@ -69,6 +74,9 @@ private:
bool readNorms( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); bool readNorms( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); bool readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode ); bool readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
std::map< std::string, WRL2INLINE* > m_inlineModels;
public: public:
@ -79,6 +87,15 @@ public:
WRL2BASE(); WRL2BASE();
virtual ~WRL2BASE(); virtual ~WRL2BASE();
// function to enable/disable Inline{} expansion
void SetEnableInline( bool enable );
bool GetEnableInline( void );
// functions to manipulate Inline{} objects
SGNODE* AddInlineData( const std::string& aName, WRL2INLINE* aObject );
SGNODE* GetInlineData( const std::string& aName, WRL2INLINE* aObject );
void DelInlineData( const std::string& aName, WRL2INLINE* aObject );
// function to read entire VRML file // function to read entire VRML file
bool Read( WRLPROC& proc ); bool Read( WRLPROC& proc );

View File

@ -228,10 +228,18 @@ SGNODE* WRL2BOX::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;

View File

@ -578,10 +578,18 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;

View File

@ -305,10 +305,18 @@ SGNODE* WRL2MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;

View File

@ -235,10 +235,11 @@ bool WRL2NODE::SetName( const std::string& aName )
return false; return false;
} }
// XXX: NOTE: in VRML2 the '-' is invalid; however there are some bad models which contain '-' in // The characters '+' and '-' are not allowed in names as per the VRML2 specification;
// a name and many VRML parsers seem to accept them. In VRML1 the '-' is allowed. // however many parsers accept them and many bad generators use them so the rules
// have been relaxed here.
// #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F" // #define BAD_CHARS1 "\"\'#+,-.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
#define BAD_CHARS1 "\"\'#+,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F" #define BAD_CHARS1 "\"\'#,.\\[]{}\x00\x01\x02\x03\x04\x05\x06\x09\x0A\x0B\x0C\x0D\x0E\x0F"
#define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" #define BAD_CHARS2 "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
if( std::string::npos != aName.find_first_of( BAD_CHARS1 ) if( std::string::npos != aName.find_first_of( BAD_CHARS1 )
@ -396,6 +397,8 @@ bool WRL2NODE::AddRefNode( WRL2NODE* aNode )
{ {
if( *sR == aNode ) if( *sR == aNode )
return false; return false;
++sR;
} }
m_Refs.push_back( aNode ); m_Refs.push_back( aNode );

View File

@ -65,9 +65,13 @@ WRL2SHAPE::~WRL2SHAPE()
bool WRL2SHAPE::isDangling( void ) bool WRL2SHAPE::isDangling( void )
{ {
// this node is dangling unless it has a parent of type WRL2_TRANSFORM // this node is dangling unless it has a parent of type:
// WRL2_TRANSFORM
// WRL2_SWITCH
if( NULL == m_Parent || m_Parent->GetNodeType() != WRL2_TRANSFORM ) if( NULL == m_Parent
|| ( m_Parent->GetNodeType() != WRL2_TRANSFORM
&& m_Parent->GetNodeType() != WRL2_SWITCH ) )
return true; return true;
return false; return false;
@ -332,10 +336,18 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;

View File

@ -0,0 +1,324 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <iostream>
#include "vrml2_base.h"
#include "vrml2_switch.h"
#include "plugins/3dapi/ifsg_all.h"
WRL2SWITCH::WRL2SWITCH() : WRL2NODE()
{
m_Type = WRL2_SWITCH;
whichChoice = -1;
return;
}
WRL2SWITCH::WRL2SWITCH( WRL2NODE* aParent ) : WRL2NODE()
{
m_Type = WRL2_SWITCH;
m_Parent = aParent;
whichChoice = -1;
if( NULL != m_Parent )
m_Parent->AddChildNode( this );
return;
}
WRL2SWITCH::~WRL2SWITCH()
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Destroying Transform with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
return;
}
bool WRL2SWITCH::isDangling( void )
{
// a Switch node is never dangling
return false;
}
// functions inherited from WRL2NODE
bool WRL2SWITCH::Read( WRLPROC& proc, WRL2BASE* aTopNode )
{
/*
* Structure of a Switch node (p.113):
*
* Switch {
* exposedField MFNode choice []
* exposedField SFInt32 whichChoice -1
* }
*/
if( NULL == aTopNode )
{
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] aTopNode is NULL\n";
#endif
return false;
}
size_t line, column;
proc.GetFilePosData( line, column );
char tok = proc.Peek();
if( proc.eof() )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad file format; unexpected eof at line ";
std::cerr << line << ", column " << column << "\n";
#endif
return false;
}
if( '{' != tok )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << proc.GetError() << "\n";
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad file format; expecting '{' but got '" << tok;
std::cerr << "' at line " << line << ", column " << column << "\n";
#endif
return false;
}
proc.Pop();
std::string glob;
while( true )
{
if( proc.Peek() == '}' )
{
proc.Pop();
break;
}
if( !proc.ReadName( glob ) )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << proc.GetError() << "\n";
#endif
return false;
}
// expecting one of:
// choice
// whichChoice
proc.GetFilePosData( line, column );
if( !glob.compare( "whichChoice" ) )
{
if( !proc.ReadSFInt( whichChoice ) )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid whichChoice at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
std::cerr << " * [INFO] message: '" << proc.GetError() << "'\n";
#endif
return false;
}
}
else if( !glob.compare( "choice" ) )
{
if( !readChildren( proc, aTopNode ) )
return false;
}
else
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad Switch at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
#endif
return false;
}
} // while( true ) -- reading contents of Switch{}
return true;
}
bool WRL2SWITCH::AddRefNode( WRL2NODE* aNode )
{
if( NULL == aNode )
{
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] NULL passed as node pointer\n";
#endif
return false;
}
if( !WRL2NODE::AddRefNode( aNode ) )
return false;
// take possession if the node is dangling WRL2_SHAPE
if( WRL2_SHAPE == aNode->GetNodeType() && aNode->isDangling() )
{
WRL2NODE* np = aNode->GetParent();
if( NULL != np )
aNode->SetParent( this );
}
return true;
}
bool WRL2SWITCH::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
{
size_t line, column;
proc.GetFilePosData( line, column );
char tok = proc.Peek();
if( proc.eof() )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad file format; unexpected eof at line ";
std::cerr << line << ", column " << column << "\n";
#endif
return false;
}
WRL2NODE* child = NULL;
if( '[' != tok )
{
// since there are no delimeters we expect a single child
if( !aTopNode->ReadNode( proc, this, &child ) )
return false;
if( NULL != child )
choices.push_back( child );
if( proc.Peek() == ',' )
proc.Pop();
return true;
}
proc.Pop();
std::string glob;
while( true )
{
if( proc.Peek() == ']' )
{
proc.Pop();
break;
}
if( !aTopNode->ReadNode( proc, this, &child ) )
return false;
if( NULL != child )
choices.push_back( child );
if( proc.Peek() == ',' )
proc.Pop();
}
return true;
}
SGNODE* WRL2SWITCH::TranslateToSG( SGNODE* aParent, bool calcNormals )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating Switch with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
if( choices.empty() )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Switch translation: no choices\n";
#endif
return NULL;
}
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
{
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Transform does not have a Transform parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
return NULL;
}
if( whichChoice < 0 || whichChoice >= (int)choices.size() )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Switch translation: no choice (choices = ";
std::cerr << choices.size() << "), whichChoice = " << whichChoice << "\n";
#endif
return NULL;
}
WRL2NODES type = choices[whichChoice]->GetNodeType();
switch( type )
{
case WRL2_SHAPE:
case WRL2_SWITCH:
case WRL2_INLINE:
case WRL2_TRANSFORM:
break;
default:
return NULL;
}
return choices[whichChoice]->TranslateToSG( aParent, calcNormals );
}

View File

@ -0,0 +1,64 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015-2016 Cirilo Bernardo <cirilo.bernardo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file vrml2_switch.h
*/
#ifndef VRML2_SWITCH_H
#define VRML2_SWITCH_H
#include "vrml2_node.h"
class WRL2BASE;
class SGNODE;
/**
* Class WRL2SWITCH
*/
class WRL2SWITCH : public WRL2NODE
{
private:
int whichChoice;
std::vector< WRL2NODE* > choices;
bool readChildren( WRLPROC& proc, WRL2BASE* aTopNode );
public:
// functions inherited from WRL2NODE
bool isDangling( void );
public:
WRL2SWITCH();
WRL2SWITCH( WRL2NODE* aNode );
virtual ~WRL2SWITCH();
// functions inherited from WRL2NODE
bool Read( WRLPROC& proc, WRL2BASE* aTopNode );
bool AddRefNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
};
#endif // VRML2_SWITCH_H

View File

@ -314,6 +314,9 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
if( !aTopNode->ReadNode( proc, this, NULL ) ) if( !aTopNode->ReadNode( proc, this, NULL ) )
return false; return false;
if( proc.Peek() == ',' )
proc.Pop();
return true; return true;
} }
@ -330,6 +333,10 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
if( !aTopNode->ReadNode( proc, this, NULL ) ) if( !aTopNode->ReadNode( proc, this, NULL ) )
return false; return false;
if( proc.Peek() == ',' )
proc.Pop();
} }
return true; return true;
@ -338,6 +345,12 @@ bool WRL2TRANSFORM::readChildren( WRLPROC& proc, WRL2BASE* aTopNode )
SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals ) SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
{ {
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating Transform with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
if( m_Children.empty() && m_Refs.empty() ) if( m_Children.empty() && m_Refs.empty() )
return NULL; return NULL;
@ -356,10 +369,18 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent && aParent != S3D::GetSGNodeParent( m_sgNode ) if( NULL != aParent )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{ {
return NULL; if( NULL == S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeChild( aParent, m_sgNode ) )
{
return NULL;
}
else if( aParent != S3D::GetSGNodeParent( m_sgNode )
&& !S3D::AddSGNodeRef( aParent, m_sgNode ) )
{
return NULL;
}
} }
return m_sgNode; return m_sgNode;
@ -371,7 +392,11 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
std::list< WRL2NODE* >::iterator eC = m_Children.end(); std::list< WRL2NODE* >::iterator eC = m_Children.end();
WRL2NODES type; WRL2NODES type;
// Include only Shape and Transform nodes in a Transform node // Include only the following in a Transform node:
// Shape
// Switch
// Transform
// Inline
bool test = false; // set to true if there are any subnodes for display bool test = false; // set to true if there are any subnodes for display
for( int i = 0; i < 2; ++i ) for( int i = 0; i < 2; ++i )
@ -383,6 +408,8 @@ SGNODE* WRL2TRANSFORM::TranslateToSG( SGNODE* aParent, bool calcNormals )
switch( type ) switch( type )
{ {
case WRL2_SHAPE: case WRL2_SHAPE:
case WRL2_SWITCH:
case WRL2_INLINE:
case WRL2_TRANSFORM: case WRL2_TRANSFORM:
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) ) if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )

View File

@ -197,6 +197,9 @@ SCENEGRAPH* Load( char const* aFileName )
#endif #endif
WRL2BASE* bp = new WRL2BASE; WRL2BASE* bp = new WRL2BASE;
// allow Inline{} files to be included
bp->SetEnableInline( true );
if( !bp->Read( proc ) ) if( !bp->Read( proc ) )
{ {
#ifdef DEBUG #ifdef DEBUG

View File

@ -113,9 +113,10 @@ bool WRLPROC::Open( const std::string& aFileName )
// backslash // backslash
// XXX: NOTE: badchars should include '-' but due to my bad model naming scheme // XXX: NOTE: badchars should include '-' but due to my bad model naming scheme
// in the VRML model generator, I have allowed '-'. Other VRML parsers seem to // in the VRML model generator, I have allowed '-'. Other VRML parsers seem to
// accept '-'. // accept '-'. FreeCAD produces names with '+' in them so '+' has been allowed
// as well; '+' is not even valid for VRML1.
//m_badchars = "'\"#,.+-[]\\{}"; //m_badchars = "'\"#,.+-[]\\{}";
m_badchars = "'\"#,.+[]\\{}"; m_badchars = "'\"#,.[]\\{}";
return true; return true;
} }
@ -305,7 +306,8 @@ bool WRLPROC::ReadName( std::string& aName )
while( m_buf[m_linepos] > 0x20 && m_linepos < ssize ) while( m_buf[m_linepos] > 0x20 && m_linepos < ssize )
{ {
if( '[' == m_buf[m_linepos] || '{' == m_buf[m_linepos] if( '[' == m_buf[m_linepos] || '{' == m_buf[m_linepos]
|| '.' == m_buf[m_linepos] || '#' == m_buf[m_linepos] ) || '.' == m_buf[m_linepos] || '#' == m_buf[m_linepos]
|| ',' == m_buf[m_linepos] )
{ {
if( !aName.empty() ) if( !aName.empty() )
{ {