Improving VRML1/2 parsers

This commit is contained in:
Cirilo Bernardo 2016-01-07 15:43:32 +11:00
parent 8a9eb3bbe8
commit 7dd4bd9f09
13 changed files with 192 additions and 48 deletions

View File

@ -4,7 +4,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/v2 ${CMAKE_CURRENT_SOURCE_DIR}/v2
) )
add_definitions( -DDEBUG_VRML1=2 -DDEBUG_VRML2=2 ) add_definitions( -DDEBUG_VRML1=3 -DDEBUG_VRML2=3 )
add_library( s3d_plugin_vrml MODULE add_library( s3d_plugin_vrml MODULE
vrml.cpp vrml.cpp

View File

@ -44,9 +44,11 @@ WRL1BASE::WRL1BASE() : WRL1NODE( NULL )
WRL1BASE::~WRL1BASE() WRL1BASE::~WRL1BASE()
{ {
if( m_dictionary ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
delete m_dictionary; std::cerr << " * [INFO] Destroying virtual base node\n";
#endif
cancelDict();
return; return;
} }
@ -474,7 +476,8 @@ bool WRL1BASE::ReadNode( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
else else
{ {
std::cerr << " * [INFO] discarded node (currently unsupported)\n"; std::cerr << " * [INFO] discarded node '" << glob << "' at line ";
std::cerr << line << ", col " << column << " (currently unsupported)\n";
} }
#endif #endif

View File

@ -62,8 +62,17 @@ WRL1MATERIAL::~WRL1MATERIAL()
// destroy any orphaned color nodes // destroy any orphaned color nodes
for( int i = 0; i < 2; ++i ) for( int i = 0; i < 2; ++i )
{ {
if( NULL != colors[i] && NULL == S3D::GetSGNodeParent( colors[i] ) ) if( NULL != colors[i] )
{
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] Destroying SGCOLOR #" << i << "\n";
#endif
if( NULL == S3D::GetSGNodeParent( colors[i] ) )
S3D::DestroyNode( colors[i] ); S3D::DestroyNode( colors[i] );
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] destroyed SGCOLOR #" << i << "\n";
#endif
}
} }
return; return;

View File

@ -84,6 +84,7 @@ typedef std::pair< std::string, WRL1NODES > NODEITEM;
typedef std::map< std::string, WRL1NODES > NODEMAP; typedef std::map< std::string, WRL1NODES > NODEMAP;
static NODEMAP nodenames; static NODEMAP nodenames;
std::string WRL1NODE::tabs = "";
WRL1NODE::WRL1NODE( NAMEREGISTER* aDictionary ) WRL1NODE::WRL1NODE( NAMEREGISTER* aDictionary )
{ {
@ -136,8 +137,17 @@ WRL1NODE::WRL1NODE( NAMEREGISTER* aDictionary )
WRL1NODE::~WRL1NODE() WRL1NODE::~WRL1NODE()
{ {
if( m_dictionary && !m_Name.empty() ) #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
m_dictionary->DelName( m_Name, this ); std::cerr << " * [INFO] ^^ Destroying Type " << m_Type << " with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
m_Items.clear();
// XXX - the dictionary may be bad - don't use it
//if( m_dictionary && !m_Name.empty() )
// m_dictionary->DelName( m_Name, this );
if( m_Parent ) if( m_Parent )
m_Parent->unlinkChildNode( this ); m_Parent->unlinkChildNode( this );
@ -145,31 +155,100 @@ WRL1NODE::~WRL1NODE()
std::list< WRL1NODE* >::iterator sBP = m_BackPointers.begin(); std::list< WRL1NODE* >::iterator sBP = m_BackPointers.begin();
std::list< WRL1NODE* >::iterator eBP = m_BackPointers.end(); std::list< WRL1NODE* >::iterator eBP = m_BackPointers.end();
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
int acc = 0;
#endif
while( sBP != eBP ) while( sBP != eBP )
{ {
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
++acc;
std::cerr << " * [INFO] " << tabs << "Type " << m_Type << " is Unlinking ref #";
std::cerr << acc << "\n";
#endif
(*sBP)->unlinkRefNode( this ); (*sBP)->unlinkRefNode( this );
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] " << tabs << "Type " << m_Type << " has unlinked ref #";
std::cerr << acc << "\n";
#endif
++sBP; ++sBP;
} }
m_Refs.clear(); m_Refs.clear();
std::list< WRL1NODE* >::iterator sC = m_Children.begin(); std::list< WRL1NODE* >::iterator sC = m_Children.begin();
std::list< WRL1NODE* >::iterator eC = m_Children.end(); std::list< WRL1NODE* >::iterator eC = m_Children.end();
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::string otabs = tabs;
tabs.append( " " );
#endif
while( sC != eC ) while( sC != eC )
{ {
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
++acc;
std::cerr << " * [INFO] " << otabs << "Type " << m_Type << " is Deleting child #";
std::cerr << acc << "\n";
#endif
(*sC)->SetParent( NULL, false ); (*sC)->SetParent( NULL, false );
delete *sC; #if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] " << otabs << "Type " << m_Type << " has unlinked child #";
std::cerr << acc << "\n";
#endif
//delete *sC;
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
std::cerr << " * [INFO] " << otabs << "Type " << m_Type << " has deleted child #";
std::cerr << acc << "\n";
#endif
++sC; ++sC;
} }
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
tabs = otabs;
#endif
m_Children.clear(); m_Children.clear();
return; return;
} }
void WRL1NODE::cancelDict( void )
{
std::list< WRL1NODE* >::iterator sC = m_Children.begin();
std::list< WRL1NODE* >::iterator eC = m_Children.end();
while( sC != eC )
{
(*sC)->cancelDict();
++sC;
}
if( m_Type == WRL1_BASE && NULL != m_dictionary )
delete m_dictionary;
m_dictionary = NULL;
return;
}
void WRL1NODE::addNodeRef( WRL1NODE* aNode ) void WRL1NODE::addNodeRef( WRL1NODE* aNode )
{ {
// note: for VRML1 we allow even parent nodes to be held as references // the parent node must never be added as a backpointer
if( aNode == m_Parent )
return;
std::list< WRL1NODE* >::iterator sR = m_BackPointers.begin();
std::list< WRL1NODE* >::iterator eR = m_BackPointers.end();
while( sR != eR )
{
if( *sR == aNode )
return;
++sR;
}
m_BackPointers.push_back( aNode ); m_BackPointers.push_back( aNode );
return; return;
@ -346,10 +425,12 @@ bool WRL1NODE::AddChildNode( WRL1NODE* aNode )
++sC; ++sC;
} }
aNode->SetParent( this );
m_Children.push_back( aNode ); m_Children.push_back( aNode );
addItem( aNode ); addItem( aNode );
if( aNode->GetParent() != this )
aNode->SetParent( this );
return true; return true;
} }
@ -394,14 +475,13 @@ void WRL1NODE::unlinkChildNode( const WRL1NODE* aNode )
if( *sL == aNode ) if( *sL == aNode )
{ {
m_Children.erase( sL ); m_Children.erase( sL );
delItem( aNode );
return; return;
} }
++sL; ++sL;
} }
delItem( aNode );
return; return;
} }
@ -416,14 +496,13 @@ void WRL1NODE::unlinkRefNode( const WRL1NODE* aNode )
if( *sL == aNode ) if( *sL == aNode )
{ {
m_Refs.erase( sL ); m_Refs.erase( sL );
delItem( aNode );
return; return;
} }
++sL; ++sL;
} }
delItem( aNode );
return; return;
} }

View File

@ -132,6 +132,12 @@ protected:
NAMEREGISTER* m_dictionary; NAMEREGISTER* m_dictionary;
public: public:
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
static std::string tabs;
#endif
// cancel the dictionary pointer; for internal use only
void cancelDict( void );
/** /**
* Function GetCurrentSettings * Function GetCurrentSettings

View File

@ -367,6 +367,12 @@ SGNODE* WRL2APPEARANCE::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL; return NULL;
} }
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating Appearance with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent ) if( NULL != aParent )

View File

@ -634,6 +634,13 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
return false; return false;
} }
#ifdef DEBUG_VRML2
else
{
std::cerr << " * [INFO] OK: discard unsupported " << glob << " node at l";
std::cerr << line << ", c" << column << "\n";
}
#endif
break; break;
} }

View File

@ -577,6 +577,13 @@ SGNODE* WRL2FACESET::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL; return NULL;
} }
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating IndexedFaceSet with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references, ";
std::cerr << m_BackPointers.size() << " backpointers and ";
std::cerr << coordIndex.size() << " coord indices\n";
#endif
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent ) if( NULL != aParent )

View File

@ -303,6 +303,12 @@ SGNODE* WRL2MATERIAL::TranslateToSG( SGNODE* aParent, bool calcNormals )
return NULL; return NULL;
} }
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating Material with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
if( m_sgNode ) if( m_sgNode )
{ {
if( NULL != aParent ) if( NULL != aParent )

View File

@ -346,6 +346,9 @@ bool WRL2NODE::SetParent( WRL2NODE* aParent, bool doUnlink )
bool WRL2NODE::AddChildNode( WRL2NODE* aNode ) bool WRL2NODE::AddChildNode( WRL2NODE* aNode )
{ {
if( aNode == NULL )
return false;
if( aNode->GetNodeType() == WRL2_BASE ) if( aNode->GetNodeType() == WRL2_BASE )
{ {
#ifdef DEBUG_VRML2 #ifdef DEBUG_VRML2
@ -366,9 +369,11 @@ bool WRL2NODE::AddChildNode( WRL2NODE* aNode )
++sC; ++sC;
} }
aNode->SetParent( this );
m_Children.push_back( aNode ); m_Children.push_back( aNode );
if( aNode->GetParent() != this )
aNode->SetParent( this );
return true; return true;
} }

View File

@ -322,7 +322,30 @@ SGNODE* WRL2SHAPE::TranslateToSG( SGNODE* aParent, bool calcNormals )
if( NULL == geometry ) if( NULL == geometry )
return NULL; return NULL;
bool vcolors = ((WRL2FACESET*)geometry)->HasColors(); WRL2NODES geomType = geometry->GetNodeType();
switch( geomType )
{
case WRL2_INDEXEDLINESET:
case WRL2_POINTSET:
case WRL2_TEXT:
return NULL;
break;
default:
break;
}
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Translating Shape with " << m_Children.size();
std::cerr << " children, " << m_Refs.size() << " references and ";
std::cerr << m_BackPointers.size() << " backpointers\n";
#endif
bool vcolors = false;
if( WRL2_INDEXEDFACESET == geometry->GetNodeType() )
vcolors = ((WRL2FACESET*)geometry)->HasColors();
// if there is no appearance, make use of the per vertex colors if available // if there is no appearance, make use of the per vertex colors if available
if( NULL == appearance ) if( NULL == appearance )
@ -406,15 +429,11 @@ void WRL2SHAPE::unlinkChildNode( const WRL2NODE* aNode )
if( NULL == aNode ) if( NULL == aNode )
return; return;
if( aNode->GetParent() == this )
{
if( aNode == appearance ) if( aNode == appearance )
appearance = NULL; appearance = NULL;
else if( aNode == geometry ) else if( aNode == geometry )
geometry = NULL; geometry = NULL;
}
WRL2NODE::unlinkChildNode( aNode ); WRL2NODE::unlinkChildNode( aNode );
return; return;
} }
@ -425,15 +444,11 @@ void WRL2SHAPE::unlinkRefNode( const WRL2NODE* aNode )
if( NULL == aNode ) if( NULL == aNode )
return; return;
if( aNode->GetParent() != this )
{
if( aNode == appearance ) if( aNode == appearance )
appearance = NULL; appearance = NULL;
else if( aNode == geometry ) else if( aNode == geometry )
geometry = NULL; geometry = NULL;
}
WRL2NODE::unlinkRefNode( aNode ); WRL2NODE::unlinkRefNode( aNode );
return; return;
} }

View File

@ -1131,17 +1131,15 @@ bool WRLPROC::ReadSFVec3f( WRLVEC3F& aSFVec3f, bool* hasComma )
return false; return false;
} }
if( lComma && i != 2 ) // ignore any commas
if( !lComma )
{ {
std::ostringstream ostr; if( !EatSpace() )
ostr << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << "\n";
ostr << " * [INFO] failed on file '" << m_filename << "'\n";
ostr << " * [INFO] line " << fileline << ", char " << linepos << " -- ";
ostr << "line " << m_fileline << ", char " << m_linepos << "\n";
ostr << " * [INFO] comma encountered in space delimited triplet";
m_error = ostr.str();
return false; return false;
if( Peek() == ',' )
Pop();
} }
std::istringstream istr; std::istringstream istr;
@ -1680,7 +1678,10 @@ bool WRLPROC::ReadMFInt( std::vector< int >& aMFInt32 )
break; break;
if( ',' == m_buf[m_linepos] ) if( ',' == m_buf[m_linepos] )
{
lcomma = true; lcomma = true;
Pop();
}
} }
if( !EatSpace() ) if( !EatSpace() )

View File

@ -33,11 +33,11 @@
using namespace std; using namespace std;
void writeLeaded( FILE* fp, double width, double length, double height, void writeLeaded( FILE* fp, double width, double length,
double wireDia, double pitch, bool inch ); double wireDia, double pitch, bool inch );
void writeLeadless( FILE* fp, double width, double length, void writeLeadless( FILE* fp, double width, double length,
double height, double chamfer, bool inch ); double chamfer, bool inch );
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
@ -305,9 +305,9 @@ int main( int argc, char **argv )
} }
if( leaded ) if( leaded )
writeLeaded( fp, width, length, height, wireDia, pitch, inch ); writeLeaded( fp, width, length, wireDia, pitch, inch );
else else
writeLeadless( fp, width, length, height, chamfer, inch ); writeLeadless( fp, width, length, chamfer, inch );
fprintf( fp, ".END_ELECTRICAL\n" ); fprintf( fp, ".END_ELECTRICAL\n" );
fclose( fp ); fclose( fp );
@ -319,7 +319,7 @@ int main( int argc, char **argv )
void writeLeaded( FILE* fp, double width, double length, void writeLeaded( FILE* fp, double width, double length,
double height, double wireDia, double pitch, bool inch ) double wireDia, double pitch, bool inch )
{ {
if( inch ) if( inch )
{ {
@ -370,7 +370,7 @@ void writeLeaded( FILE* fp, double width, double length,
} }
void writeLeadless( FILE* fp, double width, double length, void writeLeadless( FILE* fp, double width, double length,
double height, double chamfer, bool inch ) double chamfer, bool inch )
{ {
if( chamfer < 0.001 ) if( chamfer < 0.001 )
{ {