Added support for VRML2 Inline{}

This commit is contained in:
Cirilo Bernardo 2016-02-22 19:59:07 +11:00
parent af0ac955b9
commit 684e41358a
6 changed files with 446 additions and 30 deletions

View File

@ -22,6 +22,9 @@
*/
#include <iostream>
#include <utility>
#include <wx/string.h>
#include <wx/filename.h>
#include "vrml2_base.h"
#include "vrml2_transform.h"
@ -36,9 +39,12 @@
#include "vrml2_color.h"
#include "vrml2_box.h"
#include "vrml2_switch.h"
#include "vrml2_inline.h"
#include "plugins/3dapi/ifsg_all.h"
SCENEGRAPH* LoadVRML( const wxString& aFileName, bool useInline );
WRL2BASE::WRL2BASE() : WRL2NODE()
{
m_useInline = false;
@ -49,6 +55,22 @@ WRL2BASE::WRL2BASE() : WRL2NODE()
WRL2BASE::~WRL2BASE()
{
std::map< std::string, SGNODE* >::iterator iS = m_inlineModels.begin();
std::map< std::string, SGNODE* >::iterator eS = m_inlineModels.end();
while( iS != eS )
{
SGNODE* np = iS->second;
// destroy any orphaned Inline{} node data
if( np && NULL == S3D::GetSGNodeParent( np ) )
S3D::DestroyNode( np );
++iS;
}
m_inlineModels.clear();
return;
}
@ -78,28 +100,50 @@ bool WRL2BASE::GetEnableInline( void )
}
SGNODE* WRL2BASE::AddInlineData( const std::string& aName, WRL2INLINE* aObject )
SGNODE* WRL2BASE::GetInlineData( const std::string& aName )
{
std::map< std::string, WRL2INLINE* >::iterator dp = m_inlineModels.find( aName );
// XXX;
// qwerty;
if( aName.empty() )
return NULL;
}
std::map< std::string, SGNODE* >::iterator dp = m_inlineModels.find( aName );
SGNODE* WRL2BASE::GetInlineData( const std::string& aName, WRL2INLINE* aObject )
{
// XXX;
// qwerty;
if( dp != m_inlineModels.end() )
return dp->second;
wxString tname;
if( aName.find( "file://", 0, 7 ) == 0 )
{
if( aName.length() <= 7 )
return NULL;
}
tname = wxString::FromUTF8Unchecked( aName.substr( 7 ).c_str() );
}
else
{
tname = wxString::FromUTF8Unchecked( aName.c_str() );
}
void WRL2BASE::DelInlineData( const std::string& aName, WRL2INLINE* aObject )
{
// XXX;
// qwerty;
return;
wxFileName fn;
fn.Assign( tname );
if( !fn.Normalize() )
{
m_inlineModels.insert( std::pair< std::string, SGNODE* >( aName, NULL ) );
return NULL;
}
SCENEGRAPH* sp = LoadVRML( fn.GetFullPath(), false );
if( NULL == sp )
{
m_inlineModels.insert( std::pair< std::string, SGNODE* >( aName, NULL ) );
return NULL;
}
m_inlineModels.insert( std::pair< std::string, SGNODE* >( aName, (SGNODE*)sp ) );
return (SGNODE*)sp;
}
@ -587,6 +631,13 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
break;
case WRL2_INLINE:
if( !readInline( proc, aParent, aNode ) )
return false;
break;
//
// items not implemented or for optional future implementation:
//
@ -602,7 +653,6 @@ bool WRL2BASE::ReadNode( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
case WRL2_FOG:
case WRL2_FONTSTYLE:
case WRL2_IMAGETEXTURE:
case WRL2_INLINE:
case WRL2_LOD:
case WRL2_MOVIETEXTURE:
case WRL2_NAVIGATIONINFO:
@ -910,6 +960,47 @@ bool WRL2BASE::readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
}
bool WRL2BASE::readInline( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode )
{
if( NULL != aNode )
*aNode = NULL;
if( !m_useInline )
{
size_t line = 0;
size_t column = 0;
proc.GetFilePosData( line, column );
if( !proc.DiscardNode() )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << proc.GetError() << "\n";
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] could not discard Inline node at line " << line;
std::cerr << ", column " << column << "\n";
#endif
return false;
}
return true;
}
WRL2INLINE* np = new WRL2INLINE( aParent );
if( !np->Read( proc, this ) )
{
delete np;
return false;
}
if( NULL != aNode )
*aNode = (WRL2NODE*) np;
return true;
}
SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent )
{
if( m_Children.empty() )
@ -980,6 +1071,7 @@ SGNODE* WRL2BASE::TranslateToSG( SGNODE* aParent )
case WRL2_TRANSFORM:
case WRL2_SWITCH:
case WRL2_INLINE:
if( NULL != (*sC)->TranslateToSG( topNode.GetRawPtr() ) )
test = true;

View File

@ -77,8 +77,9 @@ private:
bool readColor( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readBox( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readSwitch( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
bool readInline( WRLPROC& proc, WRL2NODE* aParent, WRL2NODE** aNode );
std::map< std::string, WRL2INLINE* > m_inlineModels;
std::map< std::string, SGNODE* > m_inlineModels;
public:
@ -94,9 +95,7 @@ public:
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 );
SGNODE* GetInlineData( const std::string& aName );
// function to read entire VRML file
bool Read( WRLPROC& proc );

View File

@ -0,0 +1,257 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 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_inline.h"
#include "vrml2_base.h"
#include "plugins/3dapi/ifsg_all.h"
WRL2INLINE::WRL2INLINE() : WRL2NODE()
{
m_Type = WRL2_INLINE;
m_Parent = NULL;
return;
}
WRL2INLINE::WRL2INLINE( WRL2NODE* aParent ) : WRL2NODE()
{
m_Type = WRL2_INLINE;
m_Parent = aParent;
if( NULL != m_Parent )
m_Parent->AddChildNode( this );
return;
}
WRL2INLINE::~WRL2INLINE()
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 2 )
std::cerr << " * [INFO] Destroying Inline node\n";
#endif
return;
}
bool WRL2INLINE::isDangling( void )
{
// this node is never dangling
return false;
}
bool WRL2INLINE::Read( WRLPROC& proc, WRL2BASE* aTopNode )
{
if( aTopNode == NULL || aTopNode->GetNodeType() != WRL2_BASE )
return false;
m_VRML2Base = 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;
}
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();
while( ( tok = proc.Peek() ) )
{
std::string glob;
if( tok == '}' )
{
proc.Pop();
return true;
}
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;
}
proc.GetFilePosData( line, column );
// expecting one of 'url', 'bboxCenter', 'bboxSize'
if( !glob.compare( "url" ) )
{
if( !proc.ReadMFString( url ) )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid url 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( "bboxCenter" ) )
{
if( !proc.ReadSFVec3f( bboxCenter ) )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid bboxCenter 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( "bboxSize" ) )
{
if( !proc.ReadSFVec3f( bboxSize ) )
{
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] invalid bboxSize 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 defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad Inline at line " << line << ", column ";
std::cerr << column << "\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
#endif
return false;
}
}
proc.GetFilePosData( line, column );
#if defined( DEBUG_VRML2 ) && ( DEBUG_VRML2 > 1 )
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [INFO] bad Inline at line " << line << ", column ";
std::cerr << column << " (no closing brace)\n";
std::cerr << " * [INFO] file: '" << proc.GetFileName() << "'\n";
#endif
return false;
}
bool WRL2INLINE::AddRefNode( WRL2NODE* aNode )
{
// this node may not own or reference any other node
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] AddRefNode is not applicable\n";
#endif
return false;
}
bool WRL2INLINE::AddChildNode( WRL2NODE* aNode )
{
// this node may not own or reference any other node
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] AddChildNode is not applicable\n";
#endif
return false;
}
SGNODE* WRL2INLINE::TranslateToSG( SGNODE* aParent )
{
if( NULL == aParent || NULL == m_VRML2Base )
return NULL;
if( url.empty() )
return NULL;
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
if( ptype != S3D::SGTYPE_TRANSFORM )
{
#ifdef DEBUG_VRML2
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
std::cerr << " * [BUG] Inline does not have a Transform parent (parent ID: ";
std::cerr << ptype << ")\n";
#endif
return NULL;
}
SGNODE* np = m_VRML2Base->GetInlineData( url.front() );
if( NULL == np )
return NULL;
bool OK = false;
if( NULL == S3D::GetSGNodeParent( np ) )
OK = S3D::AddSGNodeChild( aParent, np );
else
OK = S3D::AddSGNodeRef( aParent, np );
if( !OK )
return NULL;
return np;
}

View File

@ -0,0 +1,65 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 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_inline.h
*/
#ifndef VRML2_INLINE_H
#define VRML2_INLINE_H
#include "vrml2_node.h"
class WRL2BASE;
class SGNODE;
/**
* Class WRL2INLINE
*/
class WRL2INLINE : public WRL2NODE
{
private:
WRL2BASE* m_VRML2Base;
std::vector< std::string > url;
WRLVEC3F bboxCenter;
WRLVEC3F bboxSize;
public:
// functions inherited from WRL2NODE
bool isDangling( void );
public:
WRL2INLINE();
WRL2INLINE( WRL2NODE* aParent );
virtual ~WRL2INLINE();
// functions inherited from WRL2NODE
bool Read( WRLPROC& proc, WRL2BASE* aTopNode );
bool AddRefNode( WRL2NODE* aNode );
bool AddChildNode( WRL2NODE* aNode );
SGNODE* TranslateToSG( SGNODE* aParent );
};
#endif // VRML2_INLINE_H

View File

@ -48,9 +48,9 @@
#define PLUGIN_VRML_MAJOR 1
#define PLUGIN_VRML_MINOR 2
#define PLUGIN_VRML_MINOR 3
#define PLUGIN_VRML_PATCH 0
#define PLUGIN_VRML_REVNO 1
#define PLUGIN_VRML_REVNO 0
const char* GetKicadPluginName( void )
@ -175,7 +175,7 @@ public:
};
SCENEGRAPH* LoadVRML( const wxString& aFileName )
SCENEGRAPH* LoadVRML( const wxString& aFileName, bool useInline )
{
FILE_LINE_READER* modelFile = NULL;
SCENEGRAPH* scene = NULL;
@ -206,8 +206,8 @@ SCENEGRAPH* LoadVRML( const wxString& aFileName )
WRL1BASE* bp = new WRL1BASE;
// allow Inline{} files to be included
bp->SetEnableInline( true );
// allow or ignore Inline{} files
bp->SetEnableInline( useInline );
if( !bp->Read( proc ) )
{
@ -310,7 +310,7 @@ SCENEGRAPH* Load( char const* aFileName )
if( ext == "x3d" || ext == "X3D" )
scene = LoadX3D( fname );
else
scene = LoadVRML( fname );
scene = LoadVRML( fname, true );
return scene;
}

View File

@ -687,14 +687,17 @@ bool WRLPROC::ReadString( std::string& aSFString )
continue;
}
if( '"' == m_buf[m_bufpos] )
else if( '"' == m_buf[m_bufpos] )
{
if( isesc )
aSFString.append( 1, '"' );
else
break;
}
else
{
aSFString.append( 1, m_buf[m_bufpos] );
}
// ensure that the backslash escape cannot extend beyond the first character
isesc = false;