Work on SG consistency checks: fixed a number of bugs and improved integrity checking when writing cache files

This commit is contained in:
Cirilo Bernardo 2016-03-14 12:30:59 +11:00
parent 0085d1aea7
commit 30f9aba7c9
11 changed files with 197 additions and 26 deletions

View File

@ -363,7 +363,13 @@ bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -406,7 +412,34 @@ bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
S3D::WriteVector( aFile, scale_axis ); S3D::WriteVector( aFile, scale_axis );
aFile.write( (char*)&scale_angle, sizeof( scale_angle ) ); aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
size_t asize = m_Transforms.size(); // Transfer ownership of any Transform references which hadn't been written
size_t asize = m_RTransforms.size();
size_t i;
for( i = 0; i < asize; ++i )
{
if( !m_RTransforms[i]->isWritten() )
{
m_RTransforms[i]->SwapParent( this );
--asize;
--i;
}
}
// Transfer ownership of any Shape references which hadn't been written
asize = m_RShape.size();
for( i = 0; i < asize; ++i )
{
if( !m_RShape[i]->isWritten() )
{
m_RShape[i]->SwapParent( this );
--asize;
--i;
}
}
asize = m_Transforms.size();
aFile.write( (char*)&asize, sizeof( size_t ) ); aFile.write( (char*)&asize, sizeof( size_t ) );
asize = m_RTransforms.size(); asize = m_RTransforms.size();
aFile.write( (char*)&asize, sizeof( size_t ) ); aFile.write( (char*)&asize, sizeof( size_t ) );
@ -414,8 +447,6 @@ bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
aFile.write( (char*)&asize, sizeof( size_t ) ); aFile.write( (char*)&asize, sizeof( size_t ) );
asize = m_RShape.size(); asize = m_RShape.size();
aFile.write( (char*)&asize, sizeof( size_t ) ); aFile.write( (char*)&asize, sizeof( size_t ) );
size_t i;
asize = m_Transforms.size(); asize = m_Transforms.size();
// write child transforms // write child transforms
@ -464,6 +495,7 @@ bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }
@ -550,7 +582,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data while reading transform '"; ostr << " * [INFO] corrupt data while reading transform '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif
@ -582,7 +614,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data: cannot find ref transform '"; ostr << " * [INFO] corrupt data: cannot find ref transform '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif
@ -595,7 +627,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data: type is not TRANSFORM '"; ostr << " * [INFO] corrupt data: type is not TRANSFORM '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif
@ -630,7 +662,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data while reading shape '"; ostr << " * [INFO] corrupt data while reading shape '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif
@ -662,7 +694,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data: cannot find ref shape '"; ostr << " * [INFO] corrupt data: cannot find ref shape '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif
@ -675,7 +707,7 @@ bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [INFO] corrupt data: type is not SGSHAPE '"; ostr << " * [INFO] corrupt data: type is not SGSHAPE '";
ostr << name << "'"; ostr << name << "' pos " << aFile.tellg();
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif

View File

@ -387,7 +387,13 @@ bool SGAPPEARANCE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -425,6 +431,7 @@ bool SGAPPEARANCE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -286,7 +286,13 @@ bool SGCOLORS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -323,6 +329,7 @@ bool SGCOLORS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -293,7 +293,13 @@ bool SGCOORDS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -330,6 +336,7 @@ bool SGCOORDS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -239,18 +239,21 @@ void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild )
{ {
if( aNode == m_RColors ) if( aNode == m_RColors )
{ {
delNodeRef( this );
m_RColors = NULL; m_RColors = NULL;
return; return;
} }
if( aNode == m_RCoords ) if( aNode == m_RCoords )
{ {
delNodeRef( this );
m_RCoords = NULL; m_RCoords = NULL;
return; return;
} }
if( aNode == m_RNormals ) if( aNode == m_RNormals )
{ {
delNodeRef( this );
m_RNormals = NULL; m_RNormals = NULL;
return; return;
} }
@ -558,7 +561,13 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -585,6 +594,16 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
return false; return false;
} }
// check if any references are unwritten and swap parents if so
if( NULL != m_RCoords && !m_RCoords->isWritten() )
m_RCoords->SwapParent( this );
if( NULL != m_RNormals && !m_RNormals->isWritten() )
m_RNormals->SwapParent( this );
if( NULL != m_RColors && !m_RColors->isWritten() )
m_RColors->SwapParent( this );
aFile << "[" << GetName() << "]"; aFile << "[" << GetName() << "]";
#define NITEMS 7 #define NITEMS 7
bool items[NITEMS]; bool items[NITEMS];
@ -648,6 +667,7 @@ bool SGFACESET::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -84,17 +84,25 @@ class SGCOORDINDEX;
oSL = &aOwnedList; \ oSL = &aOwnedList; \
sL = aOwnedList.begin(); \ sL = aOwnedList.begin(); \
eL = aOwnedList.end(); \ eL = aOwnedList.end(); \
while( sL != eL ) { \
if( (SGNODE*)*sL == aNode ) { \
oSL->erase( sL ); \
return; \
} \
++sL; \
} \
} else { \ } else { \
oSL = &aRefList; \ oSL = &aRefList; \
sL = aRefList.begin(); \ sL = aRefList.begin(); \
eL = aRefList.end(); \ eL = aRefList.end(); \
} \ while( sL != eL ) { \
while( sL != eL ) { \ if( (SGNODE*)*sL == aNode ) { \
if( (SGNODE*)*sL == aNode ) { \ delNodeRef( this ); \
oSL->erase( sL ); \ oSL->erase( sL ); \
return; \ return; \
} \
++sL; \
} \ } \
++sL; \
} \ } \
return; \ return; \
} } while( 0 ) } } while( 0 )

View File

@ -316,7 +316,13 @@ bool SGINDEX::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -353,6 +359,7 @@ bool SGINDEX::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -117,6 +117,36 @@ SGNODE* SGNODE::GetParent( void ) const
} }
bool SGNODE::SwapParent( SGNODE* aNewParent )
{
if( aNewParent == m_Parent )
return true;
if( NULL == aNewParent )
return false;
if( NULL == m_Parent )
{
if( aNewParent->AddChildNode( this ) )
return true;
return false;
}
if( aNewParent->GetNodeType() != m_Parent->GetNodeType() )
return false;
SGNODE* oldParent = m_Parent;
m_Parent->unlinkChildNode( this );
m_Parent = NULL;
aNewParent->unlinkRefNode( this );
aNewParent->AddChildNode( this );
oldParent->AddRefNode( this );
return true;
}
const char* SGNODE::GetName( void ) const char* SGNODE::GetName( void )
{ {
if( m_Name.empty() ) if( m_Name.empty() )
@ -145,6 +175,9 @@ const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
void SGNODE::addNodeRef( SGNODE* aNode ) void SGNODE::addNodeRef( SGNODE* aNode )
{ {
if( NULL == aNode )
return;
std::list< SGNODE* >::iterator np = std::list< SGNODE* >::iterator np =
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode ); std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
@ -156,8 +189,11 @@ void SGNODE::addNodeRef( SGNODE* aNode )
} }
void SGNODE::delNodeRef( SGNODE* aNode ) void SGNODE::delNodeRef( const SGNODE* aNode )
{ {
if( NULL == aNode )
return;
std::list< SGNODE* >::iterator np = std::list< SGNODE* >::iterator np =
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode ); std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
@ -170,7 +206,9 @@ void SGNODE::delNodeRef( SGNODE* aNode )
#ifdef DEBUG #ifdef DEBUG
std::ostringstream ostr; std::ostringstream ostr;
ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
ostr << " * [BUG] delNodeRef() did not find its target"; ostr << " * [BUG] delNodeRef() did not find its target\n";
ostr << " * This Node Type: " << m_SGtype << ", Referenced node type: ";
ostr << aNode->GetNodeType() << "\n";
wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() ); wxLogTrace( MASK_3D_SG, "%s\n", ostr.str().c_str() );
#endif #endif

View File

@ -120,7 +120,17 @@ public:
* *
* @param aNode is the node holding a reference to this object * @param aNode is the node holding a reference to this object
*/ */
void delNodeRef( SGNODE* aNode ); void delNodeRef( const SGNODE* aNode );
/**
* Function IsWritten
* returns true if the object had already been written to a
* cache file or VRML file; for internal use only.
*/
bool isWritten( void )
{
return m_written;
}
public: public:
SGNODE( SGNODE* aParent ); SGNODE( SGNODE* aParent );
@ -150,6 +160,17 @@ public:
*/ */
virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0; virtual bool SetParent( SGNODE* aParent, bool notify = true ) = 0;
/**
* Function SwapParent
* swaps the ownership with the given parent. This operation
* may be required when reordering nodes for optimization.
*
* @param aNewParent [in] will become the new parent to the
* object; it must be the same type as the parent of this
* instance.
*/
bool SwapParent( SGNODE* aNewParent );
const char* GetName( void ); const char* GetName( void );
void SetName(const char *aName); void SetName(const char *aName);

View File

@ -285,7 +285,13 @@ bool SGNORMALS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -322,6 +328,7 @@ bool SGNORMALS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }

View File

@ -191,13 +191,16 @@ void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
{ {
if( aNode == m_RAppearance ) if( aNode == m_RAppearance )
{ {
delNodeRef( this );
m_RAppearance = NULL; m_RAppearance = NULL;
return; return;
} }
if( aNode == m_RFaceSet ) if( aNode == m_RFaceSet )
{ {
delNodeRef( this );
m_RFaceSet = NULL; m_RFaceSet = NULL;
return;
} }
} }
@ -421,7 +424,13 @@ bool SGSHAPE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
while( NULL != np->GetParent() ) while( NULL != np->GetParent() )
np = np->GetParent(); np = np->GetParent();
return np->WriteCache( aFile, NULL ); if( np->WriteCache( aFile, NULL ) )
{
m_written = true;
return true;
}
return false;
} }
if( parentNode != m_Parent ) if( parentNode != m_Parent )
@ -448,6 +457,13 @@ bool SGSHAPE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
return false; return false;
} }
// check if any references are unwritten and swap parents if so
if( NULL != m_RAppearance && !m_RAppearance->isWritten() )
m_RAppearance->SwapParent(this);
if( NULL != m_RFaceSet && !m_RFaceSet->isWritten() )
m_RFaceSet->SwapParent( this );
aFile << "[" << GetName() << "]"; aFile << "[" << GetName() << "]";
#define NITEMS 4 #define NITEMS 4
bool items[NITEMS]; bool items[NITEMS];
@ -490,6 +506,7 @@ bool SGSHAPE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
if( aFile.fail() ) if( aFile.fail() )
return false; return false;
m_written = true;
return true; return true;
} }