Work in progress: VRML1 plugin
This commit is contained in:
parent
43c2c7223b
commit
79e0564622
|
@ -0,0 +1,420 @@
|
||||||
|
/*
|
||||||
|
* 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 "vrml1_base.h"
|
||||||
|
#include "vrml1_separator.h"
|
||||||
|
#include "plugins/3dapi/ifsg_all.h"
|
||||||
|
|
||||||
|
|
||||||
|
WRL1BASE::WRL1BASE() : WRL1NODE( NULL )
|
||||||
|
{
|
||||||
|
m_useInline = false;
|
||||||
|
m_Type = WRL1_BASE;
|
||||||
|
m_dictionary = new NAMEREGISTER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1BASE::~WRL1BASE()
|
||||||
|
{
|
||||||
|
if( m_dictionary )
|
||||||
|
delete m_dictionary;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// functions inherited from WRL1NODE
|
||||||
|
bool WRL1BASE::SetParent( WRL1NODE* aParent )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] attempting to set parent on WRL1BASE node\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1BASE::SetEnableInline( bool enable )
|
||||||
|
{
|
||||||
|
m_useInline = enable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::GetEnableInline( void )
|
||||||
|
{
|
||||||
|
return m_useInline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL1BASE::AddInlineData( const std::string& aName, WRL1INLINE* aObject )
|
||||||
|
{
|
||||||
|
std::map< std::string, WRL1INLINE* >::iterator dp = m_inlineModels.find( aName );
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL1BASE::GetInlineData( const std::string& aName, WRL1INLINE* aObject )
|
||||||
|
{
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1BASE::DelInlineData( const std::string& aName, WRL1INLINE* aObject )
|
||||||
|
{
|
||||||
|
// XXX;
|
||||||
|
// qwerty;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string WRL1BASE::GetName( void )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] attempting to extract name from virtual base node\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return std::string( "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::SetName( const std::string& aName )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] attempting to set name on virtual base node\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::Read( WRLPROC& proc )
|
||||||
|
{
|
||||||
|
if( proc.GetVRMLType() != VRML_V1 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] no open file or file is not a VRML2 file\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRL1NODE* node = NULL;
|
||||||
|
|
||||||
|
while( ReadNode( proc, this, &node ) && !proc.eof() );
|
||||||
|
|
||||||
|
if( proc.eof() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::implementUse( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
|
||||||
|
{
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = NULL;
|
||||||
|
|
||||||
|
if( !aParent )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invoked with NULL parent\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string glob;
|
||||||
|
|
||||||
|
if( !proc.ReadName( glob ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRL1NODE* ref = aParent->FindNode( glob );
|
||||||
|
|
||||||
|
// return 'true' - the file may be defective but it may still be somewhat OK
|
||||||
|
if( NULL == ref )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] node '" << glob << "' not found\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aParent->AddRefNode( ref ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] failed to add node '" << glob << "' (";
|
||||||
|
std::cerr << ref->GetNodeTypeName( ref->GetNodeType() ) << ") to parent of type ";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() ) << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = ref;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::implementDef( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
|
||||||
|
{
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid parent pointer (NULL)\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string glob;
|
||||||
|
WRL1NODE* lnode = NULL;
|
||||||
|
|
||||||
|
if( !proc.ReadName( glob ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t line, column;
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
if( ReadNode( proc, aParent, &lnode ) )
|
||||||
|
{
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = lnode;
|
||||||
|
|
||||||
|
if( lnode && !lnode->SetName( glob ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
size_t line, column;
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad formatting (invalid name) at line";
|
||||||
|
std::cerr << line << ", column " << column << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_dictionary )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_dictionary->AddName( glob, lnode );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::ReadNode( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
|
||||||
|
{
|
||||||
|
// This function reads a node and stores a pointer to it in aNode.
|
||||||
|
// A value 'true' is returned if a node is successfully read or,
|
||||||
|
// if the node is not supported, successfully discarded. Callers
|
||||||
|
// must always check the value of aNode when the function returns
|
||||||
|
// 'true' since it will be NULL if the node type is not supported.
|
||||||
|
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid parent pointer (NULL)\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string glob;
|
||||||
|
WRL1NODES ntype;
|
||||||
|
|
||||||
|
if( !proc.ReadName( glob ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
if( !proc.eof() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process node name:
|
||||||
|
// the names encountered at this point should be one of the
|
||||||
|
// built-in node names or one of:
|
||||||
|
// DEF, USE
|
||||||
|
if( !glob.compare( "USE" ) )
|
||||||
|
{
|
||||||
|
if( !implementUse( proc, aParent, aNode ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !glob.compare( "DEF" ) )
|
||||||
|
{
|
||||||
|
if( !implementDef( proc, aParent, aNode ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ntype = getNodeTypeID( glob );
|
||||||
|
size_t line = 0;
|
||||||
|
size_t column = 0;
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 2 )
|
||||||
|
std::cerr << " * [INFO] Processing node '" << glob << "' ID: " << ntype << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch( ntype )
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// items to be implemented:
|
||||||
|
//
|
||||||
|
case WRL1_SEPARATOR:
|
||||||
|
|
||||||
|
if( !readSeparator( proc, aParent, aNode ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
//
|
||||||
|
// items not implemented or for optional future implementation:
|
||||||
|
//
|
||||||
|
default:
|
||||||
|
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
if( !proc.DiscardNode() )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] could not discard node at line " << line;
|
||||||
|
std::cerr << ", column " << column << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::Read( WRLPROC& proc, WRL1BASE* aTopNode )
|
||||||
|
{
|
||||||
|
// this function makes no sense in the base node
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << proc.GetError() << "\n";
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this method must never be invoked on a WRL1BASE object\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1BASE::readSeparator( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode )
|
||||||
|
{
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = NULL;
|
||||||
|
|
||||||
|
WRL1SEPARATOR* np = new WRL1SEPARATOR( m_dictionary, aParent );
|
||||||
|
|
||||||
|
if( !np->Read( proc, this ) )
|
||||||
|
{
|
||||||
|
delete np;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aNode )
|
||||||
|
*aNode = (WRL1NODE*) np;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL1BASE::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
{
|
||||||
|
if( m_Items.empty() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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 vrmlv2_node.h
|
||||||
|
* defines the base class for VRML1.0 nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VRML1_BASE_H
|
||||||
|
#define VRML1_BASE_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "vrml1_node.h"
|
||||||
|
|
||||||
|
class SGNODE;
|
||||||
|
class WRL1INLINE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WRL1BASE
|
||||||
|
* represents the top node of a VRML1 model
|
||||||
|
*/
|
||||||
|
class WRL1BASE : public WRL1NODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool m_useInline;
|
||||||
|
|
||||||
|
// handle cases of USE / DEF
|
||||||
|
bool implementUse( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode );
|
||||||
|
bool implementDef( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode );
|
||||||
|
|
||||||
|
bool readSeparator( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode );
|
||||||
|
|
||||||
|
std::map< std::string, WRL1INLINE* > m_inlineModels;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WRL1BASE();
|
||||||
|
virtual ~WRL1BASE();
|
||||||
|
|
||||||
|
// function to enable/disable Inline{} expansion
|
||||||
|
void SetEnableInline( bool enable );
|
||||||
|
bool GetEnableInline( void );
|
||||||
|
|
||||||
|
// functions to manipulate Inline{} objects
|
||||||
|
SGNODE* AddInlineData( const std::string& aName, WRL1INLINE* aObject );
|
||||||
|
SGNODE* GetInlineData( const std::string& aName, WRL1INLINE* aObject );
|
||||||
|
void DelInlineData( const std::string& aName, WRL1INLINE* aObject );
|
||||||
|
|
||||||
|
// function to read entire VRML file
|
||||||
|
bool Read( WRLPROC& proc );
|
||||||
|
|
||||||
|
// read in a VRML node
|
||||||
|
bool ReadNode( WRLPROC& proc, WRL1NODE* aParent, WRL1NODE** aNode );
|
||||||
|
|
||||||
|
// overrides
|
||||||
|
virtual std::string GetName( void );
|
||||||
|
virtual bool SetName( const std::string& aName );
|
||||||
|
|
||||||
|
// functions inherited from WRL1NODE
|
||||||
|
bool Read( WRLPROC& proc, WRL1BASE* aTopNode );
|
||||||
|
bool SetParent( WRL1NODE* aParent );
|
||||||
|
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VRML1_BASE_H
|
|
@ -0,0 +1,449 @@
|
||||||
|
/*
|
||||||
|
* 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 <set>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <iterator>
|
||||||
|
#include <cctype>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "vrml1_node.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool NAMEREGISTER::AddName( const std::string aName, WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
if( aName.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
|
||||||
|
|
||||||
|
if( ir != reg.end() )
|
||||||
|
reg.erase( ir );
|
||||||
|
|
||||||
|
reg.insert( std::pair< std::string, WRL1NODE* >( aName, aNode ) );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NAMEREGISTER::DelName( const std::string aName, WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
if( aName.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
|
||||||
|
|
||||||
|
if( ir != reg.end() && ir->second == aNode )
|
||||||
|
{
|
||||||
|
reg.erase( ir );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODE* NAMEREGISTER::FindName( const std::string aName )
|
||||||
|
{
|
||||||
|
if( aName.empty() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
std::map< std::string, WRL1NODE* >::iterator ir = reg.find( aName );
|
||||||
|
|
||||||
|
if( ir != reg.end() )
|
||||||
|
return ir->second;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::pair< std::string, WRL1NODES > NODEITEM;
|
||||||
|
typedef std::map< std::string, WRL1NODES > NODEMAP;
|
||||||
|
static NODEMAP nodenames;
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODE::WRL1NODE( NAMEREGISTER* aDictionary )
|
||||||
|
{
|
||||||
|
m_sgNode = NULL;
|
||||||
|
m_Parent = NULL;
|
||||||
|
m_Type = WRL1_END;
|
||||||
|
m_dictionary = aDictionary;
|
||||||
|
|
||||||
|
if( nodenames.empty() )
|
||||||
|
{
|
||||||
|
nodenames.insert( NODEITEM( "AsciiText", WRL1_ASCIITEXT ) );
|
||||||
|
nodenames.insert( NODEITEM( "Cone", WRL1_CONE ) );
|
||||||
|
nodenames.insert( NODEITEM( "Coordinate3", WRL1_COORDINATE3 ) );
|
||||||
|
nodenames.insert( NODEITEM( "Cube", WRL1_CUBE ) );
|
||||||
|
nodenames.insert( NODEITEM( "Cylinder", WRL1_CYLINDER ) );
|
||||||
|
nodenames.insert( NODEITEM( "DirectionalLight", WRL1_DIRECTIONALLIGHT ) );
|
||||||
|
nodenames.insert( NODEITEM( "FontStyle", WRL1_FONTSTYLE ) );
|
||||||
|
nodenames.insert( NODEITEM( "IndexedFaceSet", WRL1_INDEXEDFACESET ) );
|
||||||
|
nodenames.insert( NODEITEM( "IndexedLineSet", WRL1_INDEXEDLINESET ) );
|
||||||
|
nodenames.insert( NODEITEM( "Info", WRL1_INFO ) );
|
||||||
|
nodenames.insert( NODEITEM( "LOD", WRL1_LOD ) );
|
||||||
|
nodenames.insert( NODEITEM( "Material", WRL1_MATERIAL ) );
|
||||||
|
nodenames.insert( NODEITEM( "MaterialBinding", WRL1_MATERIALBINDING ) );
|
||||||
|
nodenames.insert( NODEITEM( "MatrixTransform", WRL1_MATRIXTRANSFORM ) );
|
||||||
|
nodenames.insert( NODEITEM( "Normal", WRL1_NORMAL ) );
|
||||||
|
nodenames.insert( NODEITEM( "NormalBinding", WRL1_NORMALBINDING ) );
|
||||||
|
nodenames.insert( NODEITEM( "OrthographicCamera", WRL1_ORTHOCAMERA ) );
|
||||||
|
nodenames.insert( NODEITEM( "PerspectiveCamera", WRL1_PERSPECTIVECAMERA ) );
|
||||||
|
nodenames.insert( NODEITEM( "PointLight", WRL1_POINTLIGHT ) );
|
||||||
|
nodenames.insert( NODEITEM( "PointSet", WRL1_POINTSET ) );
|
||||||
|
nodenames.insert( NODEITEM( "Rotation", WRL1_ROTATION ) );
|
||||||
|
nodenames.insert( NODEITEM( "Scale", WRL1_SCALE ) );
|
||||||
|
nodenames.insert( NODEITEM( "Separator", WRL1_SEPARATOR ) );
|
||||||
|
nodenames.insert( NODEITEM( "ShapeHints", WRL1_SHAPEHINTS ) );
|
||||||
|
nodenames.insert( NODEITEM( "Sphere", WRL1_SPHERE ) );
|
||||||
|
nodenames.insert( NODEITEM( "SpotLight", WRL1_SPOTLIGHT ) );
|
||||||
|
nodenames.insert( NODEITEM( "Switch", WRL1_SWITCH ) );
|
||||||
|
nodenames.insert( NODEITEM( "Texture2", WRL1_TEXTURE2 ) );
|
||||||
|
nodenames.insert( NODEITEM( "Testure2Transform", WRL1_TEXTURE2TRANSFORM ) );
|
||||||
|
nodenames.insert( NODEITEM( "TextureCoordinate2", WRL1_TEXTURECOORDINATE2 ) );
|
||||||
|
nodenames.insert( NODEITEM( "Transform", WRL1_TRANSFORM ) );
|
||||||
|
nodenames.insert( NODEITEM( "Translation", WRL1_TRANSLATION ) );
|
||||||
|
nodenames.insert( NODEITEM( "WWWAnchor", WRL1_WWWANCHOR ) );
|
||||||
|
nodenames.insert( NODEITEM( "WWWInline", WRL1_WWWINLINE ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODE::~WRL1NODE()
|
||||||
|
{
|
||||||
|
if( m_dictionary && !m_Name.empty() )
|
||||||
|
m_dictionary->DelName( m_Name, this );
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
std::list< WRL1NODE* >::iterator sBP = m_BackPointers.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eBP = m_BackPointers.end();
|
||||||
|
|
||||||
|
while( sBP != eBP )
|
||||||
|
{
|
||||||
|
(*sBP)->unlinkRefNode( this );
|
||||||
|
++sBP;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Refs.clear();
|
||||||
|
std::list< WRL1NODE* >::iterator sC = m_Children.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eC = m_Children.end();
|
||||||
|
|
||||||
|
while( sC != eC )
|
||||||
|
{
|
||||||
|
(*sC)->SetParent( NULL, false );
|
||||||
|
delete *sC;
|
||||||
|
++sC;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Children.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::addNodeRef( WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
// note: for VRML1 we allow even parent nodes to be held as references
|
||||||
|
m_BackPointers.push_back( aNode );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::delNodeRef( WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< WRL1NODE* >::iterator np =
|
||||||
|
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||||
|
|
||||||
|
if( np != m_BackPointers.end() )
|
||||||
|
{
|
||||||
|
m_BackPointers.erase( np );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] delNodeRef() did not find its target\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODES WRL1NODE::GetNodeType( void ) const
|
||||||
|
{
|
||||||
|
return m_Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODE* WRL1NODE::GetParent( void ) const
|
||||||
|
{
|
||||||
|
return m_Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string WRL1NODE::GetName( void )
|
||||||
|
{
|
||||||
|
return m_Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1NODE::SetName( const std::string& aName )
|
||||||
|
{
|
||||||
|
if( aName.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( isdigit( aName[0] ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] invalid node name '" << aName << "' (begins with digit)\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The character '+' is not allowed in names as per the VRML1 specification;
|
||||||
|
// 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_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 )
|
||||||
|
|| std::string::npos != aName.find_first_of( BAD_CHARS2 ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 1 )
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] invalid node name '" << aName;
|
||||||
|
std::cerr<< "' (contains invalid character)\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Name = aName;
|
||||||
|
|
||||||
|
if( m_dictionary )
|
||||||
|
m_dictionary->AddName( aName, this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* WRL1NODE::GetNodeTypeName( WRL1NODES aNodeType ) const
|
||||||
|
{
|
||||||
|
if( aNodeType < WRL1_BASE || aNodeType >= WRL1_END )
|
||||||
|
return "*INVALID_TYPE*";
|
||||||
|
|
||||||
|
if( aNodeType == WRL1_BASE )
|
||||||
|
return "*VIRTUAL_BASE*";
|
||||||
|
|
||||||
|
NODEMAP::iterator it = nodenames.begin();
|
||||||
|
advance( it, (aNodeType - WRL1_BEGIN) );
|
||||||
|
|
||||||
|
return it->first.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1STATUS* WRL1NODE::GetCurrentSettings( void )
|
||||||
|
{
|
||||||
|
return &m_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODES WRL1NODE::getNodeTypeID( const std::string aNodeName )
|
||||||
|
{
|
||||||
|
NODEMAP::iterator it = nodenames.find( aNodeName );
|
||||||
|
|
||||||
|
if( nodenames.end() != it )
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
return WRL1_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string WRL1NODE::GetError( void )
|
||||||
|
{
|
||||||
|
return m_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1NODE* WRL1NODE::FindNode( const std::string& aNodeName )
|
||||||
|
{
|
||||||
|
if( NULL == m_dictionary )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_dictionary->FindName( aNodeName );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1NODE::SetParent( WRL1NODE* aParent, bool doUnlink )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( NULL != m_Parent && doUnlink )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1NODE::AddChildNode( WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
if( aNode->GetNodeType() == WRL1_BASE )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] attempting to add a base node to another node\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list< WRL1NODE* >::iterator sC = m_Children.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eC = m_Children.end();
|
||||||
|
|
||||||
|
while( sC != eC )
|
||||||
|
{
|
||||||
|
if( *sC == aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
++sC;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNode->SetParent( this );
|
||||||
|
m_Children.push_back( aNode );
|
||||||
|
addItem( aNode );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WRL1NODE::AddRefNode( WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL passed as node pointer\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aNode->GetNodeType() == WRL1_BASE )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] attempting to add a base node ref to another base node\n";
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: the VRML1 spec does not prevent the reuse of a node at
|
||||||
|
// the same level; for example a Coordinate3 node can be recalled
|
||||||
|
// at any time to set the current coordinate set.
|
||||||
|
m_Refs.push_back( aNode );
|
||||||
|
addItem( aNode );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::unlinkChildNode( const WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< WRL1NODE* >::iterator sL = m_Children.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eL = m_Children.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
if( *sL == aNode )
|
||||||
|
{
|
||||||
|
m_Children.erase( sL );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delItem( aNode );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::unlinkRefNode( const WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< WRL1NODE* >::iterator sL = m_Refs.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eL = m_Refs.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
if( *sL == aNode )
|
||||||
|
{
|
||||||
|
m_Refs.erase( sL );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delItem( aNode );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::addItem( WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
m_Items.push_back( aNode );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WRL1NODE::delItem( const WRL1NODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< WRL1NODE* >::iterator sL = m_Items.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eL = m_Items.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
if( *sL == aNode )
|
||||||
|
{
|
||||||
|
m_Items.erase( sL );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
* 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 vrmlv1_node.h
|
||||||
|
* defines the base class for VRML1.0 nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VRML1_NODE_H
|
||||||
|
#define VRML1_NODE_H
|
||||||
|
|
||||||
|
#define GLM_FORCE_RADIANS
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "wrlproc.h"
|
||||||
|
|
||||||
|
class WRL1NODE;
|
||||||
|
|
||||||
|
// a class to hold the dictionary of node DEFs
|
||||||
|
class NAMEREGISTER
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::map< std::string, WRL1NODE* > reg;
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool AddName( const std::string aName, WRL1NODE* aNode );
|
||||||
|
bool DelName( const std::string aName, WRL1NODE* aNode );
|
||||||
|
WRL1NODE* FindName( const std::string aName );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class WRL1BASE;
|
||||||
|
class SGNODE;
|
||||||
|
|
||||||
|
|
||||||
|
// current settings which may affect all subsequent nodes
|
||||||
|
// during translation / rendering
|
||||||
|
struct WRL1STATUS
|
||||||
|
{
|
||||||
|
// XXX - as much as possible do not use pointers and if
|
||||||
|
// pointers are necessary, use the specialized rather
|
||||||
|
// than base pointers
|
||||||
|
// material
|
||||||
|
WRL1NODE* mat;
|
||||||
|
// material binding
|
||||||
|
WRL1NODE* matbind;
|
||||||
|
// normals
|
||||||
|
WRL1NODE* norm;
|
||||||
|
// normal binding
|
||||||
|
WRL1NODE* normbind;
|
||||||
|
// coordinate3
|
||||||
|
WRL1NODE* coord;
|
||||||
|
// transform
|
||||||
|
glm::dmat4 txmatrix;
|
||||||
|
|
||||||
|
WRL1STATUS()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
mat = NULL;
|
||||||
|
matbind = NULL;
|
||||||
|
norm = NULL;
|
||||||
|
normbind = NULL;
|
||||||
|
coord = NULL;
|
||||||
|
txmatrix = glm::scale( glm::dmat4( 1.0 ), glm::dvec3( 1.0 ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WRL1NODE
|
||||||
|
* represents the base class of all VRML2 nodes
|
||||||
|
*/
|
||||||
|
class WRL1NODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void addItem( WRL1NODE* aNode );
|
||||||
|
void delItem( const WRL1NODE* aNode );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
WRL1NODE* m_Parent; // pointer to parent node; may be NULL for top level node
|
||||||
|
WRL1NODES m_Type; // type of VRML node
|
||||||
|
std::string m_Name; // name to use for referencing the node by name
|
||||||
|
|
||||||
|
std::list< WRL1NODE* > m_BackPointers; // nodes which hold a reference to this
|
||||||
|
std::list< WRL1NODE* > m_Children; // nodes owned by this node
|
||||||
|
std::list< WRL1NODE* > m_Refs; // nodes referenced by this node
|
||||||
|
std::list< WRL1NODE* > m_Items; // all nodes in order of addition
|
||||||
|
std::string m_error;
|
||||||
|
|
||||||
|
WRL1STATUS m_current; // current settings
|
||||||
|
SGNODE* m_sgNode; // the SGNODE representation of the display data
|
||||||
|
|
||||||
|
// note: once a node is orphaned from a base node it must never access
|
||||||
|
// the dictionary since there is no guarantee the dictionary had not
|
||||||
|
// been destroyed. It may be possible to enforce this rule via the
|
||||||
|
// SetParent() routine if we implement a GetDictionary() function so
|
||||||
|
// that a node can obtain the dictionary of its parent. Note that the
|
||||||
|
// dictionary must be propagated to all children as well - perhaps
|
||||||
|
// this is best done via a SetDictionary() function.
|
||||||
|
NAMEREGISTER* m_dictionary;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCurrentSettings
|
||||||
|
* is used by children to retrieve and perhaps modify the
|
||||||
|
* current settings of the parent
|
||||||
|
*/
|
||||||
|
WRL1STATUS* GetCurrentSettings( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function getNodeTypeID
|
||||||
|
* returns the ID based on the given aNodeName or WRL1_INVALID (WRL1_END)
|
||||||
|
* if no such node name exists
|
||||||
|
*/
|
||||||
|
WRL1NODES getNodeTypeID( const std::string aNodeName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function unlinkChild
|
||||||
|
* removes references to an owned child; it is invoked by the child upon destruction
|
||||||
|
* to ensure that the parent has no invalid references.
|
||||||
|
*
|
||||||
|
* @param aNode is the child which is being deleted
|
||||||
|
*/
|
||||||
|
virtual void unlinkChildNode( const WRL1NODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function unlinkRef
|
||||||
|
* removes pointers to a referenced node; it is invoked by the referenced node
|
||||||
|
* upon destruction to ensure that the referring node has no invalid references.
|
||||||
|
*
|
||||||
|
* @param aNode is the node which is being deleted
|
||||||
|
*/
|
||||||
|
virtual void unlinkRefNode( const WRL1NODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function addNodeRef
|
||||||
|
* adds a pointer to a node which references, but does not own, this node.
|
||||||
|
* Such back-pointers are required to ensure that invalidated references
|
||||||
|
* are removed when a node is deleted
|
||||||
|
*
|
||||||
|
* @param aNode is the node holding a reference to this object
|
||||||
|
*/
|
||||||
|
void addNodeRef( WRL1NODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function delNodeRef
|
||||||
|
* removes a pointer to a node which references, but does not own, this node.
|
||||||
|
*
|
||||||
|
* @param aNode is the node holding a reference to this object
|
||||||
|
*/
|
||||||
|
void delNodeRef( WRL1NODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
WRL1NODE( NAMEREGISTER* aDictionary );
|
||||||
|
virtual ~WRL1NODE();
|
||||||
|
|
||||||
|
// read data via the given file processor and WRL1BASE object
|
||||||
|
virtual bool Read( WRLPROC& proc, WRL1BASE* aTopNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetNodeType
|
||||||
|
* returns the type of this node instance
|
||||||
|
*/
|
||||||
|
WRL1NODES GetNodeType( void ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetParent
|
||||||
|
* returns a pointer to the parent SGNODE of this object
|
||||||
|
* or NULL if the object has no parent (ie. top level transform)
|
||||||
|
*/
|
||||||
|
WRL1NODE* GetParent( void ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetParent
|
||||||
|
* sets the parent WRL1NODE of this object.
|
||||||
|
*
|
||||||
|
* @param aParent [in] is the desired parent node
|
||||||
|
* @param doUnlink indicates that the child must be unlinked from the parent
|
||||||
|
* @return true if the operation succeeds; false if
|
||||||
|
* the given node is not allowed to be a parent to
|
||||||
|
* the derived object.
|
||||||
|
*/
|
||||||
|
virtual bool SetParent( WRL1NODE* aParent, bool doUnlink = true );
|
||||||
|
|
||||||
|
virtual std::string GetName( void );
|
||||||
|
virtual bool SetName( const std::string& aName );
|
||||||
|
|
||||||
|
const char* GetNodeTypeName( WRL1NODES aNodeType ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindNode searches the tree of linked nodes and returns a
|
||||||
|
* reference to the current node with the given name. The reference
|
||||||
|
* is then typically added to another node via AddRefNode().
|
||||||
|
*
|
||||||
|
* @param aNodeName is the name of the node to search for
|
||||||
|
* @return is a valid node pointer on success, otherwise NULL
|
||||||
|
*/
|
||||||
|
virtual WRL1NODE* FindNode( const std::string& aNodeName );
|
||||||
|
|
||||||
|
virtual bool AddChildNode( WRL1NODE* aNode );
|
||||||
|
|
||||||
|
virtual bool AddRefNode( WRL1NODE* aNode );
|
||||||
|
|
||||||
|
std::string GetError( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function TranslateToSG
|
||||||
|
* produces a representation of the data using the intermediate
|
||||||
|
* scenegraph structures of the kicad_3dsg library.
|
||||||
|
*
|
||||||
|
* @param aParent is a pointer to the parent SG node
|
||||||
|
* @return is non-NULL on success
|
||||||
|
*/
|
||||||
|
virtual SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VRML1_NODE_H
|
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
* 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 "vrml1_base.h"
|
||||||
|
#include "vrml1_separator.h"
|
||||||
|
#include "plugins/3dapi/ifsg_all.h"
|
||||||
|
|
||||||
|
|
||||||
|
WRL1SEPARATOR::WRL1SEPARATOR( NAMEREGISTER* aDictionary ) : WRL1NODE( aDictionary )
|
||||||
|
{
|
||||||
|
m_Type = WRL1_SEPARATOR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1SEPARATOR::WRL1SEPARATOR( NAMEREGISTER* aDictionary, WRL1NODE* aParent ) :
|
||||||
|
WRL1NODE( aDictionary )
|
||||||
|
{
|
||||||
|
m_Type = WRL1_SEPARATOR;
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
WRL1SEPARATOR::~WRL1SEPARATOR()
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// functions inherited from WRL1NODE
|
||||||
|
bool WRL1SEPARATOR::Read( WRLPROC& proc, WRL1BASE* aTopNode )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Structure of a Transform node (p.120):
|
||||||
|
*
|
||||||
|
* Transform {
|
||||||
|
* eventIn MFNode addChildren
|
||||||
|
* eventIn MFNode removeChildren
|
||||||
|
* exposedField SFVec3f center 0 0 0
|
||||||
|
* exposedField MFNode children []
|
||||||
|
* exposedField SFRotation rotation 0 0 1 0
|
||||||
|
* exposedField SFVec3f scale 1 1 1
|
||||||
|
* exposedField SFRotation scaleOrientation 0 0 1 0
|
||||||
|
* exposedField SFVec3f translation 0 0 0
|
||||||
|
* field SFVec3f bboxCenter 0 0 0
|
||||||
|
* field SFVec3f bboxSize 0 0 0
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( NULL == aTopNode )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
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_VRML1 ) && ( DEBUG_VRML1 > 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_VRML1 ) && ( DEBUG_VRML1 > 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
proc.GetFilePosData( line, column );
|
||||||
|
|
||||||
|
if( !aTopNode->ReadNode( proc, this, NULL ) )
|
||||||
|
{
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 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( proc.Peek() == ',' )
|
||||||
|
proc.Pop();
|
||||||
|
|
||||||
|
} // while( true ) -- reading contents of Separator{}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* WRL1SEPARATOR::TranslateToSG( SGNODE* aParent, bool calcNormals )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if defined( DEBUG_VRML1 ) && ( DEBUG_VRML1 > 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() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
S3D::SGTYPES ptype = S3D::GetSGNodeType( aParent );
|
||||||
|
|
||||||
|
if( NULL != aParent && ptype != S3D::SGTYPE_TRANSFORM )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_VRML1
|
||||||
|
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( 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFSG_TRANSFORM txNode( aParent );
|
||||||
|
|
||||||
|
std::list< WRL1NODE* >::iterator sC = m_Children.begin();
|
||||||
|
std::list< WRL1NODE* >::iterator eC = m_Children.end();
|
||||||
|
WRL1NODES type;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
for( int i = 0; i < 2; ++i )
|
||||||
|
{
|
||||||
|
while( sC != eC )
|
||||||
|
{
|
||||||
|
type = (*sC)->GetNodeType();
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case WRL1_SHAPE:
|
||||||
|
case WRL1_SWITCH:
|
||||||
|
case WRL1_INLINE:
|
||||||
|
case WRL1_SEPARATOR:
|
||||||
|
|
||||||
|
if( NULL != (*sC)->TranslateToSG( txNode.GetRawPtr(), calcNormals ) )
|
||||||
|
test = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ sC;
|
||||||
|
}
|
||||||
|
|
||||||
|
sC = m_Refs.begin();
|
||||||
|
eC = m_Refs.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( false == test )
|
||||||
|
{
|
||||||
|
txNode.Destroy();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
txNode.SetScale( SGPOINT( scale.x, scale.y, scale.z ) );
|
||||||
|
txNode.SetCenter( SGPOINT( center.x, center.y, center.z ) );
|
||||||
|
txNode.SetTranslation( SGPOINT( translation.x, translation.y, translation.z ) );
|
||||||
|
txNode.SetScaleOrientation( SGVECTOR( scaleOrientation.x, scaleOrientation.y,
|
||||||
|
scaleOrientation.z ), scaleOrientation.w );
|
||||||
|
txNode.SetRotation( SGVECTOR( rotation.x, rotation.y, rotation.z), rotation.w );
|
||||||
|
|
||||||
|
m_sgNode = txNode.GetRawPtr();
|
||||||
|
|
||||||
|
return m_sgNode;
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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 vrml1_separator.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef VRML1_SEPARATOR_H
|
||||||
|
#define VRML1_SEPARATOR_H
|
||||||
|
|
||||||
|
#include "vrml1_node.h"
|
||||||
|
|
||||||
|
class WRL1BASE;
|
||||||
|
class SGNODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WRL1SEPARATOR
|
||||||
|
*/
|
||||||
|
class WRL1SEPARATOR : public WRL1NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WRL1SEPARATOR( NAMEREGISTER* aDictionary );
|
||||||
|
WRL1SEPARATOR( NAMEREGISTER* aDictionary, WRL1NODE* aNode );
|
||||||
|
virtual ~WRL1SEPARATOR();
|
||||||
|
|
||||||
|
// functions inherited from WRL1NODE
|
||||||
|
bool Read( WRLPROC& proc, WRL1BASE* aTopNode );
|
||||||
|
SGNODE* TranslateToSG( SGNODE* aParent, bool calcNormals );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VRML1_SEPARATOR_H
|
Loading…
Reference in New Issue