+ Removed glm source from kicad tree (Maciej / Cirilo)
+ Added renderer for 3D model preview (Mario) + Added 3d_cache including name resolver and modifications to 3D model dialogs (Cirilo)
This commit is contained in:
parent
ab7350bf2d
commit
69cc788e8e
|
@ -0,0 +1,622 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <fstream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/utils.h>
|
||||||
|
#include <wx/stdpaths.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
#include "3d_cache.h"
|
||||||
|
#include "3d_info.h"
|
||||||
|
#include "sg/scenegraph.h"
|
||||||
|
#include "3d_filename_resolver.h"
|
||||||
|
#include "3d_plugin_manager.h"
|
||||||
|
#include "sg/ifsg_api.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define CACHE_CONFIG_NAME wxT( "cache.cfg" )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const wxString md5ToWXString( const unsigned char* aMD5Sum )
|
||||||
|
{
|
||||||
|
unsigned char uc;
|
||||||
|
unsigned char tmp;
|
||||||
|
char md5[33];
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
uc = aMD5Sum[i];
|
||||||
|
tmp = uc / 16;
|
||||||
|
|
||||||
|
if( tmp > 9 )
|
||||||
|
tmp += 87;
|
||||||
|
else
|
||||||
|
tmp += 48;
|
||||||
|
|
||||||
|
md5[j++] = tmp;
|
||||||
|
tmp = uc % 16;
|
||||||
|
|
||||||
|
if( tmp > 9 )
|
||||||
|
tmp += 87;
|
||||||
|
else
|
||||||
|
tmp += 48;
|
||||||
|
|
||||||
|
md5[j++] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
md5[j] = 0;
|
||||||
|
|
||||||
|
return wxString::FromUTF8Unchecked( md5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool md5matches( const unsigned char* md5a, const unsigned char* md5b )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
if( md5a[i] != md5b[i] )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool isMD5null( const unsigned char* aMD5Sum )
|
||||||
|
{
|
||||||
|
if( NULL == aMD5Sum )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL passed for aMD5Sum\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
if( 0 != aMD5Sum[i] )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class S3D_CACHE_ENTRY
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// prohibit assignment and default copy constructor
|
||||||
|
S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source );
|
||||||
|
S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source );
|
||||||
|
|
||||||
|
wxString m_CacheBaseName; // base name of cache file (an MD5 sum)
|
||||||
|
|
||||||
|
public:
|
||||||
|
S3D_CACHE_ENTRY();
|
||||||
|
~S3D_CACHE_ENTRY();
|
||||||
|
|
||||||
|
void SetMD5( const unsigned char* aMD5Sum );
|
||||||
|
const wxString GetCacheBaseName( void );
|
||||||
|
|
||||||
|
unsigned char md5sum[16];
|
||||||
|
SCENEGRAPH* sceneData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
S3D_CACHE_ENTRY::S3D_CACHE_ENTRY()
|
||||||
|
{
|
||||||
|
sceneData = NULL;
|
||||||
|
memset( md5sum, 0, 16 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_CACHE_ENTRY::~S3D_CACHE_ENTRY()
|
||||||
|
{
|
||||||
|
if( NULL != sceneData )
|
||||||
|
delete sceneData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_CACHE_ENTRY::SetMD5( const unsigned char* aMD5Sum )
|
||||||
|
{
|
||||||
|
if( NULL == aMD5Sum )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL passed for aMD5Sum\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( md5sum, aMD5Sum, 16 );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const wxString S3D_CACHE_ENTRY::GetCacheBaseName( void )
|
||||||
|
{
|
||||||
|
if( m_CacheBaseName.empty() )
|
||||||
|
m_CacheBaseName = md5ToWXString( md5sum );
|
||||||
|
|
||||||
|
return m_CacheBaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_CACHE::S3D_CACHE()
|
||||||
|
{
|
||||||
|
m_DirtyCache = false;
|
||||||
|
m_FNResolver = new S3D_FILENAME_RESOLVER;
|
||||||
|
m_Plugins = new S3D_PLUGIN_MANAGER;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
S3D_CACHE::~S3D_CACHE()
|
||||||
|
{
|
||||||
|
FlushCache();
|
||||||
|
|
||||||
|
if( m_FNResolver )
|
||||||
|
delete m_FNResolver;
|
||||||
|
|
||||||
|
if( m_Plugins )
|
||||||
|
delete m_Plugins;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile )
|
||||||
|
{
|
||||||
|
wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile );
|
||||||
|
|
||||||
|
if( full3Dpath.empty() )
|
||||||
|
{
|
||||||
|
// the model cannot be found; we cannot proceed
|
||||||
|
std::cout << " * [3D model] could not find model '";
|
||||||
|
std::cout << aModelFile.ToUTF8() << "'\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check cache if file is already loaded
|
||||||
|
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString >::iterator mi;
|
||||||
|
mi = m_CacheMap.find( full3Dpath );
|
||||||
|
|
||||||
|
if( mi != m_CacheMap.end() )
|
||||||
|
return mi->second->sceneData;
|
||||||
|
|
||||||
|
// a cache item does not exist; search the Filename->Cachename map
|
||||||
|
return checkCache( full3Dpath );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
unsigned char md5sum[16];
|
||||||
|
|
||||||
|
if( !getMD5( aFileName, md5sum ) || m_CacheDir.empty() )
|
||||||
|
{
|
||||||
|
// just in case we can't get an MD5 sum (for example, on access issues)
|
||||||
|
// or we do not have a configured cache file directory, we create an
|
||||||
|
// entry to prevent further attempts at loading the file
|
||||||
|
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||||
|
m_CacheList.push_back( ep );
|
||||||
|
|
||||||
|
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||||
|
( aFileName, ep ) ).second == false )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] duplicate entry in map file; key = ";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "\n";
|
||||||
|
m_CacheList.pop_back();
|
||||||
|
delete ep;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D Model] [0] added cached name '" << aFileName.ToUTF8() << "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
S3D_CACHE_ENTRY* ep = new S3D_CACHE_ENTRY;
|
||||||
|
m_CacheList.push_back( ep );
|
||||||
|
|
||||||
|
if( m_CacheMap.insert( std::pair< wxString, S3D_CACHE_ENTRY* >
|
||||||
|
( aFileName, ep ) ).second == false )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] duplicate entry in map file; key = ";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "\n";
|
||||||
|
m_CacheList.pop_back();
|
||||||
|
delete ep;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D Model] [1] added cached name '" << aFileName.ToUTF8() << "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
ep->SetMD5( md5sum );
|
||||||
|
|
||||||
|
wxString bname = ep->GetCacheBaseName();
|
||||||
|
wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
|
||||||
|
|
||||||
|
if( wxFileName::FileExists( cachename ) )
|
||||||
|
{
|
||||||
|
loadCacheData( ep );
|
||||||
|
return ep->sceneData;
|
||||||
|
}
|
||||||
|
|
||||||
|
ep->sceneData = m_Plugins->Load3DModel( aFileName );
|
||||||
|
|
||||||
|
return ep->sceneData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_CACHE::getMD5( const wxString& aFileName, unsigned char* aMD5Sum )
|
||||||
|
{
|
||||||
|
if( aFileName.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] empty filename\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL == aMD5Sum )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aMD5Sum\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
|
||||||
|
|
||||||
|
if( !fp )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3dmodel] could not open file '" << aFileName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct md5_ctx msum;
|
||||||
|
md5_init_ctx( &msum );
|
||||||
|
int res = md5_stream( fp, aMD5Sum );
|
||||||
|
fclose( fp );
|
||||||
|
|
||||||
|
if( 0 != res )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3dmodel] md5 calculation failed on file '" << aFileName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_CACHE::loadCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||||
|
{
|
||||||
|
wxString bname = aCacheItem->GetCacheBaseName();
|
||||||
|
|
||||||
|
if( bname.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] cannot load cached model; no md5 hash available\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_CacheDir.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] cannot load cached model; config directory unknown\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||||
|
|
||||||
|
// determine if the file exists and is a regular file
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if( stat( fname.ToUTF8(), &info ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !S_ISREG( info.st_mode ) )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] path exists but is not a regular file: '";
|
||||||
|
std::cerr << fname.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning NOT IMPLEMENTED
|
||||||
|
// XXX - proceed with loading the cache data
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_CACHE::saveCacheData( S3D_CACHE_ENTRY* aCacheItem )
|
||||||
|
{
|
||||||
|
if( NULL == aCacheItem )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * NULL passed for aCacheItem\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL == aCacheItem->sceneData )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * aCacheItem has no valid scene data\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString bname = aCacheItem->GetCacheBaseName();
|
||||||
|
|
||||||
|
if( bname.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] cannot load cached model; no md5 hash available\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_CacheDir.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] cannot load cached model; config directory unknown\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString fname = m_CacheDir + bname + wxT( ".3dc" );
|
||||||
|
|
||||||
|
if( wxFileName::Exists( fname ) )
|
||||||
|
{
|
||||||
|
// determine if the file is a regular file
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
if( stat( fname.ToUTF8(), &info ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !S_ISREG( info.st_mode ) )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D model] path exists but is not a regular file: '";
|
||||||
|
std::cerr << fname.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the file already exists on disk; just exit
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning NOT IMPLEMENTED
|
||||||
|
// XXX - proceed with saving the cache data
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
|
||||||
|
{
|
||||||
|
if( !m_ConfigDir.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxFileName cfgdir( aConfigDir, "" );
|
||||||
|
cfgdir.Normalize();
|
||||||
|
|
||||||
|
if( cfgdir.DirExists() )
|
||||||
|
{
|
||||||
|
m_ConfigDir = cfgdir.GetPath();
|
||||||
|
|
||||||
|
// inform the file resolver of the config directory
|
||||||
|
if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * could not set 3D Config Directory on filename resolver\n";
|
||||||
|
std::cerr << " * config directory: '" << m_ConfigDir.ToUTF8() << "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgdir.AppendDir( wxT( "cache" ) );
|
||||||
|
|
||||||
|
if( !cfgdir.DirExists() )
|
||||||
|
{
|
||||||
|
cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||||
|
|
||||||
|
if( !cfgdir.DirExists() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * failed to create 3D cache directory\n";
|
||||||
|
std::cerr << " * cache directory: '";
|
||||||
|
std::cerr << cfgdir.GetPath().ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CacheDir = cfgdir.GetPathWithSep();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString S3D_CACHE::Get3DConfigDir( bool createDefault )
|
||||||
|
{
|
||||||
|
if( !m_ConfigDir.empty() || !createDefault )
|
||||||
|
return m_ConfigDir;
|
||||||
|
|
||||||
|
// note: duplicated from common/common.cpp GetKicadConfigPath() to avoid
|
||||||
|
// code coupling; ideally the instantiating code should call
|
||||||
|
// Set3DConfigDir() to set the directory rather than relying on this
|
||||||
|
// directory remaining the same in future KiCad releases.
|
||||||
|
wxFileName cfgpath;
|
||||||
|
|
||||||
|
// From the wxWidgets wxStandardPaths::GetUserConfigDir() help:
|
||||||
|
// Unix: ~ (the home directory)
|
||||||
|
// Windows: "C:\Documents and Settings\username\Application Data"
|
||||||
|
// Mac: ~/Library/Preferences
|
||||||
|
cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
|
||||||
|
|
||||||
|
#if !defined( __WINDOWS__ ) && !defined( __WXMAC__ )
|
||||||
|
wxString envstr;
|
||||||
|
|
||||||
|
if( !wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) || envstr.IsEmpty() )
|
||||||
|
{
|
||||||
|
// XDG_CONFIG_HOME is not set, so use the fallback
|
||||||
|
cfgpath.AppendDir( wxT( ".config" ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Override the assignment above with XDG_CONFIG_HOME
|
||||||
|
cfgpath.AssignDir( envstr );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cfgpath.AppendDir( wxT( "kicad" ) );
|
||||||
|
cfgpath.AppendDir( wxT( "3d" ) );
|
||||||
|
|
||||||
|
if( !cfgpath.DirExists() )
|
||||||
|
{
|
||||||
|
cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !cfgpath.DirExists() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * failed to create 3D configuration directory\n";
|
||||||
|
return wxT( "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Set3DConfigDir( cfgpath.GetPath() ) )
|
||||||
|
return m_ConfigDir;
|
||||||
|
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_CACHE::SetProjectDir( const wxString& aProjDir )
|
||||||
|
{
|
||||||
|
bool hasChanged = false;
|
||||||
|
|
||||||
|
if( m_FNResolver->SetProjectDir( aProjDir, &hasChanged ) && hasChanged )
|
||||||
|
{
|
||||||
|
m_CacheMap.clear();
|
||||||
|
|
||||||
|
std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
|
||||||
|
std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
delete *sL;
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CacheList.clear();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString S3D_CACHE::GetProjectDir( void )
|
||||||
|
{
|
||||||
|
return m_FNResolver->GetProjectDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_FILENAME_RESOLVER* S3D_CACHE::GetResolver( void )
|
||||||
|
{
|
||||||
|
return m_FNResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::list< wxString > const* S3D_CACHE::GetFileFilters( void ) const
|
||||||
|
{
|
||||||
|
return m_Plugins->GetFileFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_CACHE::FlushCache( void )
|
||||||
|
{
|
||||||
|
std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
|
||||||
|
std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
|
||||||
|
|
||||||
|
while( sCL != eCL )
|
||||||
|
{
|
||||||
|
delete *sCL;
|
||||||
|
++sCL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CacheList.clear();
|
||||||
|
ClosePlugins();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_CACHE::ClosePlugins( void )
|
||||||
|
{
|
||||||
|
if( NULL != m_Plugins )
|
||||||
|
m_Plugins->ClosePlugins();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// notes:
|
||||||
|
// 1. aModelEntry:
|
||||||
|
// + rotation: degrees, model space X, Y, Z; rotations are specified in sequence
|
||||||
|
//
|
||||||
|
S3DMODEL* S3D_CACHE::Prepare( S3D_INFO const* aModelEntry,
|
||||||
|
const SGPOINT& aRotation, const SGPOINT& aOffset )
|
||||||
|
{
|
||||||
|
SCENEGRAPH* sp = Load( aModelEntry->filename );
|
||||||
|
|
||||||
|
if( !sp )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// create a single transform entity to apply to the models
|
||||||
|
glm::dmat4 t0 = glm::translate( glm::dvec3( 25.4 * aModelEntry->offset.x, 25.4 * aModelEntry->offset.y,
|
||||||
|
25.4 * aModelEntry->offset.z ) );
|
||||||
|
|
||||||
|
glm::dmat4 rX = glm::rotate( aModelEntry->rotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||||
|
glm::dmat4 rY = glm::rotate( -aModelEntry->rotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) );
|
||||||
|
glm::dmat4 rZ = glm::rotate( aModelEntry->rotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) );
|
||||||
|
|
||||||
|
glm::dmat4 s0 = glm::scale( glm::dvec3( aModelEntry->scale.x, aModelEntry->scale.y,
|
||||||
|
aModelEntry->scale.z ) );
|
||||||
|
|
||||||
|
glm::dmat4 m0 = rZ * rY * rX * s0 * t0;
|
||||||
|
|
||||||
|
rX = glm::rotate( aRotation.x, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||||
|
rY = glm::rotate( aRotation.y, glm::dvec3( 0.0, 1.0, 0.0 ) );
|
||||||
|
rZ = glm::rotate( aRotation.z, glm::dvec3( 0.0, 0.0, 1.0 ) );
|
||||||
|
|
||||||
|
glm::dmat4 t1 = glm::translate( glm::dvec3( aOffset.x, aOffset.y, aOffset.z ) );
|
||||||
|
|
||||||
|
glm::dmat4 m1 = t1 * rZ * rY * rX * m0;
|
||||||
|
|
||||||
|
return S3D::Prepare( sp, &m1 );
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 3d_cache.h
|
||||||
|
* defines the display data cache manager for 3D models
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CACHE_3D_H
|
||||||
|
#define CACHE_3D_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include "str_rsort.h"
|
||||||
|
#include "3d_filename_resolver.h"
|
||||||
|
#include "3d_info.h"
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
|
||||||
|
|
||||||
|
class S3D_CACHE;
|
||||||
|
class S3D_CACHE_ENTRY;
|
||||||
|
class SCENEGRAPH;
|
||||||
|
class S3D_FILENAME_RESOLVER;
|
||||||
|
class S3D_PLUGIN_MANAGER;
|
||||||
|
struct S3D_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
class S3D_CACHE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// cache entries
|
||||||
|
std::list< S3D_CACHE_ENTRY* > m_CacheList;
|
||||||
|
|
||||||
|
/// mapping of file names to cache names and data
|
||||||
|
std::map< wxString, S3D_CACHE_ENTRY*, S3D::rsort_wxString > m_CacheMap;
|
||||||
|
|
||||||
|
/// object to resolve file names
|
||||||
|
S3D_FILENAME_RESOLVER* m_FNResolver;
|
||||||
|
|
||||||
|
/// plugin manager
|
||||||
|
S3D_PLUGIN_MANAGER* m_Plugins;
|
||||||
|
|
||||||
|
/// set true if the cache needs to be updated
|
||||||
|
bool m_DirtyCache;
|
||||||
|
|
||||||
|
/// 3D cache directory
|
||||||
|
wxString m_CacheDir;
|
||||||
|
|
||||||
|
/// base configuration path for 3D items
|
||||||
|
wxString m_ConfigDir;
|
||||||
|
|
||||||
|
/// current KiCad project dir
|
||||||
|
wxString m_ProjDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function checkCache
|
||||||
|
* searches the cache list for the given filename and retrieves
|
||||||
|
* the cache data; a cache entry is created if one does not
|
||||||
|
* already exist
|
||||||
|
*
|
||||||
|
* @param aFileName [in] is a partial or full file path; a partial path is accepted
|
||||||
|
* so that a cached model may be used in cases where the user has moved or deleted
|
||||||
|
* the original model file.
|
||||||
|
* @param aModelEntry [in, out] is the model entry for which we are retrieving
|
||||||
|
* scene data.
|
||||||
|
* @param aMD5Sum [in] is an optional MD5 sum; if this parameter is supplied and its value
|
||||||
|
* differs from the cached file then the function will fail and the flag aMD5Mismatch
|
||||||
|
* will be set to true. If the parameter is not supplied then the cache model is used
|
||||||
|
* if available and with no regard to the MD5 sum.
|
||||||
|
* @param aMD5Mismatch [out] if the function succeeds then this flag is set to false;
|
||||||
|
* the flag is set true if aMD5Sum is specified and differs from the cached object's
|
||||||
|
* md5sum.
|
||||||
|
* @return on success a pointer to a SCENEGRAPH, otherwise NULL
|
||||||
|
*/
|
||||||
|
SCENEGRAPH* checkCache( const wxString& aFileName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function getMD5
|
||||||
|
* calculates the MD5 hash of the given file
|
||||||
|
*
|
||||||
|
* @param aFileName [in] is a fully qualified path to the model file
|
||||||
|
* @param aMD5Sum [out] is a 16-byte character array to hold the MD5 hash
|
||||||
|
* @return true if the md5 hash was calculated; otherwise false
|
||||||
|
*/
|
||||||
|
bool getMD5( const wxString& aFileName, unsigned char* aMD5Sum );
|
||||||
|
|
||||||
|
// load scene data from a cache file
|
||||||
|
bool loadCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||||
|
|
||||||
|
// save scene data to a cache file
|
||||||
|
bool saveCacheData( S3D_CACHE_ENTRY* aCacheItem );
|
||||||
|
|
||||||
|
public:
|
||||||
|
S3D_CACHE();
|
||||||
|
virtual ~S3D_CACHE();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Set3DConfigDir
|
||||||
|
* Sets the configuration directory to be used by the
|
||||||
|
* model manager for storing 3D model manager configuration
|
||||||
|
* data and the model cache. The config directory may only be
|
||||||
|
* set once in the lifetime of the object.
|
||||||
|
*
|
||||||
|
* @param aConfigDir is the configuration directory to use
|
||||||
|
* for 3D model manager data
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Get3DConfigDir
|
||||||
|
* returns the current 3D configuration directory on
|
||||||
|
* success, otherwise it returns wxEmptyString. If the
|
||||||
|
* directory was not previously set via Set3DConfigDir()
|
||||||
|
* then a default is used which is based on kicad's
|
||||||
|
* configuration directory code as of September 2015.
|
||||||
|
*/
|
||||||
|
wxString Get3DConfigDir( bool createDefault = false );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetProjectDir
|
||||||
|
* sets the current project's working directory; this
|
||||||
|
* affects the model search path
|
||||||
|
*/
|
||||||
|
bool SetProjectDir( const wxString& aProjDir );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetProjectDir
|
||||||
|
* returns the current project's working directory
|
||||||
|
*/
|
||||||
|
wxString GetProjectDir( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Load
|
||||||
|
* attempts to load the scene data for a model; it will consult the
|
||||||
|
* internal cache list and load from cache if possible before invoking
|
||||||
|
* the load() function of the available plugins.
|
||||||
|
*
|
||||||
|
* @param aModelFile [in] is the partial or full path to the model to be loaded
|
||||||
|
* @return true if the model was successfully loaded, otherwise false.
|
||||||
|
* The model may fail to load if, for example, the plugin does not
|
||||||
|
* support rendering of the 3D model.
|
||||||
|
*/
|
||||||
|
SCENEGRAPH* Load( const wxString& aModelFile );
|
||||||
|
|
||||||
|
S3D_FILENAME_RESOLVER* GetResolver( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetFileFilters
|
||||||
|
* returns the list of file filters retrieved from the plugins;
|
||||||
|
* this will contain at least the default "All Files (*.*)|*.*"
|
||||||
|
*
|
||||||
|
* @return a pointer to the filter list
|
||||||
|
*/
|
||||||
|
std::list< wxString > const* GetFileFilters( void ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FlushCache
|
||||||
|
* frees all data in the cache and closes all plugins
|
||||||
|
*/
|
||||||
|
void FlushCache( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ClosePlugins
|
||||||
|
* unloads plugins to free memory
|
||||||
|
*/
|
||||||
|
void ClosePlugins( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Prepare
|
||||||
|
* attempts to load the scene data for a model and to translate it
|
||||||
|
* into an S3D_MODEL structure for display by a renderer
|
||||||
|
*
|
||||||
|
* @param aModelEntry is the structure containing the model name,
|
||||||
|
* scale, offset, and rotation. Note that by kicad convention the
|
||||||
|
* operations are Offset-Scale-Rotation, the Y value of the offset
|
||||||
|
* is negative (Left-hand coordinate system), and the units of the
|
||||||
|
* offset is inches. Application of the Offset, Scale. Rotation
|
||||||
|
* within the aModelEntry structure places the model into a nominal
|
||||||
|
* (0, 0, 0) position and orientation. Final positioning of the
|
||||||
|
* model instance is determined by the aOffset, aAxis, and aAngle
|
||||||
|
* parameters.
|
||||||
|
* @ aRotation is a X, Y, Z rotation to calculate the final orientation
|
||||||
|
* of the model instance
|
||||||
|
* @param aOffset is an offset to apply to obtain the final position
|
||||||
|
* of the model instance; this offset is applied after the aAxis/aAngle
|
||||||
|
* orientation in the common Rotation-Scale-Translation order of transforms.
|
||||||
|
*/
|
||||||
|
S3DMODEL* Prepare( S3D_INFO const* aModelEntry,
|
||||||
|
const SGPOINT& aRotation, const SGPOINT& aOffset );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CACHE_3D_H
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <common.h>
|
||||||
|
#include "3d_cache_wrapper.h"
|
||||||
|
|
||||||
|
|
||||||
|
CACHE_WRAPPER::CACHE_WRAPPER()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CACHE_WRAPPER::~CACHE_WRAPPER()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_CACHE* PROJECT::Get3DCacheManager( bool updateProjDir )
|
||||||
|
{
|
||||||
|
CACHE_WRAPPER* cw = (CACHE_WRAPPER*) GetElem( ELEM_3DCACHE );
|
||||||
|
S3D_CACHE* cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||||
|
|
||||||
|
// check that we get the expected type of object or NULL
|
||||||
|
wxASSERT( !cw || cache );
|
||||||
|
|
||||||
|
if( !cw )
|
||||||
|
{
|
||||||
|
cw = new CACHE_WRAPPER;
|
||||||
|
cache = dynamic_cast<S3D_CACHE*>( cw );
|
||||||
|
|
||||||
|
wxFileName cfgpath;
|
||||||
|
cfgpath.AssignDir( GetKicadConfigPath() );
|
||||||
|
cfgpath.AppendDir( wxT( "3d" ) );
|
||||||
|
cache->Set3DConfigDir( cfgpath.GetFullPath() );
|
||||||
|
SetElem( ELEM_3DCACHE, cw );
|
||||||
|
updateProjDir = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( updateProjDir )
|
||||||
|
cache->SetProjectDir( GetProjectPath() );
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CACHE_WRAPPER_3D_H
|
||||||
|
#define CACHE_WRAPPER_3D_H
|
||||||
|
|
||||||
|
#include <project.h>
|
||||||
|
#include "3d_cache.h"
|
||||||
|
|
||||||
|
class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CACHE_WRAPPER();
|
||||||
|
virtual ~CACHE_WRAPPER();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CACHE_WRAPPER_3D_H
|
|
@ -0,0 +1,457 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/utils.h>
|
||||||
|
|
||||||
|
#include "3d_filename_resolver.h"
|
||||||
|
|
||||||
|
#define S3D_RESOLVER_CONFIG wxT( "3Dresolver.cfg" )
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::Set3DConfigDir( const wxString& aConfigDir )
|
||||||
|
{
|
||||||
|
if( aConfigDir.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxFileName cfgdir( aConfigDir, "" );
|
||||||
|
cfgdir.Normalize();
|
||||||
|
|
||||||
|
if( false == cfgdir.DirExists() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_ConfigDir = cfgdir.GetPath();
|
||||||
|
createPathList();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::SetProjectDir( const wxString& aProjDir, bool* flgChanged )
|
||||||
|
{
|
||||||
|
if( aProjDir.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxFileName projdir( aProjDir, "" );
|
||||||
|
projdir.Normalize();
|
||||||
|
|
||||||
|
if( false == projdir.DirExists() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxString path = projdir.GetPath();
|
||||||
|
|
||||||
|
if( flgChanged )
|
||||||
|
*flgChanged = false;
|
||||||
|
|
||||||
|
if( m_Paths.empty() )
|
||||||
|
{
|
||||||
|
m_Paths.push_back( path );
|
||||||
|
|
||||||
|
if( flgChanged )
|
||||||
|
*flgChanged = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( m_Paths.front().Cmp( path ) )
|
||||||
|
{
|
||||||
|
m_Paths.pop_front();
|
||||||
|
m_Paths.push_front( path );
|
||||||
|
m_NameMap.clear();
|
||||||
|
|
||||||
|
if( flgChanged )
|
||||||
|
*flgChanged = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cout << " * [INFO] changed project dir to " << m_Paths.front().ToUTF8() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString S3D_FILENAME_RESOLVER::GetProjectDir( void )
|
||||||
|
{
|
||||||
|
if( m_Paths.empty() )
|
||||||
|
return wxEmptyString;
|
||||||
|
|
||||||
|
return m_Paths.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::createPathList( void )
|
||||||
|
{
|
||||||
|
if( !m_Paths.empty() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
wxString kmod;
|
||||||
|
|
||||||
|
// add the current working directory as the first entry by
|
||||||
|
// default; since CWD is not necessarily what we really want,
|
||||||
|
// the user may change this later with a call to SetProjectDir()
|
||||||
|
|
||||||
|
if( !addPath( wxFileName::GetCwd() ) )
|
||||||
|
m_Paths.push_back( wxEmptyString );
|
||||||
|
|
||||||
|
if( wxGetEnv( wxT( "KISYS3DMOD" ), &kmod ) )
|
||||||
|
addPath( kmod );
|
||||||
|
|
||||||
|
if( !m_ConfigDir.empty() )
|
||||||
|
readPathList();
|
||||||
|
|
||||||
|
if( m_Paths.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << " * [3D model] search paths:\n";
|
||||||
|
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||||
|
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
std::cout << " + '" << (*sPL).ToUTF8() << "'\n";
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::UpdatePathList( std::vector< wxString >& aPathList )
|
||||||
|
{
|
||||||
|
while( m_Paths.size() > 1 )
|
||||||
|
m_Paths.pop_back();
|
||||||
|
|
||||||
|
size_t nI = aPathList.size();
|
||||||
|
|
||||||
|
for( size_t i = 0; i < nI; ++i )
|
||||||
|
addPath( aPathList[i] );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "* S3D_FILENAME_RESOLVER::UpdatePathList()\n";
|
||||||
|
std::cerr << "NItems: " << aPathList.size() << "\n";
|
||||||
|
|
||||||
|
for( size_t i = 0; i < aPathList.size(); ++i )
|
||||||
|
std::cerr << "Item #" << i << ": " << aPathList[i].ToUTF8() << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return writePathList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString S3D_FILENAME_RESOLVER::ResolvePath( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
if( aFileName.empty() )
|
||||||
|
return wxEmptyString;
|
||||||
|
|
||||||
|
if( m_Paths.empty() )
|
||||||
|
createPathList();
|
||||||
|
|
||||||
|
// first attempt to use the name as specified:
|
||||||
|
wxString aResolvedName;
|
||||||
|
wxString fname = aFileName;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// translate from KiCad's internal UNIX-like path to MSWin paths
|
||||||
|
fname.Replace( wxT( "/" ), wxT( "\\" ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( checkRealPath( fname, aResolvedName ) )
|
||||||
|
return aResolvedName;
|
||||||
|
|
||||||
|
// look up the filename in the internal filename map
|
||||||
|
std::map< wxString, wxString, S3D::rsort_wxString >::iterator mi;
|
||||||
|
mi = m_NameMap.find( fname );
|
||||||
|
|
||||||
|
if( mi != m_NameMap.end() )
|
||||||
|
return mi->second;
|
||||||
|
|
||||||
|
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||||
|
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
wxFileName fpath( wxFileName::DirName( *sPL ) );
|
||||||
|
wxFileName filename( fname );
|
||||||
|
|
||||||
|
// we can only attempt a search if the filename is incomplete
|
||||||
|
if( filename.IsRelative() )
|
||||||
|
{
|
||||||
|
wxString fullPath = fpath.GetPathWithSep() + fname;
|
||||||
|
|
||||||
|
if( checkRealPath( fullPath, aResolvedName ) )
|
||||||
|
return aResolvedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << " * [3D Model] filename could not be resolved: '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
|
||||||
|
return wxEmptyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::checkRealPath( const wxString& aFileName,
|
||||||
|
wxString& aResolvedName )
|
||||||
|
{
|
||||||
|
aResolvedName.clear();
|
||||||
|
wxFileName fname( aFileName );
|
||||||
|
fname.Normalize();
|
||||||
|
|
||||||
|
if( !fname.FileExists() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
aResolvedName = fname.GetFullPath();
|
||||||
|
m_NameMap.insert( std::pair< wxString, wxString > ( aFileName, aResolvedName ) );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::addPath( const wxString& aPath )
|
||||||
|
{
|
||||||
|
if( aPath.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxFileName path( aPath, "" );
|
||||||
|
path.Normalize();
|
||||||
|
|
||||||
|
if( !path.DirExists() )
|
||||||
|
{
|
||||||
|
std::cerr << " * [3D Model] invalid path: '" << path.GetPath().ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString pname = path.GetPath();
|
||||||
|
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||||
|
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
if( !pname.Cmp( *sPL ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Paths.push_back( pname );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::readPathList( void )
|
||||||
|
{
|
||||||
|
if( m_ConfigDir.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * 3D configuration directory is unknown\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxFileName cfgpath( m_ConfigDir, S3D_RESOLVER_CONFIG );
|
||||||
|
cfgpath.Normalize();
|
||||||
|
wxString cfgname = cfgpath.GetFullPath();
|
||||||
|
|
||||||
|
size_t nitems = m_Paths.size();
|
||||||
|
|
||||||
|
std::ifstream cfgFile;
|
||||||
|
std::string cfgLine;
|
||||||
|
|
||||||
|
if( !wxFileName::Exists( cfgname ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * no 3D configuration file: '";
|
||||||
|
std::cerr << cfgname.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgFile.open( cfgname.ToUTF8() );
|
||||||
|
|
||||||
|
if( !cfgFile.is_open() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * could not open configuration file '" << cfgname.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lineno = 0;
|
||||||
|
bool mod = false; // set to true if there are non-existent paths in the file
|
||||||
|
|
||||||
|
while( cfgFile.good() )
|
||||||
|
{
|
||||||
|
cfgLine.clear();
|
||||||
|
std::getline( cfgFile, cfgLine );
|
||||||
|
++lineno;
|
||||||
|
|
||||||
|
if( cfgLine.empty() )
|
||||||
|
{
|
||||||
|
if( cfgFile.eof() )
|
||||||
|
break;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string::size_type spos = cfgLine.find_first_of( '"', 0 );
|
||||||
|
|
||||||
|
if( std::string::npos == spos )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||||
|
std::cerr << " line " << lineno << " [missing opening quote mark]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgLine.erase( 0, spos + 1 );
|
||||||
|
|
||||||
|
spos = cfgLine.find_last_of( '"' );
|
||||||
|
|
||||||
|
if( std::string::npos == spos )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||||
|
std::cerr << " line " << lineno << " [missing closing quote mark]\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgLine.erase( spos );
|
||||||
|
|
||||||
|
if( !addPath( cfgLine ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * bad config entry in config file '" << cfgname.ToUTF8() << "'\n";
|
||||||
|
std::cerr << " line " << lineno << " [not a valid path]: '";
|
||||||
|
std::cerr << cfgLine << "'\n";
|
||||||
|
mod = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgFile.close();
|
||||||
|
|
||||||
|
if( mod )
|
||||||
|
writePathList();
|
||||||
|
|
||||||
|
if( m_Paths.size() != nitems )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D_FILENAME_RESOLVER::writePathList( void )
|
||||||
|
{
|
||||||
|
if( m_ConfigDir.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * 3D configuration directory is unknown\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_Paths.empty() || 1 == m_Paths.size() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wxString cfgname = m_ConfigDir + S3D_RESOLVER_CONFIG;
|
||||||
|
std::ofstream cfgFile;
|
||||||
|
|
||||||
|
cfgFile.open( cfgname.ToUTF8(), std::ios_base::trunc );
|
||||||
|
|
||||||
|
if( !cfgFile.is_open() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * could not open configuration file '" << cfgname.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list< wxString >::const_iterator sPL = m_Paths.begin();
|
||||||
|
std::list< wxString >::const_iterator ePL = m_Paths.end();
|
||||||
|
|
||||||
|
// the first entry is the current project dir; we never add a project dir
|
||||||
|
// to the path list in the configuration file
|
||||||
|
++sPL;
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
cfgFile << "\"" << (*sPL).ToUTF8() << "\"\n";
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bad = cfgFile.bad();
|
||||||
|
cfgFile.close();
|
||||||
|
|
||||||
|
if( bad )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString S3D_FILENAME_RESOLVER::ShortenPath( const wxString& aFullPathName )
|
||||||
|
{
|
||||||
|
wxString fname = aFullPathName;
|
||||||
|
|
||||||
|
if( m_Paths.empty() )
|
||||||
|
createPathList();
|
||||||
|
|
||||||
|
std::list< wxString >::const_iterator sL = m_Paths.begin();
|
||||||
|
std::list< wxString >::const_iterator eL = m_Paths.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
wxFileName fpath( *sL, "" );
|
||||||
|
wxString fps = fpath.GetPathWithSep();
|
||||||
|
|
||||||
|
if( std::string::npos != fname.find( fps ) )
|
||||||
|
{
|
||||||
|
fname = fname.substr( fps.size() );
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
fname.Replace( wxT( "\\" ), wxT( "/" ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const std::list< wxString >* S3D_FILENAME_RESOLVER::GetPaths( void )
|
||||||
|
{
|
||||||
|
return &m_Paths;
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 3d_filename_resolver.h
|
||||||
|
* provides an extensible class to resolve 3D model paths. Initially
|
||||||
|
* the legacy behavior will be implemented and an incomplete path
|
||||||
|
* would be checked against the project directory or the KISYS3DMOD
|
||||||
|
* environment variable. In the future a configurable set of search
|
||||||
|
* paths may be specified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FILENAME_RESOLVER_3D_H
|
||||||
|
#define FILENAME_RESOLVER_3D_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include "str_rsort.h"
|
||||||
|
|
||||||
|
|
||||||
|
class S3D_FILENAME_RESOLVER
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
wxString m_ConfigDir; // 3D configuration directory
|
||||||
|
std::list< wxString > m_Paths; // list of base paths to search from
|
||||||
|
// mapping of (short) file names to resolved names
|
||||||
|
std::map< wxString, wxString, S3D::rsort_wxString > m_NameMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function checkRealPath
|
||||||
|
* checks if a file exists, is a regular file, and retrieves
|
||||||
|
* the canonical name and extension.
|
||||||
|
*
|
||||||
|
* @param aFileName [in] is the file name and path to be checked
|
||||||
|
* @param aResolvedName [out] is the canonical resolved filename
|
||||||
|
* @param aFileExtension [out] is the file's extension string
|
||||||
|
* @return true if the file was found and is a regular file
|
||||||
|
*/
|
||||||
|
bool checkRealPath( const wxString& aFileName, wxString& aResolvedName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function createPathList
|
||||||
|
* builds the path list using available information such as
|
||||||
|
* KISYS3DMOD and the 3d_path_list configuration file. Invalid
|
||||||
|
* paths are silently discarded and removed from the configuration
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* @return true if at least one valid path was found
|
||||||
|
*/
|
||||||
|
bool createPathList( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function addPath
|
||||||
|
* checks that a path is valid and adds it to the search list
|
||||||
|
*
|
||||||
|
* @param aPath is the path to be checked and added
|
||||||
|
* @return true if aPath is valid
|
||||||
|
*/
|
||||||
|
bool addPath( const wxString& aPath );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function readPathList
|
||||||
|
* reads a list of path names from a configuration file
|
||||||
|
*
|
||||||
|
* @return true if a file was found and contained at least
|
||||||
|
* one valid path
|
||||||
|
*/
|
||||||
|
bool readPathList( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function writePathList
|
||||||
|
* writes the current path list to a configuration file
|
||||||
|
*
|
||||||
|
* @return true if the path list was not empty and was
|
||||||
|
* successfully written to the configuration file
|
||||||
|
*/
|
||||||
|
bool writePathList( void );
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Function Set3DConfigDir
|
||||||
|
* sets the user's configuration directory
|
||||||
|
* for 3D models.
|
||||||
|
*
|
||||||
|
* @param aConfigDir
|
||||||
|
* @return true if the call succeeds (directory exists)
|
||||||
|
*/
|
||||||
|
bool Set3DConfigDir( const wxString& aConfigDir );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetProjectDir
|
||||||
|
* sets the current KiCad project directory as the first
|
||||||
|
* entry in the model path list
|
||||||
|
*
|
||||||
|
* @param aProjDir is the current project directory
|
||||||
|
* @param flgChanged, if specified, is set to true if the directory actually changed
|
||||||
|
* @return true if the call succeeds
|
||||||
|
*/
|
||||||
|
bool SetProjectDir( const wxString& aProjDir, bool* flgChanged = NULL );
|
||||||
|
wxString GetProjectDir( void );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function UpdatePathList
|
||||||
|
* clears the current path list and substitutes the given path
|
||||||
|
* list, updating the path configuration file on success.
|
||||||
|
*/
|
||||||
|
bool UpdatePathList( std::vector< wxString >& aPathList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ResolvePath
|
||||||
|
* determines the full path of the given file name. In the future
|
||||||
|
* remote files may be supported, in which case it is best to
|
||||||
|
* require a full URI in which case ResolvePath should check that
|
||||||
|
* the URI conforms to RFC-2396 and related documents and copies
|
||||||
|
* aFileName into aResolvedName if the URI is valid.
|
||||||
|
*/
|
||||||
|
wxString ResolvePath( const wxString& aFileName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ShortenPath
|
||||||
|
* produces a relative path based on the existing
|
||||||
|
* search directories or returns the same path if
|
||||||
|
* the path is not a superset of an existing search path.
|
||||||
|
*
|
||||||
|
* @param aFullPathName is an absolute path to shorten
|
||||||
|
* @return the shortened path or aFullPathName
|
||||||
|
*/
|
||||||
|
wxString ShortenPath( const wxString& aFullPathName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetPaths
|
||||||
|
* returns a pointer to the internal path list; the items in:load
|
||||||
|
*
|
||||||
|
* the list can be used to set up the list of search paths
|
||||||
|
* available to a 3D file browser.
|
||||||
|
*
|
||||||
|
* @return pointer to the internal path list
|
||||||
|
*/
|
||||||
|
const std::list< wxString >* GetPaths( void );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILENAME_RESOLVER_3D_H
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Cirilo Bernardo <cirilo.bernardo@gmail.com>
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@gmail.com>
|
||||||
|
* Copyright (C) 2011 Wayne Stambaugh <stambaughw@verizon.net>
|
||||||
|
* Copyright (C) 2004 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 3d_info.h
|
||||||
|
* defines the basic data associated with a single 3D model.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INFO_3D_H
|
||||||
|
#define INFO_3D_H
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct S3D_INFO
|
||||||
|
{
|
||||||
|
SGPOINT scale; ///< scaling factors for the 3D footprint shape
|
||||||
|
SGPOINT rotation; ///< an X,Y,Z rotation (unit = degrees) for the 3D shape
|
||||||
|
SGPOINT offset; ///< an offset (unit = inch) for the 3D shape
|
||||||
|
// note: the models are treated in a peculiar fashion since it is the
|
||||||
|
// SCALE which is applied first, followed by the ROTATION and finally
|
||||||
|
// the TRANSLATION/Offset (S-R-T). The usual order of operations is T-R-S.
|
||||||
|
|
||||||
|
wxString filename; ///< The 3D shape filename in 3D library
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INFO_3D_H
|
|
@ -0,0 +1,602 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <utility>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <wx/dir.h>
|
||||||
|
#include <wx/config.h>
|
||||||
|
#include <wx/stdpaths.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <3d_plugin_manager.h>
|
||||||
|
#include <plugins/3d/3d_plugin.h>
|
||||||
|
#include <3d_cache/sg/scenegraph.h>
|
||||||
|
|
||||||
|
class S3D_PLUGIN_ITEM
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
#ifdef _WIN32
|
||||||
|
HMODULE m_dlHandle;
|
||||||
|
#else
|
||||||
|
void* m_dlHandle; // handle to the opened plugin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
S3D_PLUGIN* m_plugin; // pointer to an instance
|
||||||
|
wxString m_pluginName; // plugin name
|
||||||
|
|
||||||
|
public:
|
||||||
|
S3D_PLUGIN_ITEM( const wxString& aPluginPath );
|
||||||
|
~S3D_PLUGIN_ITEM();
|
||||||
|
bool Open( void );
|
||||||
|
void Close( void );
|
||||||
|
S3D_PLUGIN* GetPlugin( void );
|
||||||
|
const wxString GetPluginName( void );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
S3D_PLUGIN_ITEM::S3D_PLUGIN_ITEM( const wxString& aPluginPath )
|
||||||
|
{
|
||||||
|
m_pluginName = aPluginPath;
|
||||||
|
m_dlHandle = NULL;
|
||||||
|
m_plugin = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
S3D_PLUGIN_ITEM::~S3D_PLUGIN_ITEM()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool S3D_PLUGIN_ITEM::Open( void )
|
||||||
|
{
|
||||||
|
if( NULL != m_dlHandle )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( m_pluginName.IsEmpty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_plugin = NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// NOTE: MSWin uses UTF-16 encoding
|
||||||
|
#if defined( UNICODE ) || defined( _UNICODE )
|
||||||
|
m_dlHandle = LoadLibrary( m_pluginName.wc_str() );
|
||||||
|
#else
|
||||||
|
m_dlHandle = LoadLibrary( m_pluginName.ToUTF8() );
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
m_dlHandle = dlopen( m_pluginName.ToUTF8(), RTLD_LAZY | RTLD_LOCAL );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( NULL == m_dlHandle )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * could not open file: '" << m_pluginName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef S3D_PLUGIN* (*pPLUGIN)( void );
|
||||||
|
pPLUGIN Get3DPlugin = (pPLUGIN) GetProcAddress( m_dlHandle, "Get3DPlugin" );
|
||||||
|
#else
|
||||||
|
S3D_PLUGIN* (*Get3DPlugin)( void );
|
||||||
|
*(void **) (&Get3DPlugin) = dlsym( m_dlHandle, "Get3DPlugin" );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( NULL == Get3DPlugin )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
std::cerr << " * [INFO] could not find symbol\n";
|
||||||
|
#else
|
||||||
|
char* err = dlerror();
|
||||||
|
std::cerr << " * [INFO] could not find symbol: '" << err << "'\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// set the 3D Model Plugin object
|
||||||
|
m_plugin = (*Get3DPlugin)();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
FreeLibrary( m_dlHandle );
|
||||||
|
#else
|
||||||
|
dlclose( m_dlHandle );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_dlHandle = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void S3D_PLUGIN_ITEM::Close( void )
|
||||||
|
{
|
||||||
|
m_plugin = NULL;
|
||||||
|
|
||||||
|
if( m_dlHandle )
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
FreeLibrary( m_dlHandle );
|
||||||
|
#else
|
||||||
|
dlclose( m_dlHandle );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_dlHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_PLUGIN* S3D_PLUGIN_ITEM::GetPlugin( void )
|
||||||
|
{
|
||||||
|
if( NULL == m_plugin && !Open() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const wxString S3D_PLUGIN_ITEM::GetPluginName( void )
|
||||||
|
{
|
||||||
|
return m_pluginName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_PLUGIN_MANAGER::S3D_PLUGIN_MANAGER()
|
||||||
|
{
|
||||||
|
// create the initial file filter list entry
|
||||||
|
m_FileFilters.push_back( _( "All Files (*.*)|*.*" ) );
|
||||||
|
|
||||||
|
// discover and load plugins
|
||||||
|
loadPlugins();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if( !m_ExtMap.empty() )
|
||||||
|
{
|
||||||
|
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::const_iterator sM = m_ExtMap.begin();
|
||||||
|
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::const_iterator eM = m_ExtMap.end();
|
||||||
|
std::cout << "* Extension [plugin name]:\n";
|
||||||
|
|
||||||
|
while( sM != eM )
|
||||||
|
{
|
||||||
|
std::cout << " + '" << sM->first.ToUTF8() << "' [";
|
||||||
|
std::cout << sM->second->GetPluginName().ToUTF8() << "]\n";
|
||||||
|
++sM;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "* No plugins available\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( !m_FileFilters.empty() )
|
||||||
|
{
|
||||||
|
/// list of file filters
|
||||||
|
std::list< wxString >::const_iterator sFF = m_FileFilters.begin();
|
||||||
|
std::list< wxString >::const_iterator eFF = m_FileFilters.end();
|
||||||
|
std::cout << "* File filters:\n";
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while( sFF != eFF )
|
||||||
|
{
|
||||||
|
std::cout << " + '" << *sFF << "'\n";
|
||||||
|
++sFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "* No file filters available\n";
|
||||||
|
}
|
||||||
|
#endif // DEBUG
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D_PLUGIN_MANAGER::~S3D_PLUGIN_MANAGER()
|
||||||
|
{
|
||||||
|
std::list< S3D_PLUGIN_ITEM* >::iterator sP = m_Plugins.begin();
|
||||||
|
std::list< S3D_PLUGIN_ITEM* >::iterator eP = m_Plugins.end();
|
||||||
|
|
||||||
|
while( sP != eP )
|
||||||
|
{
|
||||||
|
(*sP)->Close();
|
||||||
|
delete *sP;
|
||||||
|
++sP;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Plugins.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||||
|
{
|
||||||
|
std::list< std::string > pathlist;
|
||||||
|
std::list< wxString > searchpaths;
|
||||||
|
std::list< wxString > pluginlist;
|
||||||
|
wxFileName fn;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// set up to work from the build directory
|
||||||
|
fn.Assign( wxStandardPaths::Get().GetExecutablePath() );
|
||||||
|
fn.AppendDir( wxT("..") );
|
||||||
|
fn.AppendDir( wxT("plugins") );
|
||||||
|
fn.AppendDir( wxT("3d") );
|
||||||
|
|
||||||
|
std::string testpath = std::string( fn.GetPathWithSep().ToUTF8() );
|
||||||
|
checkPluginPath( testpath, searchpaths );
|
||||||
|
#endif
|
||||||
|
fn.Assign( wxStandardPaths::Get().GetPluginsDir() );
|
||||||
|
fn.AppendDir( wxT( "kicad" ) );
|
||||||
|
fn.AppendDir( wxT( "plugins" ) );
|
||||||
|
fn.AppendDir( wxT( "3d" ) );
|
||||||
|
checkPluginPath( std::string( fn.GetPathWithSep().ToUTF8() ), searchpaths );
|
||||||
|
|
||||||
|
checkPluginPath( wxT( "/usr/lib/kicad/plugins/3d" ), searchpaths );
|
||||||
|
checkPluginPath( wxT( "/usr/local/lib/kicad/plugins/3d" ), searchpaths );
|
||||||
|
checkPluginPath( wxT( "/opt/kicad/lib/kicad/plugins/3d" ), searchpaths );
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
// XXX - we want to use GetOSX... so add support for that somehow in order to avoid hard coding
|
||||||
|
// "/Library/Application Support/kicad/plugins/3d"
|
||||||
|
checkPluginPath( wxT( "/Library/Application Support/kicad/plugins/3d" ), searchpaths );
|
||||||
|
|
||||||
|
// /Library/Application Support/kicad/plugins
|
||||||
|
//fn.Assign( GetOSXKicadMachineDataDir() );
|
||||||
|
//fn.AppendDir( wxT( "plugins" ) );
|
||||||
|
//fn.AppendDir( wxT( "3d" ) );
|
||||||
|
//checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// note: GetUserDataDir() gives '.pcbnew' rather than '.kicad' since it uses the exe name;
|
||||||
|
fn.Assign( wxStandardPaths::Get().GetUserDataDir() );
|
||||||
|
fn.AppendDir( wxT( ".kicad" ) );
|
||||||
|
fn.AppendDir( wxT( "plugins" ) );
|
||||||
|
fn.AppendDir( wxT( "3d" ) );
|
||||||
|
checkPluginPath( fn.GetPathWithSep(), searchpaths );
|
||||||
|
|
||||||
|
std::list< wxString >::iterator sPL = searchpaths.begin();
|
||||||
|
std::list< wxString >::iterator ePL = searchpaths.end();
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||||
|
std::cout << "* [DEBUG] searching path: '" << (*sPL).ToUTF8() << "'\n";
|
||||||
|
#endif
|
||||||
|
listPlugins( *sPL, pluginlist );
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pluginlist.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
sPL = pluginlist.begin();
|
||||||
|
ePL = pluginlist.end();
|
||||||
|
|
||||||
|
while( sPL != ePL )
|
||||||
|
{
|
||||||
|
S3D_PLUGIN_ITEM* pp = new S3D_PLUGIN_ITEM( *sPL );
|
||||||
|
|
||||||
|
if( pp )
|
||||||
|
{
|
||||||
|
if( pp->Open() )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||||
|
std::cout << "* [DEBUG] adding plugin\n";
|
||||||
|
#endif
|
||||||
|
m_Plugins.push_back( pp );
|
||||||
|
|
||||||
|
S3D_PLUGIN* lpp = pp->GetPlugin();
|
||||||
|
|
||||||
|
if( lpp )
|
||||||
|
{
|
||||||
|
int nf = lpp->GetNFilters();
|
||||||
|
|
||||||
|
for( int i = 0; i < nf; ++i )
|
||||||
|
addFilterString( lpp->GetFileFilter( i ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
addExtensionMap( pp );
|
||||||
|
|
||||||
|
// close the loaded library
|
||||||
|
pp->Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||||
|
std::cout << "* [DEBUG] deleting plugin\n";
|
||||||
|
#endif
|
||||||
|
delete pp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++sPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << __FILE__ << ":" << __FUNCTION__ << ":" << __LINE__ << ":\n";
|
||||||
|
std::cout << "* [DEBUG] plugins loaded\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::listPlugins( const wxString& aPath,
|
||||||
|
std::list< wxString >& aPluginList )
|
||||||
|
{
|
||||||
|
// list potential plugins given a search paths
|
||||||
|
// note on typical plugin names:
|
||||||
|
// Linux: *.so, *.so.* (note: *.so.* will not be supported)
|
||||||
|
// MSWin: *.dll
|
||||||
|
// OSX: *.dylib, *.bundle
|
||||||
|
|
||||||
|
std::list< wxString > nameFilter; // filter to apply to files
|
||||||
|
wxString lName; // stores name of enumerated files
|
||||||
|
wxString fName; // full name of file
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
|
||||||
|
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.so" ) );
|
||||||
|
|
||||||
|
#elif defined _WIN32
|
||||||
|
|
||||||
|
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.dll" ) );
|
||||||
|
|
||||||
|
#elif defined __APPLE__
|
||||||
|
|
||||||
|
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.dylib" ) );
|
||||||
|
nameFilter.push_back( wxString::FromUTF8Unchecked( "*.bundle" ) );
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// note: we need to positively identify a supported OS here
|
||||||
|
// and add suffixes which may be used for 3D model plugins
|
||||||
|
// on the specific OS
|
||||||
|
#warning NOT IMPLEMENTED
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxDir wd;
|
||||||
|
wd.Open( aPath );
|
||||||
|
|
||||||
|
if( !wd.IsOpened() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxString lp = wd.GetNameWithSep();
|
||||||
|
std::list< wxString >::iterator sExt = nameFilter.begin();
|
||||||
|
std::list< wxString >::iterator eExt = nameFilter.end();
|
||||||
|
|
||||||
|
while( sExt != eExt )
|
||||||
|
{
|
||||||
|
if( wd.GetFirst( &lName, *sExt, wxDIR_FILES ) )
|
||||||
|
{
|
||||||
|
fName = lp + lName;
|
||||||
|
checkPluginName( fName, aPluginList );
|
||||||
|
|
||||||
|
while( wd.GetNext( &lName ) )
|
||||||
|
{
|
||||||
|
fName = lp + lName;
|
||||||
|
checkPluginName( fName, aPluginList );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++sExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
wd.Close();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::checkPluginName( const wxString& aPath,
|
||||||
|
std::list< wxString >& aPluginList )
|
||||||
|
{
|
||||||
|
// check the existence of a plugin name and add it to the list
|
||||||
|
|
||||||
|
if( aPath.empty() || !wxFileName::FileExists( aPath ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxFileName path( aPath );
|
||||||
|
path.Normalize();
|
||||||
|
|
||||||
|
// determine if the path is already in the list
|
||||||
|
wxString wxpath = path.GetFullPath();
|
||||||
|
std::list< wxString >::iterator bl = aPluginList.begin();
|
||||||
|
std::list< wxString >::iterator el = aPluginList.end();
|
||||||
|
|
||||||
|
while( bl != el )
|
||||||
|
{
|
||||||
|
if( 0 == (*bl).Cmp( wxpath ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
++bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
aPluginList.push_back( wxpath );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::checkPluginPath( const wxString& aPath,
|
||||||
|
std::list< wxString >& aSearchList )
|
||||||
|
{
|
||||||
|
// check the existence of a path and add it to the path search list
|
||||||
|
if( aPath.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
wxFileName path( wxFileName::DirName( aPath ) );
|
||||||
|
path.Normalize();
|
||||||
|
|
||||||
|
if( !wxFileName::DirExists( path.GetFullPath() ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// determine if the directory is already in the list
|
||||||
|
wxString wxpath = path.GetFullPath();
|
||||||
|
std::list< wxString >::iterator bl = aSearchList.begin();
|
||||||
|
std::list< wxString >::iterator el = aSearchList.end();
|
||||||
|
|
||||||
|
while( bl != el )
|
||||||
|
{
|
||||||
|
if( 0 == (*bl).Cmp( wxpath ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
++bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
aSearchList.push_back( wxpath );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::addFilterString( const wxString& aFilterString )
|
||||||
|
{
|
||||||
|
// add an entry to the file filter list
|
||||||
|
if( aFilterString.empty() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::list< wxString >::iterator sFF = m_FileFilters.begin();
|
||||||
|
std::list< wxString >::iterator eFF = m_FileFilters.end();
|
||||||
|
|
||||||
|
while( sFF != eFF )
|
||||||
|
{
|
||||||
|
if( 0 == (*sFF).Cmp( aFilterString ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
++sFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_FileFilters.push_back( aFilterString );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::addExtensionMap( S3D_PLUGIN_ITEM* aPlugin )
|
||||||
|
{
|
||||||
|
// add entries to the extension map
|
||||||
|
if( NULL == aPlugin )
|
||||||
|
return;
|
||||||
|
|
||||||
|
S3D_PLUGIN* pp = aPlugin->GetPlugin();
|
||||||
|
|
||||||
|
if( NULL == pp )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int nExt = pp->GetNExtensions();
|
||||||
|
|
||||||
|
for( int i = 0; i < nExt; ++i )
|
||||||
|
{
|
||||||
|
wxString ws = pp->GetModelExtension( i );
|
||||||
|
|
||||||
|
if( !ws.empty() )
|
||||||
|
{
|
||||||
|
m_ExtMap.insert( std::pair< const wxString, S3D_PLUGIN_ITEM* >( ws, aPlugin ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::list< wxString > const* S3D_PLUGIN_MANAGER::GetFileFilters( void ) const
|
||||||
|
{
|
||||||
|
return &m_FileFilters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCENEGRAPH* S3D_PLUGIN_MANAGER::Load3DModel( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
wxFileName raw( aFileName );
|
||||||
|
wxString ext = raw.GetExt();
|
||||||
|
|
||||||
|
std::pair < std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator,
|
||||||
|
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator > items;
|
||||||
|
|
||||||
|
items = m_ExtMap.equal_range( ext );
|
||||||
|
std::multimap< const wxString, S3D_PLUGIN_ITEM* >::iterator sL = items.first;
|
||||||
|
|
||||||
|
while( sL != items.second )
|
||||||
|
{
|
||||||
|
S3D_PLUGIN* pplug = sL->second->GetPlugin();
|
||||||
|
|
||||||
|
if( NULL != pplug && pplug->CanRender() )
|
||||||
|
{
|
||||||
|
SCENEGRAPH* sp = pplug->Load( aFileName );
|
||||||
|
|
||||||
|
if( NULL != sp )
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D_PLUGIN_MANAGER::ClosePlugins( void )
|
||||||
|
{
|
||||||
|
std::list< S3D_PLUGIN_ITEM* >::iterator sP = m_Plugins.begin();
|
||||||
|
std::list< S3D_PLUGIN_ITEM* >::iterator eP = m_Plugins.end();
|
||||||
|
|
||||||
|
while( sP != eP )
|
||||||
|
{
|
||||||
|
(*sP)->Close();
|
||||||
|
++sP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 3d_plugin_manager.h
|
||||||
|
* manages 3D model plugins
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLUGIN_MANAGER_3D_H
|
||||||
|
#define PLUGIN_MANAGER_3D_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
class wxWindow;
|
||||||
|
class S3D_PLUGIN_ITEM;
|
||||||
|
struct S3D_INFO;
|
||||||
|
class SCENEGRAPH;
|
||||||
|
|
||||||
|
class S3D_PLUGIN_MANAGER
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// list of discovered plugins
|
||||||
|
std::list< S3D_PLUGIN_ITEM* > m_Plugins;
|
||||||
|
|
||||||
|
/// mapping of extensions to available plugins
|
||||||
|
std::multimap< const wxString, S3D_PLUGIN_ITEM* > m_ExtMap;
|
||||||
|
|
||||||
|
/// list of file filters
|
||||||
|
std::list< wxString > m_FileFilters;
|
||||||
|
|
||||||
|
/// load plugins
|
||||||
|
void loadPlugins( void );
|
||||||
|
|
||||||
|
/// list potential plugins
|
||||||
|
void listPlugins( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||||
|
|
||||||
|
/// check the existence of a plugin name and add it to the list
|
||||||
|
void checkPluginName( const wxString& aPath, std::list< wxString >& aPluginList );
|
||||||
|
|
||||||
|
/// check the existence of a path and add it to the path search list
|
||||||
|
void checkPluginPath( const wxString& aPath, std::list< wxString >& aSearchList );
|
||||||
|
|
||||||
|
/// add an entry to the file filter list
|
||||||
|
void addFilterString( const wxString& aFilterString );
|
||||||
|
|
||||||
|
/// add entries to the extension map
|
||||||
|
void addExtensionMap( S3D_PLUGIN_ITEM* aPlugin );
|
||||||
|
|
||||||
|
public:
|
||||||
|
S3D_PLUGIN_MANAGER();
|
||||||
|
virtual ~S3D_PLUGIN_MANAGER();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetFileFilters
|
||||||
|
* returns the list of file filters; this will contain at least
|
||||||
|
* the default "All Files (*.*)|*.*" and the file filters supported
|
||||||
|
* by any available plugins
|
||||||
|
*
|
||||||
|
* @return a pointer to the internal filter list
|
||||||
|
*/
|
||||||
|
std::list< wxString > const* GetFileFilters( void ) const;
|
||||||
|
|
||||||
|
SCENEGRAPH* Load3DModel( const wxString& aFileName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ClosePlugins
|
||||||
|
* iterates through all discovered plugins and closes them to
|
||||||
|
* reclaim memory. The individual plugins will be automatically
|
||||||
|
* reloaded as calls are made to load specific models.
|
||||||
|
*/
|
||||||
|
void ClosePlugins( void );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLUGIN_MANAGER_3D_H
|
|
@ -0,0 +1,3 @@
|
||||||
|
# unset CMAKE_CXX_FLAGS because it's contaminated with too many options
|
||||||
|
set( CMAKE_CXX_FLAGS "" )
|
||||||
|
add_subdirectory( sg )
|
|
@ -0,0 +1,132 @@
|
||||||
|
This directory will contain code used in the refactoring of
|
||||||
|
the 3D viewer and 3D model management.
|
||||||
|
|
||||||
|
Notes on building the test program on Linux:
|
||||||
|
1. Configure to build KiCad; ensue you have "-DS3D_TEST=ON" to
|
||||||
|
enable the "test3dmm" test program.
|
||||||
|
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DKICAD_SCRIPTING=ON \
|
||||||
|
-DKICAD_SCRIPTING_MODULES=ON \
|
||||||
|
-DBUILD_GITHUB_PLUGIN=ON \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
|
-DKICAD_SKIP_BOOST=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DS3D_TEST=ON \
|
||||||
|
-DCMAKE_VERBOSE_MAKEFILE=ON ..
|
||||||
|
|
||||||
|
2. After configuring to build KiCad, descend into the 3dv build
|
||||||
|
directory:
|
||||||
|
|
||||||
|
cd 3dv
|
||||||
|
|
||||||
|
3. Build all files in the 3dv directory:
|
||||||
|
|
||||||
|
make -j8
|
||||||
|
|
||||||
|
4. Install to a directory within the build directory:
|
||||||
|
|
||||||
|
mkdir inst
|
||||||
|
make install DESTDIR=./inst
|
||||||
|
|
||||||
|
5. Set LD_LIBRARY_PATH so that the 3d manager code can be found:
|
||||||
|
|
||||||
|
export LD_LIBRARY_PATH=${PWD}/inst/usr/lib/kicad
|
||||||
|
|
||||||
|
( note: the previous step may have installed the library in
|
||||||
|
${PWD}/inst/usr/local/lib/kicad )
|
||||||
|
There is no need to include the plugins directory in
|
||||||
|
LD_LIBRARY_PATH since the manager should magically find
|
||||||
|
plugins there and load them.
|
||||||
|
|
||||||
|
6. Run the test program:
|
||||||
|
|
||||||
|
./inst/usr/bin/test3dmm
|
||||||
|
|
||||||
|
|
||||||
|
===========================
|
||||||
|
For OSX and MSWin
|
||||||
|
===========================
|
||||||
|
The dynamic plugin has only been built and tested on Linux; until
|
||||||
|
the dynamic plugin system can be made to work on MSWin and OSX, those
|
||||||
|
systems will not be able to use the 3D cache framework for anything
|
||||||
|
other than a filename resolver and model file browser. Without the
|
||||||
|
plugins the 3D viewer will not be able to use the new framework for
|
||||||
|
loading generic 3D model formats.
|
||||||
|
|
||||||
|
Dynamic plugins are managed in 3dv/3d_plugin_manager.cpp so that is the
|
||||||
|
only source file which developers need to modify to support plugins
|
||||||
|
on OSX and MSWin
|
||||||
|
|
||||||
|
1. OSX:
|
||||||
|
+ In general some attention is required wherever the __APPLE__
|
||||||
|
macro is found
|
||||||
|
|
||||||
|
+ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||||
|
In this function a list of reasonable search paths must be provided;
|
||||||
|
these paths will be checked for the existence of a plugin
|
||||||
|
|
||||||
|
+ void S3D_PLUGIN_MANAGER::listPlugins( ... )
|
||||||
|
In this function the list of suffixes to use in the plugin
|
||||||
|
discovery should be checked to ensure that they comply with
|
||||||
|
the expectations of OSX
|
||||||
|
|
||||||
|
+ bool S3D_PLUGIN_ITEM::Open( void )
|
||||||
|
This function loads the dynamic plugins. If OSX use the gcc dlopen
|
||||||
|
set of functions then there may be no further work to be done here.
|
||||||
|
|
||||||
|
2. MSWin:
|
||||||
|
+ In general some attention is required wherever the _WIN32 macro is found
|
||||||
|
|
||||||
|
+ void S3D_PLUGIN_MANAGER::loadPlugins( void )
|
||||||
|
In this function a list of reasonable search paths must be provided;
|
||||||
|
these paths will be checked for the existence of a plugin
|
||||||
|
|
||||||
|
+ bool S3D_PLUGIN_ITEM::Open( void )
|
||||||
|
This function loads the dynamic plugins. Since the gcc dlopen family
|
||||||
|
of functions do not exist on MSWin, some _WIN32 specific code must
|
||||||
|
be added to handle the library loading.
|
||||||
|
|
||||||
|
===
|
||||||
|
|
||||||
|
Q. How do you know the plugin system is working?
|
||||||
|
A. The plugin system is working if the dummy plugin is located and loaded.
|
||||||
|
If the plugin is located and the software was built with the DEBUG flag,
|
||||||
|
you will see a group of messages which, among other things, advertises
|
||||||
|
the file types supported by the dummy plugin:
|
||||||
|
|
||||||
|
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:404:
|
||||||
|
* [DEBUG] searching path: '~/usr/lib/kicad/plugins'
|
||||||
|
XXX - Initializing S3D_PLUGIN_DUMMY
|
||||||
|
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:426:
|
||||||
|
* [DEBUG] adding plugin
|
||||||
|
XXX - Destroying S3D_PLUGIN_DUMMY
|
||||||
|
~/code/kicad/branch_3d/3dv/3d_plugin_manager.cpp:loadPlugins:461:
|
||||||
|
* [DEBUG] plugins loaded
|
||||||
|
* Extension [plugin name]:
|
||||||
|
+ 'IDF' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'IGES' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'IGS' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'STEP' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'STP' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'WRL' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'X3D' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'idf' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'iges' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'igs' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'step' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'stp' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'wrl' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
+ 'x3d' [~/usr/lib/kicad/plugins/libs3d_plugin_dummy.so]
|
||||||
|
* File filters:
|
||||||
|
+ 'All Files (*.*)|*.*'
|
||||||
|
+ 'VRML 1.0/2.0 (*.wrl;*.WRL)|*.wrl;*.WRL'
|
||||||
|
+ 'X3D (*.x3d;*.X3D)|*.x3d;*.X3D'
|
||||||
|
+ 'IDF 2.0/3.0 (*.idf;*.IDF)|*.idf;*.IDF'
|
||||||
|
+ 'IGESv5.3 (*.igs;*.iges;*.IGS;*.IGES)|*.igs;*.iges;*.IGS;*.IGES'
|
||||||
|
+ 'STEP (*.stp;*.step;*.STP;*.STEP)|*.stp;*.step;*.STP;*.STEP'
|
||||||
|
|
||||||
|
The supported file extensions should appear in the list of file filters within the
|
||||||
|
model selection dialog; if no plugins are loaded then the only available file
|
||||||
|
filter will be the wildcard filter *.*
|
|
@ -0,0 +1,297 @@
|
||||||
|
/* ANSI and traditional C compatability macros
|
||||||
|
Copyright 1991, 1992, 1*993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
/* ANSI and traditional C compatibility macros
|
||||||
|
|
||||||
|
ANSI C is assumed if __STDC__ is #defined.
|
||||||
|
|
||||||
|
Macro ANSI C definition Traditional C definition
|
||||||
|
----- ---- - ---------- ----------- - ----------
|
||||||
|
ANSI_PROTOTYPES 1 not defined
|
||||||
|
PTR `void *' `char *'
|
||||||
|
PTRCONST `void *const' `char *'
|
||||||
|
LONG_DOUBLE `long double' `double'
|
||||||
|
const not defined `'
|
||||||
|
volatile not defined `'
|
||||||
|
signed not defined `'
|
||||||
|
VA_START(ap, var) va_start(ap, var) va_start(ap)
|
||||||
|
|
||||||
|
Note that it is safe to write "void foo();" indicating a function
|
||||||
|
with no return value, in all K+R compilers we have been able to test.
|
||||||
|
|
||||||
|
For declaring functions with prototypes, we also provide these:
|
||||||
|
|
||||||
|
PARAMS ((prototype))
|
||||||
|
-- for functions which take a fixed number of arguments. Use this
|
||||||
|
when declaring the function. When defining the function, write a
|
||||||
|
K+R style argument list. For example:
|
||||||
|
|
||||||
|
char *strcpy PARAMS ((char *dest, char *source));
|
||||||
|
...
|
||||||
|
char *
|
||||||
|
strcpy (dest, source)
|
||||||
|
char *dest;
|
||||||
|
char *source;
|
||||||
|
{ ... }
|
||||||
|
|
||||||
|
VPARAMS ((prototype, ...))
|
||||||
|
-- for functions which take a variable number of arguments. Use
|
||||||
|
PARAMS to declare the function, VPARAMS to define it. For example:
|
||||||
|
|
||||||
|
int printf PARAMS ((const char *format, ...));
|
||||||
|
...
|
||||||
|
int
|
||||||
|
printf VPARAMS ((const char *format, ...))
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
For writing functions which take variable numbers of arguments, we
|
||||||
|
also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros. These
|
||||||
|
hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
|
||||||
|
thoroughly than the simple VA_START() macro mentioned above.
|
||||||
|
|
||||||
|
VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
|
||||||
|
Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
|
||||||
|
corresponding to the list of fixed arguments. Then use va_arg
|
||||||
|
normally to get the variable arguments, or pass your va_list object
|
||||||
|
around. You do not declare the va_list yourself; VA_OPEN does it
|
||||||
|
for you.
|
||||||
|
|
||||||
|
Here is a complete example:
|
||||||
|
|
||||||
|
int
|
||||||
|
printf VPARAMS ((const char *format, ...))
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
VA_OPEN (ap, format);
|
||||||
|
VA_FIXEDARG (ap, const char *, format);
|
||||||
|
|
||||||
|
result = vfprintf (stdout, format, ap);
|
||||||
|
VA_CLOSE (ap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
You can declare variables either before or after the VA_OPEN,
|
||||||
|
VA_FIXEDARG sequence. Also, VA_OPEN and VA_CLOSE are the beginning
|
||||||
|
and end of a block. They must appear at the same nesting level,
|
||||||
|
and any variables declared after VA_OPEN go out of scope at
|
||||||
|
VA_CLOSE. Unfortunately, with a K+R compiler, that includes the
|
||||||
|
argument list. You can have multiple instances of VA_OPEN/VA_CLOSE
|
||||||
|
pairs in a single function in case you need to traverse the
|
||||||
|
argument list more than once.
|
||||||
|
|
||||||
|
For ease of writing code which uses GCC extensions but needs to be
|
||||||
|
portable to other compilers, we provide the GCC_VERSION macro that
|
||||||
|
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
|
||||||
|
wrappers around __attribute__. Also, __extension__ will be #defined
|
||||||
|
to nothing if it doesn't work. See below.
|
||||||
|
|
||||||
|
This header also defines a lot of obsolete macros:
|
||||||
|
CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
|
||||||
|
AND, DOTS, NOARGS. Don't use them. */
|
||||||
|
|
||||||
|
#ifndef _ANSIDECL_H
|
||||||
|
#define _ANSIDECL_H 1
|
||||||
|
|
||||||
|
/* Every source file includes this file,
|
||||||
|
so they will all get the switch for lint. */
|
||||||
|
/* LINTLIBRARY */
|
||||||
|
|
||||||
|
/* Using MACRO(x,y) in cpp #if conditionals does not work with some
|
||||||
|
older preprocessors. Thus we can't define something like this:
|
||||||
|
|
||||||
|
#define HAVE_GCC_VERSION(MAJOR, MINOR) \
|
||||||
|
(__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
|
||||||
|
|
||||||
|
and then test "#if HAVE_GCC_VERSION(2,7)".
|
||||||
|
|
||||||
|
So instead we use the macro below and test it against specific values. */
|
||||||
|
|
||||||
|
/* This macro simplifies testing whether we are using gcc, and if it
|
||||||
|
is of a particular mini*mum version. (Both major & minor numbers are
|
||||||
|
significant.) This macro will evaluate to 0 if we are not using
|
||||||
|
gcc at all. */
|
||||||
|
#ifndef GCC_VERSION
|
||||||
|
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
|
||||||
|
#endif /* GCC_VERSION */
|
||||||
|
|
||||||
|
#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus))
|
||||||
|
/* All known AIX compilers implement these things (but don't always
|
||||||
|
define __STDC__). The RISC/OS MIPS compiler defines these things
|
||||||
|
in SVR4 mode, but does not define __STDC__. */
|
||||||
|
/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
|
||||||
|
C ++ compilers, does not define __STDC__, though it acts as if this
|
||||||
|
was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
|
||||||
|
|
||||||
|
#define ANSI_PROTOTYPES 1
|
||||||
|
#define PTR void *
|
||||||
|
#define PTRCONST void *const
|
||||||
|
#define LONG_DOUBLE long double
|
||||||
|
|
||||||
|
#define PARAMS(ARGS) ARGS
|
||||||
|
#define VPARAMS(ARGS) ARGS
|
||||||
|
#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR)
|
||||||
|
|
||||||
|
/* variadic function helper macros */
|
||||||
|
/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
|
||||||
|
use without inhibiting further decls and without declaring an
|
||||||
|
actual variable. */
|
||||||
|
#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP, VAR); { struct Qdmy
|
||||||
|
#define VA_CLOSE(AP) } va_end(AP); }
|
||||||
|
#define VA_FIXEDARG(AP, T, N) struct Qdmy
|
||||||
|
|
||||||
|
#undef const
|
||||||
|
#undef volatile
|
||||||
|
#undef signed
|
||||||
|
|
||||||
|
/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
|
||||||
|
it too, but it's not in C89. */
|
||||||
|
#undef inline
|
||||||
|
#if __STDC_VERSION__ > 199901L
|
||||||
|
/* it's a keyword */
|
||||||
|
#else
|
||||||
|
# if GCC_VERSION >= 2007
|
||||||
|
# define inline __inline__ /* __inline__ prevents -pedantic warnings */
|
||||||
|
# else
|
||||||
|
# define inline /* nothing */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* These are obsolete. Do not use. */
|
||||||
|
#ifndef IN_GCC
|
||||||
|
#define CONST const
|
||||||
|
#define VOLATILE volatile
|
||||||
|
#define SIGNED signed
|
||||||
|
|
||||||
|
#define PROTO(type, name, arglist) type name arglist
|
||||||
|
#define EXFUN(name, proto) name proto
|
||||||
|
#define DEFUN(name, arglist, args) name(args)
|
||||||
|
#define DEFUN_VOID(name) name(void)
|
||||||
|
#define AND ,
|
||||||
|
#define DOTS , ...
|
||||||
|
#define NOARGS void
|
||||||
|
#endif /* ! IN_GCC */
|
||||||
|
|
||||||
|
#else /* Not ANSI C. */
|
||||||
|
|
||||||
|
#undef ANSI_PROTOTYPES
|
||||||
|
#define PTR char *
|
||||||
|
#define PTRCONST PTR
|
||||||
|
#define LONG_DOUBLE double
|
||||||
|
|
||||||
|
#define PARAMS(args) ()
|
||||||
|
#define VPARAMS(args) (va_alist) va_dcl
|
||||||
|
#define VA_START(va_list, var) va_start(va_list)
|
||||||
|
|
||||||
|
#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP); { struct Qdmy
|
||||||
|
#define VA_CLOSE(AP) } va_end(AP); }
|
||||||
|
#define VA_FIXEDARG(AP, TYPE, NAME) TYPE NAME = va_arg(AP, TYPE)
|
||||||
|
|
||||||
|
/* some systems define these in header files for non-ansi mode */
|
||||||
|
#undef const
|
||||||
|
#undef volatile
|
||||||
|
#undef signed
|
||||||
|
#undef inline
|
||||||
|
#define const
|
||||||
|
#define volatile
|
||||||
|
#define signed
|
||||||
|
#define inline
|
||||||
|
|
||||||
|
#ifndef IN_GCC
|
||||||
|
#define CONST
|
||||||
|
#define VOLATILE
|
||||||
|
#define SIGNED
|
||||||
|
|
||||||
|
#define PROTO(type, name, arglist) type name ()
|
||||||
|
#define EXFUN(name, proto) name()
|
||||||
|
#define DEFUN(name, arglist, args) name arglist args;
|
||||||
|
#define DEFUN_VOID(name) name()
|
||||||
|
#define AND ;
|
||||||
|
#define DOTS
|
||||||
|
#define NOARGS
|
||||||
|
#endif /* ! IN_GCC */
|
||||||
|
|
||||||
|
#endif /* ANSI C. */
|
||||||
|
|
||||||
|
/* Define macros for some gcc attributes. This permits us to use the
|
||||||
|
macros freely, and know that they will come into play for the
|
||||||
|
version of gcc in which they are supported. */
|
||||||
|
|
||||||
|
#if (GCC_VERSION < 2007)
|
||||||
|
# define __attribute__(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
|
||||||
|
#ifndef ATTRIBUTE_MALLOC
|
||||||
|
# if (GCC_VERSION >= 2096)
|
||||||
|
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_MALLOC
|
||||||
|
# endif /* GNUC >= 2.96 */
|
||||||
|
#endif /* ATTRIBUTE_MALLOC */
|
||||||
|
|
||||||
|
/* Attributes on labels were valid as of gcc 2.93. */
|
||||||
|
#ifndef ATTRIBUTE_UNUSED_LABEL
|
||||||
|
# if (GCC_VERSION >= 2093)
|
||||||
|
# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
|
||||||
|
# else
|
||||||
|
# define ATTRIBUTE_UNUSED_LABEL
|
||||||
|
# endif /* GNUC >= 2.93 */
|
||||||
|
#endif /* ATTRIBUTE_UNUSED_LABEL */
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_UNUSED
|
||||||
|
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||||
|
#endif /* ATTRIBUTE_UNUSED */
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_NORETURN
|
||||||
|
#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||||
|
#endif /* ATTRIBUTE_NORETURN */
|
||||||
|
|
||||||
|
#ifndef ATTRIBUTE_PRINTF
|
||||||
|
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
|
||||||
|
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
|
||||||
|
#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
|
||||||
|
#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
|
||||||
|
#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
|
||||||
|
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
|
||||||
|
#endif /* ATTRIBUTE_PRINTF */
|
||||||
|
|
||||||
|
/* We use __extension__ in some places to suppress -pedantic warnings
|
||||||
|
about GCC extensions. This feature didn't work properly before
|
||||||
|
gcc 2.8. */
|
||||||
|
#if GCC_VERSION < 2008
|
||||||
|
#define __extension__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Bootstrap support: Adjust certain macros defined by Autoconf,
|
||||||
|
which are only valid for the stage1 compiler. If we detect
|
||||||
|
a modern version of GCC, we are probably in stage2 or beyond,
|
||||||
|
so unconditionally reset the values. Note that const, inline,
|
||||||
|
etc. have been dealt with above. */
|
||||||
|
#if (GCC_VERSION >= 2007)
|
||||||
|
# ifndef HAVE_LONG_DOUBLE
|
||||||
|
# define HAVE_LONG_DOUBLE 1
|
||||||
|
# endif
|
||||||
|
#endif /* GCC >= 2.7 */
|
||||||
|
|
||||||
|
#endif /* ansidecl.h */
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <wx/filename.h>
|
||||||
|
#include <3d_info.h>
|
||||||
|
#include <3d_cache.h>
|
||||||
|
#include <sg/ifsg_api.h>
|
||||||
|
|
||||||
|
#include "3d_cache_dialogs.h"
|
||||||
|
#include "dialog_config_3dpath.h"
|
||||||
|
#include "dialog_select_3dmodel.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||||
|
wxString& prevModelSelectDir, int& prevModelWildcard, S3D_INFO* aModel )
|
||||||
|
{
|
||||||
|
DLG_SEL_3DMODEL* dm = new DLG_SEL_3DMODEL( aParent, aCache,
|
||||||
|
prevModelSelectDir, prevModelWildcard );
|
||||||
|
|
||||||
|
if( wxID_OK == dm->ShowModal() )
|
||||||
|
{
|
||||||
|
// retrieve the data entry for the 3D model
|
||||||
|
dm->GetModelData( aModel );
|
||||||
|
|
||||||
|
// remember the previous settings
|
||||||
|
prevModelWildcard = dm->GetFilterIndex();
|
||||||
|
wxFileName name( dm->GetPath() );
|
||||||
|
name.Normalize();
|
||||||
|
prevModelSelectDir = name.GetPath();
|
||||||
|
|
||||||
|
delete dm;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dm;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||||
|
{
|
||||||
|
DLG_CFG_3DPATH* dp = new DLG_CFG_3DPATH( aParent, aResolver );
|
||||||
|
|
||||||
|
if( wxID_OK == dp->ShowModal() )
|
||||||
|
{
|
||||||
|
delete dp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dp;
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CACHE_DIALOGS_3D_H
|
||||||
|
#define CACHE_DIALOGS_3D_H
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
|
||||||
|
class S3D_CACHE;
|
||||||
|
class S3D_FILENAME_RESOLVER;
|
||||||
|
struct S3D_INFO;
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
bool Select3DModel( wxWindow* aParent, S3D_CACHE* aCache,
|
||||||
|
wxString& prevModelSelectDir, int& prevModelWildcard, S3D_INFO* aModel );
|
||||||
|
|
||||||
|
bool Configure3DPaths( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CACHE_DIALOGS_3D_H
|
|
@ -0,0 +1,257 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <cstdlib>
|
||||||
|
#include <list>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <3d_cache.h>
|
||||||
|
|
||||||
|
#include "dialog_config_3dpath.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
btnEditPath = wxID_HIGHEST + 1,
|
||||||
|
btnAddPath,
|
||||||
|
btnDeletePath,
|
||||||
|
lbPathList
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
wxBEGIN_EVENT_TABLE( DLG_CFG_3DPATH, wxDialog )
|
||||||
|
EVT_BUTTON( wxID_OK, DLG_CFG_3DPATH::OnOK )
|
||||||
|
EVT_BUTTON( wxID_CANCEL, DLG_CFG_3DPATH::OnExit )
|
||||||
|
EVT_BUTTON( btnEditPath, DLG_CFG_3DPATH::EditPath )
|
||||||
|
EVT_BUTTON( btnAddPath, DLG_CFG_3DPATH::AddPath )
|
||||||
|
EVT_BUTTON( btnDeletePath, DLG_CFG_3DPATH::DeletePath )
|
||||||
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
DLG_CFG_3DPATH::DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver )
|
||||||
|
: wxDialog( aParent, -1, _( "3D Model Path Configuration" ),
|
||||||
|
wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX | wxSYSTEM_MENU
|
||||||
|
| wxRESIZE_BORDER | wxMINIMIZE_BOX )
|
||||||
|
{
|
||||||
|
resolver = aResolver;
|
||||||
|
|
||||||
|
Bind( wxEVT_LIST_ITEM_ACTIVATED, &DLG_CFG_3DPATH::EditPath, this, lbPathList );
|
||||||
|
Bind( wxEVT_LIST_ITEM_SELECTED, &DLG_CFG_3DPATH::PathSelect, this, lbPathList );
|
||||||
|
Bind( wxEVT_LIST_ITEM_DESELECTED, &DLG_CFG_3DPATH::PathSelect, this, lbPathList );
|
||||||
|
|
||||||
|
wxBoxSizer *vboxMain = new wxBoxSizer( wxVERTICAL );
|
||||||
|
wxBoxSizer *vboxSide = new wxBoxSizer( wxVERTICAL );
|
||||||
|
wxBoxSizer* hboxTop = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hboxBot = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
|
||||||
|
pathList = new wxListView( this, lbPathList, wxDefaultPosition, wxSize( 400, 200 ),
|
||||||
|
wxLC_REPORT | wxLC_NO_HEADER | wxLC_SINGLE_SEL );
|
||||||
|
|
||||||
|
pathList->AppendColumn( wxEmptyString );
|
||||||
|
|
||||||
|
editButton = new wxButton( this, btnEditPath, _( "Edit" ),
|
||||||
|
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||||
|
|
||||||
|
editButton->Enable( false );
|
||||||
|
|
||||||
|
wxButton* addButton = new wxButton( this, btnAddPath, _( "Add" ),
|
||||||
|
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||||
|
|
||||||
|
deleteButton = new wxButton( this, btnDeletePath, _( "Delete" ),
|
||||||
|
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||||
|
|
||||||
|
deleteButton->Enable( false );
|
||||||
|
|
||||||
|
wxButton* okButton = new wxButton( this, wxID_OK, _( "Ok" ),
|
||||||
|
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||||
|
|
||||||
|
wxButton* cancelButton = new wxButton( this, wxID_CANCEL, _( "Cancel" ),
|
||||||
|
wxDefaultPosition, wxSize( 100, 30 ) );
|
||||||
|
|
||||||
|
vboxSide->Add( editButton, 0, wxALL, 10 );
|
||||||
|
vboxSide->Add( addButton, 0, wxALL, 10 );
|
||||||
|
vboxSide->Add( deleteButton, 0, wxALL, 10 );
|
||||||
|
|
||||||
|
hboxTop->Add( pathList, 1, wxEXPAND | wxALL, 10 );
|
||||||
|
hboxTop->Add( vboxSide, 0, wxEXPAND | wxALL, 10 );
|
||||||
|
|
||||||
|
hboxBot->Add( okButton, 0, wxALL, 10 );
|
||||||
|
hboxBot->Add( cancelButton, 0, wxALL, 10 );
|
||||||
|
|
||||||
|
vboxMain->Add( hboxTop, 1, wxEXPAND | wxALL, 10 );
|
||||||
|
vboxMain->Add( hboxBot, 0, wxEXPAND | wxALL, 10 );
|
||||||
|
|
||||||
|
if( resolver )
|
||||||
|
{
|
||||||
|
const std::list< wxString >* pl = resolver->GetPaths();
|
||||||
|
std::list< wxString >::const_iterator sL = pl->begin();
|
||||||
|
std::list< wxString >::const_iterator eL = pl->end();
|
||||||
|
|
||||||
|
// always skip the first entry which is the current project dir
|
||||||
|
if( sL != eL )
|
||||||
|
++sL;
|
||||||
|
|
||||||
|
long i = 0;
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
m_paths.push_back( *sL );
|
||||||
|
pathList->InsertItem( i, *sL );
|
||||||
|
++i;
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSizerAndFit( vboxMain );
|
||||||
|
Centre();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::OnExit( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( IsModal() )
|
||||||
|
EndModal( wxID_EXIT );
|
||||||
|
else
|
||||||
|
Close( true );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::OnOK( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( resolver )
|
||||||
|
resolver->UpdatePathList( m_paths );
|
||||||
|
|
||||||
|
if( IsModal() )
|
||||||
|
EndModal( wxID_OK );
|
||||||
|
else
|
||||||
|
Close( true );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::EditPath( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
long nItem = pathList->GetFirstSelected();
|
||||||
|
wxString tmpname = m_paths[ nItem ];
|
||||||
|
|
||||||
|
wxDirDialog* dd = new wxDirDialog( this, _( "Change 3D model directory" ),
|
||||||
|
m_paths[ nItem ] );
|
||||||
|
|
||||||
|
if( wxID_OK == dd->ShowModal() )
|
||||||
|
{
|
||||||
|
wxFileName path( wxFileName::DirName( dd->GetPath() ) );
|
||||||
|
path.Normalize();
|
||||||
|
wxString newname = path.GetPath();
|
||||||
|
|
||||||
|
if( tmpname.Cmp( newname ) )
|
||||||
|
{
|
||||||
|
pathList->DeleteItem( nItem );
|
||||||
|
pathList->InsertItem( nItem, newname );
|
||||||
|
m_paths[ nItem ] = newname;
|
||||||
|
pathList->Focus( nItem );
|
||||||
|
editButton->Enable( false );
|
||||||
|
deleteButton->Enable( false );
|
||||||
|
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dd;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::AddPath( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
wxDirDialog* dd = new wxDirDialog( this, _( "Add a 3D model directory" ) );
|
||||||
|
|
||||||
|
if( wxID_OK == dd->ShowModal() )
|
||||||
|
{
|
||||||
|
wxFileName path( wxFileName::DirName( dd->GetPath() ) );
|
||||||
|
path.Normalize();
|
||||||
|
wxString newname = path.GetPath();
|
||||||
|
|
||||||
|
m_paths.push_back( newname );
|
||||||
|
pathList->InsertItem( pathList->GetItemCount(), *m_paths.rbegin() );
|
||||||
|
pathList->Focus( pathList->GetItemCount() -1 );
|
||||||
|
editButton->Enable( false );
|
||||||
|
deleteButton->Enable( false );
|
||||||
|
pathList->SetColumnWidth(0, wxLIST_AUTOSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete dd;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::DeletePath( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
long nItem = pathList->GetFirstSelected();
|
||||||
|
|
||||||
|
if( -1 == nItem )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_paths.erase( m_paths.begin() + nItem );
|
||||||
|
pathList->DeleteItem( nItem );
|
||||||
|
|
||||||
|
if( m_paths.size() > 0 )
|
||||||
|
{
|
||||||
|
if( nItem > 0 )
|
||||||
|
--nItem;
|
||||||
|
|
||||||
|
pathList->Select( nItem );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
editButton->Enable( false );
|
||||||
|
deleteButton->Enable( false );
|
||||||
|
pathList->Select( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_CFG_3DPATH::PathSelect( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
long nItem = pathList->GetFirstSelected();
|
||||||
|
|
||||||
|
if( -1 == nItem )
|
||||||
|
{
|
||||||
|
editButton->Enable( false );
|
||||||
|
deleteButton->Enable( false );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
editButton->Enable( true );
|
||||||
|
deleteButton->Enable( true );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 dialog_config_3dpath.h
|
||||||
|
* creates a dialog to edit the default search paths for 3D model files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DIALOG_CONFIG_3DPATH_H
|
||||||
|
#define DIALOG_CONFIG_3DPATH_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/listctrl.h>
|
||||||
|
|
||||||
|
class S3D_FILENAME_RESOLVER;
|
||||||
|
|
||||||
|
class DLG_CFG_3DPATH : public wxDialog
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
wxListView* pathList;
|
||||||
|
wxButton* editButton;
|
||||||
|
wxButton* deleteButton;
|
||||||
|
|
||||||
|
S3D_FILENAME_RESOLVER* resolver;
|
||||||
|
std::vector< wxString > m_paths;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DLG_CFG_3DPATH( wxWindow* aParent, S3D_FILENAME_RESOLVER* aResolver );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnExit( wxCommandEvent& event );
|
||||||
|
void OnOK( wxCommandEvent& event );
|
||||||
|
void EditPath( wxCommandEvent& event );
|
||||||
|
void AddPath( wxCommandEvent& event );
|
||||||
|
void DeletePath( wxCommandEvent& event );
|
||||||
|
void PathSelect( wxCommandEvent& event );
|
||||||
|
|
||||||
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOG_CONFIG_3DPATH_H
|
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache.h>
|
||||||
|
#include "dialog_select_3dmodel.h"
|
||||||
|
#include "panel_prev_model.h"
|
||||||
|
|
||||||
|
static S3D_CACHE* mm = NULL;
|
||||||
|
static wxFileDialog* fm = NULL;
|
||||||
|
|
||||||
|
static wxWindow* mkPreviewPanel( wxWindow* aParent )
|
||||||
|
{
|
||||||
|
PANEL_PREV_3D* pp = new PANEL_PREV_3D( aParent, true );
|
||||||
|
pp->SetModelManager( mm );
|
||||||
|
pp->SetFileSelectorDlg( fm );
|
||||||
|
|
||||||
|
return (wxWindow*)pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxBEGIN_EVENT_TABLE( DLG_SEL_3DMODEL, wxFileDialog )
|
||||||
|
EVT_BUTTON( wxID_OK, DLG_SEL_3DMODEL::OnOK )
|
||||||
|
EVT_BUTTON( wxID_CANCEL, DLG_SEL_3DMODEL::OnExit )
|
||||||
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
DLG_SEL_3DMODEL::DLG_SEL_3DMODEL( wxWindow* aParent, S3D_CACHE* aManager,
|
||||||
|
const wxString& aDefaultDir, int aFilterIndex )
|
||||||
|
: wxFileDialog( aParent, _( "Select a 3D Model" ), aDefaultDir )
|
||||||
|
{
|
||||||
|
m_manager = aManager;
|
||||||
|
mm = aManager;
|
||||||
|
fm = this;
|
||||||
|
|
||||||
|
long ws = GetWindowStyleFlag();
|
||||||
|
ws |= wxFD_FILE_MUST_EXIST;
|
||||||
|
SetWindowStyleFlag( ws );
|
||||||
|
SetExtraControlCreator( mkPreviewPanel );
|
||||||
|
|
||||||
|
if( NULL != m_manager )
|
||||||
|
{
|
||||||
|
std::list< wxString > const* fl = m_manager->GetFileFilters();
|
||||||
|
std::list< wxString >::const_iterator sL = fl->begin();
|
||||||
|
std::list< wxString >::const_iterator eL = fl->end();
|
||||||
|
wxString filter;
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
filter.Append( *sL );
|
||||||
|
|
||||||
|
++sL;
|
||||||
|
|
||||||
|
if( sL != eL )
|
||||||
|
filter.Append( wxT( "|" ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !filter.empty() )
|
||||||
|
SetWildcard( filter );
|
||||||
|
|
||||||
|
if( aFilterIndex >= 0 && aFilterIndex < (int)fl->size() )
|
||||||
|
SetFilterIndex( aFilterIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_SEL_3DMODEL::OnExit( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( IsModal() )
|
||||||
|
EndModal( wxID_EXIT );
|
||||||
|
else
|
||||||
|
Close( true );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_SEL_3DMODEL::OnOK( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( IsModal() )
|
||||||
|
EndModal( wxID_OK );
|
||||||
|
else
|
||||||
|
Close( true );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DLG_SEL_3DMODEL::GetModelData( S3D_INFO* aModel )
|
||||||
|
{
|
||||||
|
PANEL_PREV_3D* pp = (PANEL_PREV_3D*)GetExtraControl();
|
||||||
|
|
||||||
|
if( pp )
|
||||||
|
pp->GetModelData( aModel );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 dialog_select_3dmodel.h
|
||||||
|
* creates a dialog to select 3D model files
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DIALOG_SELECT_3DMODEL_H
|
||||||
|
#define DIALOG_SELECT_3DMODEL_H
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/filedlg.h>
|
||||||
|
|
||||||
|
class S3D_CACHE;
|
||||||
|
class S3D_INFO;
|
||||||
|
|
||||||
|
class DLG_SEL_3DMODEL : public wxFileDialog
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
S3D_CACHE* m_manager;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DLG_SEL_3DMODEL( wxWindow* aParent, S3D_CACHE* aManager,
|
||||||
|
const wxString& aDefaultDir, int aFilterIndex );
|
||||||
|
|
||||||
|
// Retrieve model data
|
||||||
|
void GetModelData( S3D_INFO* aModel );
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnExit( wxCommandEvent& event );
|
||||||
|
void OnOK( wxCommandEvent& event );
|
||||||
|
|
||||||
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOG_SELECT_3DMODEL_H
|
|
@ -0,0 +1,634 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_model_viewer/c3d_model_viewer.h>
|
||||||
|
#include <3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h>
|
||||||
|
#include <common_ogl/cogl_att_list.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <wx/sizer.h>
|
||||||
|
#include <wx/choice.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/glcanvas.h>
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <3d_cache.h>
|
||||||
|
#include <3d_info.h>
|
||||||
|
#include <3d_filename_resolver.h>
|
||||||
|
#include <3d_cache/sg/ifsg_api.h>
|
||||||
|
|
||||||
|
#include "panel_prev_model.h"
|
||||||
|
#include "dialog_select_3dmodel.h"
|
||||||
|
#include "3d_cache_dialogs.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ensure -360 < rotation < 360
|
||||||
|
static void checkRotation( double& rot )
|
||||||
|
{
|
||||||
|
if( rot >= 360.0 )
|
||||||
|
{
|
||||||
|
int n = rot / 360.0;
|
||||||
|
rot -= 360.0 * (double)n;
|
||||||
|
}
|
||||||
|
else if( rot <= -360.0 )
|
||||||
|
{
|
||||||
|
int n = -rot / 360.0;
|
||||||
|
rot += 360.0 * (double)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ID_SET_DIR = wxID_LAST + 1,
|
||||||
|
ID_CFG_PATHS,
|
||||||
|
ID_3D_ISO,
|
||||||
|
ID_3D_UPDATE,
|
||||||
|
ID_3D_LEFT,
|
||||||
|
ID_3D_RIGHT,
|
||||||
|
ID_3D_FRONT,
|
||||||
|
ID_3D_BACK,
|
||||||
|
ID_3D_TOP,
|
||||||
|
ID_3D_BOTTOM
|
||||||
|
};
|
||||||
|
|
||||||
|
wxBEGIN_EVENT_TABLE( PANEL_PREV_3D, wxPanel)
|
||||||
|
EVT_CHOICE( ID_SET_DIR, PANEL_PREV_3D::SetRootDir )
|
||||||
|
EVT_BUTTON( ID_CFG_PATHS, PANEL_PREV_3D::Cfg3DPaths )
|
||||||
|
EVT_BUTTON( ID_3D_ISO, PANEL_PREV_3D::View3DISO )
|
||||||
|
EVT_BUTTON( ID_3D_UPDATE, PANEL_PREV_3D::View3DUpdate )
|
||||||
|
EVT_BUTTON( ID_3D_LEFT, PANEL_PREV_3D::View3DLeft )
|
||||||
|
EVT_BUTTON( ID_3D_RIGHT, PANEL_PREV_3D::View3DRight )
|
||||||
|
EVT_BUTTON( ID_3D_FRONT, PANEL_PREV_3D::View3DFront )
|
||||||
|
EVT_BUTTON( ID_3D_BACK, PANEL_PREV_3D::View3DBack )
|
||||||
|
EVT_BUTTON( ID_3D_TOP, PANEL_PREV_3D::View3DTop )
|
||||||
|
EVT_BUTTON( ID_3D_BOTTOM, PANEL_PREV_3D::View3DBottom )
|
||||||
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, bool hasFileSelector ) :
|
||||||
|
wxPanel( aParent, -1 )
|
||||||
|
{
|
||||||
|
m_ModelManager = NULL;
|
||||||
|
m_FileDlg = NULL;
|
||||||
|
canvas = NULL;
|
||||||
|
model = NULL;
|
||||||
|
|
||||||
|
wxBoxSizer* mainBox = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
wxStaticBoxSizer* vbox = new wxStaticBoxSizer( wxVERTICAL, this, _( "3D Model Orientation" ) );
|
||||||
|
wxBoxSizer* hboxDirChoice = NULL;
|
||||||
|
dirChoices = NULL;
|
||||||
|
|
||||||
|
if( hasFileSelector )
|
||||||
|
{
|
||||||
|
hboxDirChoice = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
dirChoices = new wxChoice( this, ID_SET_DIR );
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Note: On Win32 the native selector box will truncate text
|
||||||
|
// if the text is too long.
|
||||||
|
dirChoices->SetMinSize( wxSize( 450, -1 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
wxStaticText* stDirChoice = new wxStaticText( this, -1, _( "Paths:" ) );
|
||||||
|
wxButton* cfgPaths = new wxButton( this, ID_CFG_PATHS, _( "Configure Paths" ) );
|
||||||
|
hboxDirChoice->Add( stDirChoice, 0, wxALL | wxCENTER, 5 );
|
||||||
|
hboxDirChoice->Add( dirChoices, 1, wxEXPAND | wxALL, 5 );
|
||||||
|
hboxDirChoice->Add( cfgPaths, 0, wxALL, 5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
wxStaticBoxSizer* vbScale = new wxStaticBoxSizer( wxVERTICAL, this, _( "Scale" ) );
|
||||||
|
wxStaticBoxSizer* vbRotate = new wxStaticBoxSizer( wxVERTICAL, this, _( "Rotation" ) );
|
||||||
|
wxStaticBoxSizer* vbOffset = new wxStaticBoxSizer( wxVERTICAL, this, _( "Offset (inches)" ) );
|
||||||
|
|
||||||
|
wxStaticBox* modScale = vbScale->GetStaticBox();
|
||||||
|
wxStaticBox* modRotate = vbRotate->GetStaticBox();
|
||||||
|
wxStaticBox* modOffset = vbOffset->GetStaticBox();
|
||||||
|
|
||||||
|
wxBoxSizer* hbS1 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbS2 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbS3 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxStaticText* txtS1 = new wxStaticText( modScale, -1, wxT( "X:" ) );
|
||||||
|
wxStaticText* txtS2 = new wxStaticText( modScale, -1, wxT( "Y:" ) );
|
||||||
|
wxStaticText* txtS3 = new wxStaticText( modScale, -1, wxT( "Z:" ) );
|
||||||
|
xscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
yscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
zscale = new wxTextCtrl( modScale, -1, "1.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
xscale->SetMaxLength( 9 );
|
||||||
|
yscale->SetMaxLength( 9 );
|
||||||
|
zscale->SetMaxLength( 9 );
|
||||||
|
hbS1->Add( txtS1, 0, wxALL, 2 );
|
||||||
|
hbS1->Add( xscale, 0, wxALL, 2 );
|
||||||
|
hbS2->Add( txtS2, 0, wxALL, 2 );
|
||||||
|
hbS2->Add( yscale, 0, wxALL, 2 );
|
||||||
|
hbS3->Add( txtS3, 0, wxALL, 2 );
|
||||||
|
hbS3->Add( zscale, 0, wxALL, 2 );
|
||||||
|
vbScale->Add( hbS1, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbScale->Add( hbS2, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbScale->Add( hbS3, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
|
||||||
|
wxBoxSizer* hbR1 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbR2 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbR3 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxStaticText* txtR1 = new wxStaticText( modRotate, -1, wxT( "X:" ) );
|
||||||
|
wxStaticText* txtR2 = new wxStaticText( modRotate, -1, wxT( "Y:" ) );
|
||||||
|
wxStaticText* txtR3 = new wxStaticText( modRotate, -1, wxT( "Z:" ) );
|
||||||
|
xrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
yrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
zrot = new wxTextCtrl( modRotate, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
xrot->SetMaxLength( 9 );
|
||||||
|
yrot->SetMaxLength( 9 );
|
||||||
|
zrot->SetMaxLength( 9 );
|
||||||
|
hbR1->Add( txtR1, 0, wxALL, 2 );
|
||||||
|
hbR1->Add( xrot, 0, wxALL, 2 );
|
||||||
|
hbR2->Add( txtR2, 0, wxALL, 2 );
|
||||||
|
hbR2->Add( yrot, 0, wxALL, 2 );
|
||||||
|
hbR3->Add( txtR3, 0, wxALL, 2 );
|
||||||
|
hbR3->Add( zrot, 0, wxALL, 2 );
|
||||||
|
vbRotate->Add( hbR1, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbRotate->Add( hbR2, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbRotate->Add( hbR3, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
|
||||||
|
wxBoxSizer* hbO1 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbO2 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbO3 = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxStaticText* txtO1 = new wxStaticText( modOffset, -1, wxT( "X:" ) );
|
||||||
|
wxStaticText* txtO2 = new wxStaticText( modOffset, -1, wxT( "Y:" ) );
|
||||||
|
wxStaticText* txtO3 = new wxStaticText( modOffset, -1, wxT( "Z:" ) );
|
||||||
|
xoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
yoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
zoff = new wxTextCtrl( modOffset, -1, "0.0", wxDefaultPosition, wxDefaultSize,
|
||||||
|
wxTE_PROCESS_ENTER );
|
||||||
|
xoff->SetMaxLength( 9 );
|
||||||
|
yoff->SetMaxLength( 9 );
|
||||||
|
zoff->SetMaxLength( 9 );
|
||||||
|
hbO1->Add( txtO1, 0, wxALL, 2 );
|
||||||
|
hbO1->Add( xoff, 0, wxALL, 2 );
|
||||||
|
hbO2->Add( txtO2, 0, wxALL, 2 );
|
||||||
|
hbO2->Add( yoff, 0, wxALL, 2 );
|
||||||
|
hbO3->Add( txtO3, 0, wxALL, 2 );
|
||||||
|
hbO3->Add( zoff, 0, wxALL, 2 );
|
||||||
|
vbOffset->Add( hbO1, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbOffset->Add( hbO2, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
vbOffset->Add( hbO3, 0, wxEXPAND | wxALL, 2 );
|
||||||
|
|
||||||
|
if( NULL != hboxDirChoice )
|
||||||
|
mainBox->Add( hboxDirChoice, 0, wxEXPAND );
|
||||||
|
|
||||||
|
// hbox holding orientation data and preview
|
||||||
|
wxBoxSizer* hbox = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
// vbox holding orientation data
|
||||||
|
wxBoxSizer* vboxOrient = new wxBoxSizer( wxVERTICAL );
|
||||||
|
// vbox holding the preview and view buttons
|
||||||
|
wxBoxSizer* vboxPrev = new wxBoxSizer( wxVERTICAL );
|
||||||
|
|
||||||
|
vboxOrient->Add( vbScale, 0, wxALL, 5 );
|
||||||
|
vboxOrient->Add( vbRotate, 0, wxALL, 5 );
|
||||||
|
vboxOrient->Add( vbOffset, 0, wxALL, 5 );
|
||||||
|
vboxOrient->AddSpacer( 20 );
|
||||||
|
|
||||||
|
// add preview items
|
||||||
|
preview = new wxPanel( this, -1 );
|
||||||
|
preview->SetMinSize( wxSize( 320, 240 ) );
|
||||||
|
preview->SetBackgroundColour( wxColor( 0, 0, 0 ));
|
||||||
|
vboxPrev->Add( preview, 1, wxEXPAND | wxALIGN_CENTER | wxLEFT | wxRIGHT, 5 );
|
||||||
|
// buttons:
|
||||||
|
wxButton* vFront = new wxButton( this, ID_3D_FRONT, wxT( "F" ) );
|
||||||
|
wxButton* vBack = new wxButton( this, ID_3D_BACK, wxT( "B" ) );
|
||||||
|
wxButton* vLeft = new wxButton( this, ID_3D_LEFT, wxT( "L" ) );
|
||||||
|
wxButton* vRight = new wxButton( this, ID_3D_RIGHT, wxT( "R" ) );
|
||||||
|
wxButton* vTop = new wxButton( this, ID_3D_TOP, wxT( "T" ) );
|
||||||
|
wxButton* vBottom = new wxButton( this, ID_3D_BOTTOM, wxT( "B" ) );
|
||||||
|
wxButton* vISO = new wxButton( this, ID_3D_ISO, wxT( "I" ) );
|
||||||
|
wxButton* vUpdate = new wxButton( this, ID_3D_UPDATE, wxT( "U" ) );
|
||||||
|
wxBoxSizer* hbBT = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
wxBoxSizer* hbBB = new wxBoxSizer( wxHORIZONTAL );
|
||||||
|
hbBT->Add( vISO, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBT->Add( vLeft, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBT->Add( vFront, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBT->Add( vTop, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBT->AddSpacer( 17 );
|
||||||
|
hbBB->Add( vUpdate, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBB->Add( vRight, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBB->Add( vBack, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBB->Add( vBottom, 0, wxCENTER | wxALL, 3 );
|
||||||
|
hbBB->AddSpacer( 17 );
|
||||||
|
|
||||||
|
vboxPrev->AddSpacer( 7 );
|
||||||
|
vboxPrev->Add( hbBT, 0 );
|
||||||
|
vboxPrev->Add( hbBB, 0 );
|
||||||
|
|
||||||
|
// XXX - Suppress the buttons until the Renderer code is ready.
|
||||||
|
// vboxPrev->Hide( preview, true );
|
||||||
|
vboxPrev->Hide( hbBT, true );
|
||||||
|
vboxPrev->Hide( hbBB, true );
|
||||||
|
|
||||||
|
hbox->Add( vboxOrient, 0, wxALL, 5 );
|
||||||
|
hbox->Add( vboxPrev, 1, wxEXPAND );
|
||||||
|
vbox->Add( hbox, 1, wxEXPAND );
|
||||||
|
|
||||||
|
mainBox->Add( vbox, 1, wxEXPAND | wxALL, 5 );
|
||||||
|
|
||||||
|
if( hasFileSelector )
|
||||||
|
{
|
||||||
|
// NOTE: if/when the FIle Selector preview is implemented
|
||||||
|
// we may need to hide the orientation boxes to ensure the
|
||||||
|
// users have sufficient display area for the browser.
|
||||||
|
// hbox->Hide( vboxOrient, true );
|
||||||
|
// XXX -
|
||||||
|
// NOTE: for now we always suppress the preview and model orientation
|
||||||
|
// panels while in the file selector
|
||||||
|
mainBox->Hide( vbox, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
SetSizerAndFit( mainBox );
|
||||||
|
Centre();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PANEL_PREV_3D::~PANEL_PREV_3D()
|
||||||
|
{
|
||||||
|
if( NULL != canvas )
|
||||||
|
{
|
||||||
|
canvas->Clear3DModel();
|
||||||
|
canvas->Refresh();
|
||||||
|
canvas->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( model )
|
||||||
|
S3D::Destroy3DModel( &model );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::SetModelManager( S3D_CACHE* aModelManager )
|
||||||
|
{
|
||||||
|
m_ModelManager = aModelManager;
|
||||||
|
updateDirChoiceList();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::SetFileSelectorDlg( wxFileDialog* aFileDlg )
|
||||||
|
{
|
||||||
|
m_FileDlg = aFileDlg;
|
||||||
|
updateDirChoiceList();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::updateDirChoiceList( void )
|
||||||
|
{
|
||||||
|
if( NULL == m_FileDlg || NULL == m_ModelManager || NULL == dirChoices )
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::list< wxString > const* md = m_ModelManager->GetResolver()->GetPaths();
|
||||||
|
std::list< wxString >::const_iterator sL = md->begin();
|
||||||
|
std::list< wxString >::const_iterator eL = md->end();
|
||||||
|
std::vector< wxString > cl;
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
cl.push_back( *sL );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !cl.empty() )
|
||||||
|
{
|
||||||
|
dirChoices->Clear();
|
||||||
|
dirChoices->Append( (int)cl.size(), &cl[0] );
|
||||||
|
dirChoices->Select( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::SetRootDir( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( !m_FileDlg )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_FileDlg->SetDirectory( dirChoices->GetString( dirChoices->GetSelection() ) );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::Cfg3DPaths( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
if( !m_FileDlg || !m_ModelManager )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( S3D::Configure3DPaths( this, m_ModelManager->GetResolver() ) )
|
||||||
|
updateDirChoiceList();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DISO( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Isometric View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DUpdate( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Update 3D View\n";
|
||||||
|
|
||||||
|
// update the model filename if appropriate
|
||||||
|
if( NULL != m_FileDlg )
|
||||||
|
{
|
||||||
|
wxString modelName = m_FileDlg->GetCurrentlySelectedFilename();
|
||||||
|
UpdateModelName( modelName );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DLeft( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Left View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DRight( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Right View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DFront( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Front View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DBack( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Back View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DTop( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Top View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::View3DBottom( wxCommandEvent& event )
|
||||||
|
{
|
||||||
|
// XXX - TO BE IMPLEMENTED
|
||||||
|
std::cout << "Switch to Bottom View\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::GetModelData( S3D_INFO* aModel )
|
||||||
|
{
|
||||||
|
if( NULL == aModel )
|
||||||
|
return;
|
||||||
|
|
||||||
|
SGPOINT scale;
|
||||||
|
SGPOINT rotation;
|
||||||
|
SGPOINT offset;
|
||||||
|
|
||||||
|
xscale->GetValue().ToDouble( &scale.x );
|
||||||
|
yscale->GetValue().ToDouble( &scale.y );
|
||||||
|
zscale->GetValue().ToDouble( &scale.z );
|
||||||
|
|
||||||
|
if( 0.001 > scale.x || 0.001 > scale.y || 0.001 > scale.z )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] invalid scale values; setting all to 1.0\n";
|
||||||
|
scale.x = 1.0;
|
||||||
|
scale.y = 1.0;
|
||||||
|
scale.z = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
xrot->GetValue().ToDouble( &rotation.x );
|
||||||
|
yrot->GetValue().ToDouble( &rotation.y );
|
||||||
|
zrot->GetValue().ToDouble( &rotation.z );
|
||||||
|
checkRotation( rotation.x );
|
||||||
|
checkRotation( rotation.y );
|
||||||
|
checkRotation( rotation.z );
|
||||||
|
|
||||||
|
xoff->GetValue().ToDouble( &offset.x );
|
||||||
|
yoff->GetValue().ToDouble( &offset.y );
|
||||||
|
zoff->GetValue().ToDouble( &offset.z );
|
||||||
|
|
||||||
|
aModel->scale = scale;
|
||||||
|
aModel->offset = offset;
|
||||||
|
aModel->rotation = rotation;
|
||||||
|
|
||||||
|
// return if we are not in file selection mode
|
||||||
|
if( NULL == m_FileDlg )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// file selection mode: retrieve the filename and specify a
|
||||||
|
// path relative to one of the config paths
|
||||||
|
wxFileName fname = m_FileDlg->GetPath();
|
||||||
|
fname.Normalize();
|
||||||
|
aModel->filename = m_ModelManager->GetResolver()->ShortenPath( fname.GetFullPath() );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::SetModelData( S3D_INFO const* aModel )
|
||||||
|
{
|
||||||
|
xscale->SetValue( wxString::FromDouble( aModel->scale.x ) );
|
||||||
|
yscale->SetValue( wxString::FromDouble( aModel->scale.y ) );
|
||||||
|
zscale->SetValue( wxString::FromDouble( aModel->scale.z ) );
|
||||||
|
|
||||||
|
xrot->SetValue( wxString::FromDouble( aModel->rotation.x ) );
|
||||||
|
yrot->SetValue( wxString::FromDouble( aModel->rotation.y ) );
|
||||||
|
zrot->SetValue( wxString::FromDouble( aModel->rotation.z ) );
|
||||||
|
|
||||||
|
xoff->SetValue( wxString::FromDouble( aModel->offset.x ) );
|
||||||
|
yoff->SetValue( wxString::FromDouble( aModel->offset.y ) );
|
||||||
|
zoff->SetValue( wxString::FromDouble( aModel->offset.z ) );
|
||||||
|
|
||||||
|
modelInfo = *aModel;
|
||||||
|
UpdateModelName( aModel->filename );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::UpdateModelName( wxString const& aModelName )
|
||||||
|
{
|
||||||
|
bool newModel = false;
|
||||||
|
|
||||||
|
// if the model name is a directory simply clear the current model
|
||||||
|
if( aModelName.empty() || wxFileName::DirExists( aModelName ) )
|
||||||
|
{
|
||||||
|
currentModelFile.clear();
|
||||||
|
modelInfo.filename.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxString newModelFile;
|
||||||
|
|
||||||
|
if( m_ModelManager )
|
||||||
|
newModelFile = m_ModelManager->GetResolver()->ResolvePath( aModelName );
|
||||||
|
else if( wxFileName::FileExists( aModelName ) )
|
||||||
|
newModelFile = aModelName;
|
||||||
|
|
||||||
|
if( newModelFile.empty() )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: (no such file) " << aModelName.ToUTF8() << "\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( newModelFile.Cmp( currentModelFile ) )
|
||||||
|
{
|
||||||
|
newModel = true;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: " << newModelFile.ToUTF8() << "\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "[3dv] Update Model: [model unchanged]\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
currentModelFile = newModelFile;
|
||||||
|
modelInfo.filename = currentModelFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( currentModelFile.empty() || newModel )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: painting black\n";
|
||||||
|
#endif
|
||||||
|
if( NULL != canvas )
|
||||||
|
canvas->Clear3DModel();
|
||||||
|
|
||||||
|
if( model )
|
||||||
|
S3D::Destroy3DModel( &model );
|
||||||
|
|
||||||
|
if( currentModelFile.empty() )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGPOINT rot;
|
||||||
|
SGPOINT trans;
|
||||||
|
model = m_ModelManager->Prepare( &modelInfo, rot, trans );
|
||||||
|
|
||||||
|
if( NULL == model )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: no model loaded\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( NULL != canvas )
|
||||||
|
{
|
||||||
|
canvas->Refresh();
|
||||||
|
canvas->Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: loading preview\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if( NULL == canvas )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cout << "[3dv] Update Model: creating canvas\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
canvas = new C3D_MODEL_VIEWER( preview,
|
||||||
|
COGL_ATT_LIST::GetAttributesList( true ) );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if( NULL == canvas )
|
||||||
|
std::cout << "[3dv] Update Model: canvas creation FAILED\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
canvas->SetSize( preview->GetClientSize() );
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas->Set3DModel( *model );
|
||||||
|
canvas->Refresh();
|
||||||
|
canvas->Update();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PANEL_PREV_3D::UpdateWindowUI( long flags )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
XXX -
|
||||||
|
NOTE: until we figure out how to ensure that a Paint Event is
|
||||||
|
generated for the File Selector's UI, we cannot display any
|
||||||
|
preview within the file browser.
|
||||||
|
if( wxUPDATE_UI_RECURSE == flags && m_FileDlg && m_ModelManager )
|
||||||
|
{
|
||||||
|
// check for a change in the current model file
|
||||||
|
S3D_INFO info;
|
||||||
|
modelInfo = info;
|
||||||
|
UpdateModelName( m_FileDlg->GetCurrentlySelectedFilename() );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
wxPanel::UpdateWindowUI( flags );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 panel_prev_model.h
|
||||||
|
* defines a panel which is to be added to a wxFileDialog via SetExtraControl();
|
||||||
|
* the panel shows a preview of the model being browsed (if preview is supported
|
||||||
|
* by a plugin) and provides controls to set the offset/rotation/scale of the
|
||||||
|
* model as per KiCad's current behavior. The panel may also be used in the 3D
|
||||||
|
* configuration dialog to tune the positioning of the models without invoking
|
||||||
|
* a file selector dialog.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PANEL_PREV_MODEL_H
|
||||||
|
#define PANEL_PREV_MODEL_H
|
||||||
|
|
||||||
|
#include <wx/wx.h>
|
||||||
|
#include <wx/panel.h>
|
||||||
|
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
#include <3d_cache/3d_info.h>
|
||||||
|
|
||||||
|
class S3D_CACHE;
|
||||||
|
class C3D_MODEL_VIEWER;
|
||||||
|
|
||||||
|
class PANEL_PREV_3D : public wxPanel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PANEL_PREV_3D( wxWindow* aParent, bool hasFileSelector = false );
|
||||||
|
~PANEL_PREV_3D();
|
||||||
|
|
||||||
|
void SetModelManager( S3D_CACHE* aModelManager );
|
||||||
|
void SetFileSelectorDlg( wxFileDialog* aFileDlg );
|
||||||
|
void SetRootDir( wxCommandEvent& event );
|
||||||
|
void Cfg3DPaths( wxCommandEvent& event );
|
||||||
|
// 3D views
|
||||||
|
void View3DISO( wxCommandEvent& event );
|
||||||
|
void View3DUpdate( wxCommandEvent& event );
|
||||||
|
void View3DLeft( wxCommandEvent& event );
|
||||||
|
void View3DRight( wxCommandEvent& event );
|
||||||
|
void View3DFront( wxCommandEvent& event );
|
||||||
|
void View3DBack( wxCommandEvent& event );
|
||||||
|
void View3DTop( wxCommandEvent& event );
|
||||||
|
void View3DBottom( wxCommandEvent& event );
|
||||||
|
// Set / Retrieve model data
|
||||||
|
void SetModelData( S3D_INFO const* aModel );
|
||||||
|
void GetModelData( S3D_INFO* aModel );
|
||||||
|
void UpdateModelName( wxString const& aModel );
|
||||||
|
// Update on change of FileDlg selection
|
||||||
|
virtual void UpdateWindowUI( long flags = wxUPDATE_UI_NONE );
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxString currentModelFile;
|
||||||
|
S3D_CACHE* m_ModelManager;
|
||||||
|
wxFileDialog* m_FileDlg;
|
||||||
|
wxChoice* dirChoices;
|
||||||
|
wxTextCtrl* xscale;
|
||||||
|
wxTextCtrl* yscale;
|
||||||
|
wxTextCtrl* zscale;
|
||||||
|
wxTextCtrl* xrot;
|
||||||
|
wxTextCtrl* yrot;
|
||||||
|
wxTextCtrl* zrot;
|
||||||
|
wxTextCtrl* xoff;
|
||||||
|
wxTextCtrl* yoff;
|
||||||
|
wxTextCtrl* zoff;
|
||||||
|
wxPanel* preview;
|
||||||
|
C3D_MODEL_VIEWER* canvas;
|
||||||
|
S3DMODEL* model;
|
||||||
|
S3D_INFO modelInfo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateDirChoiceList( void );
|
||||||
|
|
||||||
|
wxDECLARE_EVENT_TABLE();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PANEL_PREV_MODEL_H
|
|
@ -0,0 +1,409 @@
|
||||||
|
/* md5.c - Functions to compute MD5 message digest of files or memory blocks
|
||||||
|
* according to the definition of MD5 in RFC 1321 from April 1992.
|
||||||
|
* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* NOTE: This source is derived from an old version taken from the GNU C
|
||||||
|
* Library (glibc).
|
||||||
|
*
|
||||||
|
* 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, 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, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
|
||||||
|
#include "ansidecl.h"
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
# include <machine/endian.h>
|
||||||
|
#elif !defined( _WIN32 )
|
||||||
|
# include <endian.h>
|
||||||
|
#endif
|
||||||
|
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||||
|
# define WORDS_BIGENDIAN 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#ifdef WORDS_BIGENDIAN
|
||||||
|
# define SWAP(n) \
|
||||||
|
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||||
|
#else
|
||||||
|
# define SWAP(n) (n)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* This array contains the bytes used to pad the buffer to the next
|
||||||
|
* 64-byte boundary. (RFC 1321, 3.1: Step 1) */
|
||||||
|
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize structure containing state of computation.
|
||||||
|
* (RFC 1321, 3.3: Step 3) */
|
||||||
|
void
|
||||||
|
md5_init_ctx ( struct md5_ctx *ctx )
|
||||||
|
{
|
||||||
|
ctx->A = (md5_uint32) 0x67452301;
|
||||||
|
ctx->B = (md5_uint32) 0xefcdab89;
|
||||||
|
ctx->C = (md5_uint32) 0x98badcfe;
|
||||||
|
ctx->D = (md5_uint32) 0x10325476;
|
||||||
|
|
||||||
|
ctx->total[0] = ctx->total[1] = 0;
|
||||||
|
ctx->buflen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put result from CTX in first 16 bytes following RESBUF. The result
|
||||||
|
* must be in little endian byte order.
|
||||||
|
*
|
||||||
|
* IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
* aligned for a 32 bits value. */
|
||||||
|
void *
|
||||||
|
md5_read_ctx ( const struct md5_ctx *ctx, void *resbuf )
|
||||||
|
{
|
||||||
|
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
|
||||||
|
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
|
||||||
|
((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
|
||||||
|
((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
|
||||||
|
|
||||||
|
return resbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process the remaining bytes in the internal buffer and the usual
|
||||||
|
* prolog according to the standard and write the result to RESBUF.
|
||||||
|
*
|
||||||
|
* IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
* aligned for a 32 bits value. */
|
||||||
|
void *
|
||||||
|
md5_finish_ctx ( struct md5_ctx *ctx, void *resbuf )
|
||||||
|
{
|
||||||
|
/* Take yet unprocessed bytes into account. */
|
||||||
|
md5_uint32 bytes = ctx->buflen;
|
||||||
|
size_t pad;
|
||||||
|
|
||||||
|
/* Now count remaining bytes. */
|
||||||
|
ctx->total[0] += bytes;
|
||||||
|
if (ctx->total[0] < bytes)
|
||||||
|
++ctx->total[1];
|
||||||
|
|
||||||
|
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||||
|
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||||
|
|
||||||
|
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||||
|
*(md5_uint32 *) (&ctx->buffer[bytes + pad]) = SWAP (ctx->total[0] << 3);
|
||||||
|
*(md5_uint32 *) (&ctx->buffer[bytes + pad + 4]) = SWAP ((ctx->total[1] << 3) |
|
||||||
|
(ctx->total[0] >> 29));
|
||||||
|
|
||||||
|
/* Process last bytes. */
|
||||||
|
md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||||
|
|
||||||
|
return md5_read_ctx (ctx, resbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||||
|
* resulting message digest number will be written into the 16 bytes
|
||||||
|
* beginning at RESBLOCK. */
|
||||||
|
int
|
||||||
|
md5_stream ( FILE *stream, void *resblock )
|
||||||
|
{
|
||||||
|
/* Important: BLOCKSIZE must be a multiple of 64. */
|
||||||
|
#define BLOCKSIZE 4096
|
||||||
|
struct md5_ctx ctx;
|
||||||
|
char buffer[BLOCKSIZE + 72];
|
||||||
|
size_t sum;
|
||||||
|
|
||||||
|
/* Initialize the computation context. */
|
||||||
|
md5_init_ctx (&ctx);
|
||||||
|
|
||||||
|
/* Iterate over full file contents. */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||||
|
* computation function processes the whole buffer so that with the
|
||||||
|
* next round of the loop another block can be read. */
|
||||||
|
size_t n;
|
||||||
|
sum = 0;
|
||||||
|
|
||||||
|
/* Read block. Take care for partial reads. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
|
||||||
|
|
||||||
|
sum += n;
|
||||||
|
}
|
||||||
|
while (sum < BLOCKSIZE && n != 0);
|
||||||
|
if (n == 0 && ferror (stream))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* If end of file is reached, end the loop. */
|
||||||
|
if (n == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||||
|
* BLOCKSIZE % 64 == 0
|
||||||
|
*/
|
||||||
|
md5_process_block (buffer, BLOCKSIZE, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the last bytes if necessary. */
|
||||||
|
if (sum > 0)
|
||||||
|
md5_process_bytes (buffer, sum, &ctx);
|
||||||
|
|
||||||
|
/* Construct result in desired memory. */
|
||||||
|
md5_finish_ctx (&ctx, resblock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||||
|
* result is always in little endian byte order, so that a byte-wise
|
||||||
|
* output yields to the wanted ASCII representation of the message
|
||||||
|
* digest. */
|
||||||
|
void *
|
||||||
|
md5_buffer ( const char *buffer, size_t len, void *resblock )
|
||||||
|
{
|
||||||
|
struct md5_ctx ctx;
|
||||||
|
|
||||||
|
/* Initialize the computation context. */
|
||||||
|
md5_init_ctx (&ctx);
|
||||||
|
|
||||||
|
/* Process whole buffer but last len % 64 bytes. */
|
||||||
|
md5_process_bytes (buffer, len, &ctx);
|
||||||
|
|
||||||
|
/* Put result in desired memory area. */
|
||||||
|
return md5_finish_ctx (&ctx, resblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
md5_process_bytes ( const void *buffer, size_t len, struct md5_ctx *ctx )
|
||||||
|
{
|
||||||
|
/* When we already have some bits in our internal buffer concatenate
|
||||||
|
* both inputs first. */
|
||||||
|
if (ctx->buflen != 0)
|
||||||
|
{
|
||||||
|
size_t left_over = ctx->buflen;
|
||||||
|
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||||
|
|
||||||
|
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||||
|
ctx->buflen += add;
|
||||||
|
|
||||||
|
if (left_over + add > 64)
|
||||||
|
{
|
||||||
|
md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
|
||||||
|
/* The regions in the following copy operation cannot overlap. */
|
||||||
|
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||||
|
(left_over + add) & 63);
|
||||||
|
ctx->buflen = (left_over + add) & 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (const void *) ((const char *) buffer + add);
|
||||||
|
len -= add;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process available complete blocks. */
|
||||||
|
if (len > 64)
|
||||||
|
{
|
||||||
|
md5_process_block (buffer, len & ~63, ctx);
|
||||||
|
buffer = (const void *) ((const char *) buffer + (len & ~63));
|
||||||
|
len &= 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move remaining bytes in internal buffer. */
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
memcpy (ctx->buffer, buffer, len);
|
||||||
|
ctx->buflen = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* These are the four functions used in the four steps of the MD5 algorithm
|
||||||
|
* and defined in the RFC 1321. The first function is a little bit optimized
|
||||||
|
* (as found in Colin Plumbs public domain implementation). */
|
||||||
|
/* #define FF(b, c, d) ((b & c) | (~b & d)) */
|
||||||
|
#define FF(b, c, d) (d ^ (b & (c ^ d)))
|
||||||
|
#define FG(b, c, d) FF (d, b, c)
|
||||||
|
#define FH(b, c, d) (b ^ c ^ d)
|
||||||
|
#define FI(b, c, d) (c ^ (b | ~d))
|
||||||
|
|
||||||
|
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||||
|
* It is assumed that LEN % 64 == 0. */
|
||||||
|
|
||||||
|
void
|
||||||
|
md5_process_block ( const void *buffer, size_t len, struct md5_ctx *ctx )
|
||||||
|
{
|
||||||
|
md5_uint32 correct_words[16];
|
||||||
|
const md5_uint32 *words = (const md5_uint32 *) buffer;
|
||||||
|
size_t nwords = len / sizeof (md5_uint32);
|
||||||
|
const md5_uint32 *endp = words + nwords;
|
||||||
|
md5_uint32 A = ctx->A;
|
||||||
|
md5_uint32 B = ctx->B;
|
||||||
|
md5_uint32 C = ctx->C;
|
||||||
|
md5_uint32 D = ctx->D;
|
||||||
|
|
||||||
|
/* First increment the byte count. RFC 1321 specifies the possible
|
||||||
|
* length of the file up to 2^64 bits. Here we only compute the
|
||||||
|
* number of bytes. Do a double word increment. */
|
||||||
|
ctx->total[0] += len;
|
||||||
|
if (ctx->total[0] < len)
|
||||||
|
++ctx->total[1];
|
||||||
|
|
||||||
|
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||||
|
* the loop. */
|
||||||
|
while (words < endp)
|
||||||
|
{
|
||||||
|
md5_uint32 *cwp = correct_words;
|
||||||
|
md5_uint32 A_save = A;
|
||||||
|
md5_uint32 B_save = B;
|
||||||
|
md5_uint32 C_save = C;
|
||||||
|
md5_uint32 D_save = D;
|
||||||
|
|
||||||
|
/* First round: using the given function, the context and a constant
|
||||||
|
* the next context is computed. Because the algorithms processing
|
||||||
|
* unit is a 32-bit word and it is determined to work on words in
|
||||||
|
* little endian byte order we perhaps have to change the byte order
|
||||||
|
* before the computation. To reduce the work for the next steps
|
||||||
|
* we store the swapped words in the array CORRECT_WORDS. */
|
||||||
|
|
||||||
|
#define OP(a, b, c, d, s, T) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
|
||||||
|
++words; \
|
||||||
|
CYCLIC (a, s); \
|
||||||
|
a += b; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
/* It is unfortunate that C does not provide an operator for
|
||||||
|
* cyclic rotation. Hope the C compiler is smart enough. */
|
||||||
|
#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
|
||||||
|
|
||||||
|
/* Before we start, one word to the strange constants.
|
||||||
|
* They are defined in RFC 1321 as
|
||||||
|
*
|
||||||
|
* T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Round 1. */
|
||||||
|
OP (A, B, C, D, 7, (md5_uint32) 0xd76aa478);
|
||||||
|
OP (D, A, B, C, 12, (md5_uint32) 0xe8c7b756);
|
||||||
|
OP (C, D, A, B, 17, (md5_uint32) 0x242070db);
|
||||||
|
OP (B, C, D, A, 22, (md5_uint32) 0xc1bdceee);
|
||||||
|
OP (A, B, C, D, 7, (md5_uint32) 0xf57c0faf);
|
||||||
|
OP (D, A, B, C, 12, (md5_uint32) 0x4787c62a);
|
||||||
|
OP (C, D, A, B, 17, (md5_uint32) 0xa8304613);
|
||||||
|
OP (B, C, D, A, 22, (md5_uint32) 0xfd469501);
|
||||||
|
OP (A, B, C, D, 7, (md5_uint32) 0x698098d8);
|
||||||
|
OP (D, A, B, C, 12, (md5_uint32) 0x8b44f7af);
|
||||||
|
OP (C, D, A, B, 17, (md5_uint32) 0xffff5bb1);
|
||||||
|
OP (B, C, D, A, 22, (md5_uint32) 0x895cd7be);
|
||||||
|
OP (A, B, C, D, 7, (md5_uint32) 0x6b901122);
|
||||||
|
OP (D, A, B, C, 12, (md5_uint32) 0xfd987193);
|
||||||
|
OP (C, D, A, B, 17, (md5_uint32) 0xa679438e);
|
||||||
|
OP (B, C, D, A, 22, (md5_uint32) 0x49b40821);
|
||||||
|
|
||||||
|
/* For the second to fourth round we have the possibly swapped words
|
||||||
|
* in CORRECT_WORDS. Redefine the macro to take an additional first
|
||||||
|
* argument specifying the function to use. */
|
||||||
|
#undef OP
|
||||||
|
#define OP(a, b, c, d, k, s, T) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
a += FX (b, c, d) + correct_words[k] + T; \
|
||||||
|
CYCLIC (a, s); \
|
||||||
|
a += b; \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
#define FX(b, c, d) FG (b, c, d)
|
||||||
|
|
||||||
|
/* Round 2. */
|
||||||
|
OP (A, B, C, D, 1, 5, (md5_uint32) 0xf61e2562);
|
||||||
|
OP (D, A, B, C, 6, 9, (md5_uint32) 0xc040b340);
|
||||||
|
OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51);
|
||||||
|
OP (B, C, D, A, 0, 20, (md5_uint32) 0xe9b6c7aa);
|
||||||
|
OP (A, B, C, D, 5, 5, (md5_uint32) 0xd62f105d);
|
||||||
|
OP (D, A, B, C, 10, 9, (md5_uint32) 0x02441453);
|
||||||
|
OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681);
|
||||||
|
OP (B, C, D, A, 4, 20, (md5_uint32) 0xe7d3fbc8);
|
||||||
|
OP (A, B, C, D, 9, 5, (md5_uint32) 0x21e1cde6);
|
||||||
|
OP (D, A, B, C, 14, 9, (md5_uint32) 0xc33707d6);
|
||||||
|
OP (C, D, A, B, 3, 14, (md5_uint32) 0xf4d50d87);
|
||||||
|
OP (B, C, D, A, 8, 20, (md5_uint32) 0x455a14ed);
|
||||||
|
OP (A, B, C, D, 13, 5, (md5_uint32) 0xa9e3e905);
|
||||||
|
OP (D, A, B, C, 2, 9, (md5_uint32) 0xfcefa3f8);
|
||||||
|
OP (C, D, A, B, 7, 14, (md5_uint32) 0x676f02d9);
|
||||||
|
OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a);
|
||||||
|
|
||||||
|
#undef FX
|
||||||
|
#define FX(b, c, d) FH (b, c, d)
|
||||||
|
|
||||||
|
/* Round 3. */
|
||||||
|
OP (A, B, C, D, 5, 4, (md5_uint32) 0xfffa3942);
|
||||||
|
OP (D, A, B, C, 8, 11, (md5_uint32) 0x8771f681);
|
||||||
|
OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122);
|
||||||
|
OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c);
|
||||||
|
OP (A, B, C, D, 1, 4, (md5_uint32) 0xa4beea44);
|
||||||
|
OP (D, A, B, C, 4, 11, (md5_uint32) 0x4bdecfa9);
|
||||||
|
OP (C, D, A, B, 7, 16, (md5_uint32) 0xf6bb4b60);
|
||||||
|
OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70);
|
||||||
|
OP (A, B, C, D, 13, 4, (md5_uint32) 0x289b7ec6);
|
||||||
|
OP (D, A, B, C, 0, 11, (md5_uint32) 0xeaa127fa);
|
||||||
|
OP (C, D, A, B, 3, 16, (md5_uint32) 0xd4ef3085);
|
||||||
|
OP (B, C, D, A, 6, 23, (md5_uint32) 0x04881d05);
|
||||||
|
OP (A, B, C, D, 9, 4, (md5_uint32) 0xd9d4d039);
|
||||||
|
OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5);
|
||||||
|
OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8);
|
||||||
|
OP (B, C, D, A, 2, 23, (md5_uint32) 0xc4ac5665);
|
||||||
|
|
||||||
|
#undef FX
|
||||||
|
#define FX(b, c, d) FI (b, c, d)
|
||||||
|
|
||||||
|
/* Round 4. */
|
||||||
|
OP (A, B, C, D, 0, 6, (md5_uint32) 0xf4292244);
|
||||||
|
OP (D, A, B, C, 7, 10, (md5_uint32) 0x432aff97);
|
||||||
|
OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7);
|
||||||
|
OP (B, C, D, A, 5, 21, (md5_uint32) 0xfc93a039);
|
||||||
|
OP (A, B, C, D, 12, 6, (md5_uint32) 0x655b59c3);
|
||||||
|
OP (D, A, B, C, 3, 10, (md5_uint32) 0x8f0ccc92);
|
||||||
|
OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d);
|
||||||
|
OP (B, C, D, A, 1, 21, (md5_uint32) 0x85845dd1);
|
||||||
|
OP (A, B, C, D, 8, 6, (md5_uint32) 0x6fa87e4f);
|
||||||
|
OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0);
|
||||||
|
OP (C, D, A, B, 6, 15, (md5_uint32) 0xa3014314);
|
||||||
|
OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1);
|
||||||
|
OP (A, B, C, D, 4, 6, (md5_uint32) 0xf7537e82);
|
||||||
|
OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235);
|
||||||
|
OP (C, D, A, B, 2, 15, (md5_uint32) 0x2ad7d2bb);
|
||||||
|
OP (B, C, D, A, 9, 21, (md5_uint32) 0xeb86d391);
|
||||||
|
|
||||||
|
/* Add the starting values of the context. */
|
||||||
|
A += A_save;
|
||||||
|
B += B_save;
|
||||||
|
C += C_save;
|
||||||
|
D += D_save;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Put checksum in context given as argument. */
|
||||||
|
ctx->A = A;
|
||||||
|
ctx->B = B;
|
||||||
|
ctx->C = C;
|
||||||
|
ctx->D = D;
|
||||||
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* md5.h - Declaration of functions and data types used for MD5 sum
|
||||||
|
computing library functions.
|
||||||
|
|
||||||
|
Copyright 1995, 1996, 2000 Free Software Foundation, Inc.
|
||||||
|
NOTE: The canonical source of this file is maintained with the GNU C
|
||||||
|
Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
|
||||||
|
|
||||||
|
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, 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, write to the Free Software Foundation,
|
||||||
|
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MD5_H
|
||||||
|
#define _MD5_H 1
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if defined HAVE_LIMITS_H || _LIBC
|
||||||
|
# include <limits.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* The following contortions are an attempt to use the C preprocessor
|
||||||
|
to determine an unsigned integral type that is 32 bits wide. An
|
||||||
|
alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
|
||||||
|
doing that would require that the configure script compile and *run*
|
||||||
|
the resulting executable. Locally running cross-compiled executables
|
||||||
|
is usually not possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _LIBC
|
||||||
|
# include <sys/types.h>
|
||||||
|
typedef u_int32_t md5_uint32;
|
||||||
|
#else
|
||||||
|
# define INT_MAX_32_BITS 2147483647
|
||||||
|
|
||||||
|
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
|
||||||
|
This should be valid for all systems GNU cares about because
|
||||||
|
that doesn't include 16-bit systems, and only modern systems
|
||||||
|
(that certainly have <limits.h>) have 64+-bit integral types.
|
||||||
|
*/
|
||||||
|
|
||||||
|
# ifndef INT_MAX
|
||||||
|
# define INT_MAX INT_MAX_32_BITS
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# if INT_MAX == INT_MAX_32_BITS
|
||||||
|
typedef unsigned int md5_uint32;
|
||||||
|
# else
|
||||||
|
# if SHRT_MAX == INT_MAX_32_BITS
|
||||||
|
typedef unsigned short md5_uint32;
|
||||||
|
# else
|
||||||
|
# if LONG_MAX == INT_MAX_32_BITS
|
||||||
|
typedef unsigned long md5_uint32;
|
||||||
|
# else
|
||||||
|
/* The following line is intended to evoke an error.
|
||||||
|
* Using #error is not portable enough. */
|
||||||
|
"Cannot determine unsigned 32-bit data type."
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef __P
|
||||||
|
#if defined (__STDC__) && __STDC__
|
||||||
|
#define __P(x) x
|
||||||
|
#else
|
||||||
|
#define __P(x) ()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Structure to save state of computation between the single steps. */
|
||||||
|
struct md5_ctx
|
||||||
|
{
|
||||||
|
md5_uint32 A;
|
||||||
|
md5_uint32 B;
|
||||||
|
md5_uint32 C;
|
||||||
|
md5_uint32 D;
|
||||||
|
|
||||||
|
md5_uint32 total[2];
|
||||||
|
md5_uint32 buflen;
|
||||||
|
char buffer[128];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following three functions are build up the low level used in
|
||||||
|
* the functions `md5_stream' and `md5_buffer'.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Initialize structure containing state of computation.
|
||||||
|
(RFC 1321, 3.3: Step 3) */
|
||||||
|
extern void md5_init_ctx __P ((struct md5_ctx *ctx));
|
||||||
|
|
||||||
|
/* Starting with the result of former calls of this function (or the
|
||||||
|
initialization function update the context for the next LEN bytes
|
||||||
|
starting at BUFFER.
|
||||||
|
It is necessary that LEN is a multiple of 64!!! */
|
||||||
|
extern void md5_process_block __P ((const void *buffer, size_t len,
|
||||||
|
struct md5_ctx *ctx));
|
||||||
|
|
||||||
|
/* Starting with the result of former calls of this function (or the
|
||||||
|
initialization function update the context for the next LEN bytes
|
||||||
|
starting at BUFFER.
|
||||||
|
It is NOT required that LEN is a multiple of 64. */
|
||||||
|
extern void md5_process_bytes __P ((const void *buffer, size_t len,
|
||||||
|
struct md5_ctx *ctx));
|
||||||
|
|
||||||
|
/* Process the remaining bytes in the buffer and put result from CTX
|
||||||
|
in first 16 bytes following RESBUF. The result is always in little
|
||||||
|
endian byte order, so that a byte-wise output yields to the wanted
|
||||||
|
ASCII representation of the message digest.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
|
||||||
|
|
||||||
|
|
||||||
|
/* Put result from CTX in first 16 bytes following RESBUF. The result is
|
||||||
|
always in little endian byte order, so that a byte-wise output yields
|
||||||
|
to the wanted ASCII representation of the message digest.
|
||||||
|
|
||||||
|
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||||
|
aligned for a 32 bits value. */
|
||||||
|
extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||||
|
resulting message digest number will be written into the 16 bytes
|
||||||
|
beginning at RESBLOCK. */
|
||||||
|
extern int md5_stream __P ((FILE *stream, void *resblock));
|
||||||
|
|
||||||
|
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||||
|
result is always in little endian byte order, so that a byte-wise
|
||||||
|
output yields to the wanted ASCII representation of the message
|
||||||
|
digest. */
|
||||||
|
extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,55 @@
|
||||||
|
include_directories(
|
||||||
|
${CMAKE_SOURCE_DIR}/include
|
||||||
|
# ${CMAKE_SOURCE_DIR}/include/gal/opengl
|
||||||
|
${CMAKE_SOURCE_DIR}/3d-viewer
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_library( s3d_sg SHARED
|
||||||
|
sg_base.cpp
|
||||||
|
sg_node.cpp
|
||||||
|
sg_helpers.cpp
|
||||||
|
scenegraph.cpp
|
||||||
|
sg_appearance.cpp
|
||||||
|
sg_faceset.cpp
|
||||||
|
sg_shape.cpp
|
||||||
|
sg_colors.cpp
|
||||||
|
sg_coords.cpp
|
||||||
|
sg_normals.cpp
|
||||||
|
sg_index.cpp
|
||||||
|
sg_colorindex.cpp
|
||||||
|
sg_coordindex.cpp
|
||||||
|
ifsg_node.cpp
|
||||||
|
ifsg_transform.cpp
|
||||||
|
ifsg_appearance.cpp
|
||||||
|
ifsg_index.cpp
|
||||||
|
ifsg_colorindex.cpp
|
||||||
|
ifsg_coordindex.cpp
|
||||||
|
ifsg_colors.cpp
|
||||||
|
ifsg_coords.cpp
|
||||||
|
ifsg_faceset.cpp
|
||||||
|
ifsg_normals.cpp
|
||||||
|
ifsg_shape.cpp
|
||||||
|
ifsg_api.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
if( MSVC )
|
||||||
|
# Define a flag to expose the appropriate SG_DLL macro at build time
|
||||||
|
target_compile_definitions( s3d_sg PRIVATE -DDLL_SGIF )
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_link_libraries( s3d_sg ${wxWidgets_LIBRARIES} )
|
||||||
|
|
||||||
|
if( APPLE )
|
||||||
|
install( TARGETS
|
||||||
|
s3d_sg
|
||||||
|
DESTINATION /Applications/kicad.app/SharedSupport
|
||||||
|
COMPONENT binary
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install( TARGETS
|
||||||
|
s3d_sg
|
||||||
|
DESTINATION lib/kicad
|
||||||
|
COMPONENT binary
|
||||||
|
)
|
||||||
|
endif()
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 "sg_api.h"
|
||||||
|
#include "sg_node.h"
|
||||||
|
|
||||||
|
S3D::API_SGNODE::API_SGNODE()
|
||||||
|
{
|
||||||
|
node = NULL;
|
||||||
|
nodeType = SGTYPE_END; // signal an invalid type by default
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* S3D::API_SGNODE::GetNode( void )
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::AttachNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
node = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aNode->GetNodeType() != nodeType )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] object with node type " << aNode->GetNodeType();
|
||||||
|
std::cerr << " is being attached to API node type " << nodeType << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = aNode;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::GetNodeType( S3D::SGTYPES& aNodeType ) const
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
{
|
||||||
|
aNodeType = SGTYPE_END;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNodeType = node->GetNodeType();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::GetParent( SGNODE const*& aParent ) const
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
{
|
||||||
|
aParent = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aParent = node->GetParent();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::SetParent( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return node->SetParent( aParent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::GetName( const char*& aName )
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
{
|
||||||
|
aName = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aName = node->GetName();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::SetName( const char *aName )
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
node->SetName( aName );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType, const char*& aName ) const
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
{
|
||||||
|
aName = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aName = node->GetNodeTypeName( aNodeType );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::API_SGNODE::FindNode( const char *aNodeName, const SGNODE *aCaller, SGNODE*& aNode )
|
||||||
|
{
|
||||||
|
if( NULL == node )
|
||||||
|
{
|
||||||
|
aNode = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNode = node->FindNode( aNodeName, aCaller );
|
||||||
|
|
||||||
|
if( NULL == aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_api.h>
|
||||||
|
|
||||||
|
XXX - TO BE IMPLEMENTED
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_all.h
|
||||||
|
* collects header files for all SG* wrappers and the API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_transform.h>
|
||||||
|
#include <3d_cache/sg/ifsg_appearance.h>
|
||||||
|
#include <3d_cache/sg/ifsg_colors.h>
|
||||||
|
#include <3d_cache/sg/ifsg_coords.h>
|
||||||
|
#include <3d_cache/sg/ifsg_faceset.h>
|
||||||
|
#include <3d_cache/sg/ifsg_colorindex.h>
|
||||||
|
#include <3d_cache/sg/ifsg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/ifsg_normals.h>
|
||||||
|
#include <3d_cache/sg/ifsg_shape.h>
|
||||||
|
#include <3d_cache/sg/ifsg_api.h>
|
|
@ -0,0 +1,413 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <3d_cache/sg/ifsg_api.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
#include <3d_cache/sg/scenegraph.h>
|
||||||
|
#include <3d_cache/sg/sg_appearance.h>
|
||||||
|
#include <3d_cache/sg/sg_colorindex.h>
|
||||||
|
#include <3d_cache/sg/sg_colors.h>
|
||||||
|
#include <3d_cache/sg/sg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/sg_coords.h>
|
||||||
|
#include <3d_cache/sg/sg_faceset.h>
|
||||||
|
#include <3d_cache/sg/sg_normals.h>
|
||||||
|
#include <3d_cache/sg/sg_shape.h>
|
||||||
|
#include <3d_info.h>
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
|
||||||
|
|
||||||
|
static char BadNode[] = " * [BUG] NULL pointer passed for aNode\n";
|
||||||
|
|
||||||
|
static void formatMaterial( SMATERIAL& mat, SGAPPEARANCE const* app )
|
||||||
|
{
|
||||||
|
float v0, v1, v2;
|
||||||
|
|
||||||
|
v0 = app->ambient;
|
||||||
|
mat.m_Ambient.x = v0;
|
||||||
|
mat.m_Ambient.y = v0;
|
||||||
|
mat.m_Ambient.z = v0;
|
||||||
|
|
||||||
|
app->diffuse.GetColor( v0, v1, v2 );
|
||||||
|
mat.m_Diffuse.x = v0;
|
||||||
|
mat.m_Diffuse.y = v1;
|
||||||
|
mat.m_Diffuse.z = v2;
|
||||||
|
|
||||||
|
app->emissive.GetColor( v0, v1, v2 );
|
||||||
|
mat.m_Emissive.x = v0;
|
||||||
|
mat.m_Emissive.y = v1;
|
||||||
|
mat.m_Emissive.z = v2;
|
||||||
|
|
||||||
|
app->specular.GetColor( v0, v1, v2 );
|
||||||
|
mat.m_Specular.x = v0;
|
||||||
|
mat.m_Specular.y = v1;
|
||||||
|
mat.m_Specular.z = v2;
|
||||||
|
|
||||||
|
mat.m_Shininess = app->shininess;
|
||||||
|
mat.m_Transparency = app->transparency;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class VRML_LOCALE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string lname;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VRML_LOCALE()
|
||||||
|
{
|
||||||
|
lname = setlocale( LC_NUMERIC, NULL );
|
||||||
|
setlocale( LC_NUMERIC, "C" ); // switch the numerics locale to "C"
|
||||||
|
}
|
||||||
|
|
||||||
|
~VRML_LOCALE()
|
||||||
|
{
|
||||||
|
setlocale( LC_NUMERIC, lname.c_str() ); // revert to the previous locale
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::WriteVRML( const wxString& filename, bool overwrite, SGNODE* aTopNode,
|
||||||
|
bool reuse, bool renameNodes )
|
||||||
|
{
|
||||||
|
if( wxFileName::Exists( filename ) )
|
||||||
|
{
|
||||||
|
if( !overwrite )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// make sure we make no attempt to write a directory
|
||||||
|
if( !wxFileName::FileExists( filename ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL == aTopNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aTopNode\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != aTopNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] aTopNode is not a SCENEGRAPH object\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VRML_LOCALE vrmlLocale;
|
||||||
|
std::ofstream op;
|
||||||
|
op.open( filename.ToUTF8(), std::ios_base::out | std::ios_base::trunc
|
||||||
|
| std::ios_base::binary );
|
||||||
|
|
||||||
|
if( !op.is_open() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] failed to open file '" << filename.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
op << "#VRML V2.0 utf8\n";
|
||||||
|
|
||||||
|
if( renameNodes )
|
||||||
|
{
|
||||||
|
aTopNode->ResetNodeIndex();
|
||||||
|
aTopNode->ReNameNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
aTopNode->WriteVRML( op, reuse );
|
||||||
|
|
||||||
|
if( !op.fail() )
|
||||||
|
{
|
||||||
|
op.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
op.close();
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] problems encountered writing file '" << filename.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::ResetNodeIndex( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNode->ResetNodeIndex();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::RenameNodes( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aNode->ReNameNodes();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::DestroyNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete aNode;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::WriteCache( const wxString& aFileName, bool overwrite, SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadNode;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( wxFileName::Exists( aFileName ) )
|
||||||
|
{
|
||||||
|
if( !overwrite )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] file exists; not overwriting: '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we make no attempt to write a directory
|
||||||
|
if( !wxFileName::FileExists( aFileName ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] specified path is a directory: '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream output;
|
||||||
|
output.open( aFileName.ToUTF8(), std::ios_base::out | std::ios_base::trunc
|
||||||
|
| std::ios_base::binary );
|
||||||
|
|
||||||
|
if( !output.is_open() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] failed to open file '" << aFileName.ToUTF8() << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rval = aNode->WriteCache( output, NULL );
|
||||||
|
output.close();
|
||||||
|
|
||||||
|
if( !rval )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] problems encountered writing cache file '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* S3D::ReadCache( const wxString& aFileName )
|
||||||
|
{
|
||||||
|
if( !wxFileName::FileExists( aFileName ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] no such file: '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = new SCENEGRAPH( NULL );
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] failed to instantiate SCENEGRAPH\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream file;
|
||||||
|
file.open( aFileName.ToUTF8(), std::ios_base::in | std::ios_base::binary );
|
||||||
|
|
||||||
|
if( !file.is_open() )
|
||||||
|
{
|
||||||
|
delete np;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] failed to open file '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rval = np->ReadCache( file, NULL );
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if( !rval )
|
||||||
|
{
|
||||||
|
delete np;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] problems encountered reading cache file '";
|
||||||
|
std::cerr << aFileName.ToUTF8() << "'\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return np;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3DMODEL* S3D::Prepare( SCENEGRAPH* aNode, const glm::dmat4* aTransform )
|
||||||
|
{
|
||||||
|
S3D::MATLIST materials;
|
||||||
|
std::vector< SMESH > meshes;
|
||||||
|
|
||||||
|
// the materials list shall have a default color; although the VRML
|
||||||
|
// default is an opaque black, the default used here shall be a median
|
||||||
|
// gray in hopes that it may help highlight faulty models; this color is
|
||||||
|
// also typical of MCAD applications. When a model has no associated
|
||||||
|
// material color it shall be assigned the index 0.
|
||||||
|
SGAPPEARANCE app( NULL );
|
||||||
|
app.ambient = 0.9;
|
||||||
|
app.diffuse = SGCOLOR( 0.6, 0.6, 0.6 );
|
||||||
|
app.specular = app.diffuse;
|
||||||
|
app.shininess = 0.05;
|
||||||
|
app.transparency = 0.0;
|
||||||
|
|
||||||
|
materials.matorder.push_back( &app );
|
||||||
|
materials.matmap.insert( std::pair< SGAPPEARANCE const*, int >( &app, 0 ) );
|
||||||
|
|
||||||
|
if( aNode->Prepare( aTransform, materials, meshes ) )
|
||||||
|
{
|
||||||
|
if( meshes.empty() )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
S3DMODEL* model = S3D::New3DModel();
|
||||||
|
|
||||||
|
// add all the materials
|
||||||
|
size_t j = materials.matorder.size();
|
||||||
|
SMATERIAL* lmat = new SMATERIAL[j];
|
||||||
|
|
||||||
|
for( int i = 0; i < j; ++i )
|
||||||
|
formatMaterial( lmat[i], materials.matorder[i] );
|
||||||
|
|
||||||
|
model->m_Materials = lmat;
|
||||||
|
model->m_MaterialsSize = j;
|
||||||
|
|
||||||
|
// add all the meshes
|
||||||
|
j = meshes.size();
|
||||||
|
SMESH* lmesh = new SMESH[j];
|
||||||
|
|
||||||
|
for( int i = 0; i < j; ++i )
|
||||||
|
lmesh[i] = meshes[i];
|
||||||
|
|
||||||
|
model->m_Meshes = lmesh;
|
||||||
|
model->m_MeshesSize = j;
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t j = meshes.size();
|
||||||
|
|
||||||
|
for( size_t i = 0; i < j; ++i )
|
||||||
|
S3D::Free3DMesh( meshes[i] );
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::Destroy3DModel( S3DMODEL** aModel )
|
||||||
|
{
|
||||||
|
if( NULL == aModel || NULL == *aModel )
|
||||||
|
return;
|
||||||
|
|
||||||
|
S3DMODEL* m = *aModel;
|
||||||
|
S3D::FREE_S3DMODEL( *m );
|
||||||
|
delete m;
|
||||||
|
*aModel = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Free3DModel( S3DMODEL& aModel )
|
||||||
|
{
|
||||||
|
S3D::FREE_S3DMODEL( aModel );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::Free3DMesh( SMESH& aMesh )
|
||||||
|
{
|
||||||
|
S3D::FREE_SMESH( aMesh );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3DMODEL* S3D::New3DModel( void )
|
||||||
|
{
|
||||||
|
S3DMODEL* mp = new S3DMODEL;
|
||||||
|
S3D::INIT_S3DMODEL( *mp );
|
||||||
|
return mp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::Init3DMaterial( SMATERIAL& aMat )
|
||||||
|
{
|
||||||
|
S3D::INIT_SMATERIAL( aMat );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::Init3DMesh( SMESH& aMesh )
|
||||||
|
{
|
||||||
|
S3D::INIT_SMESH( aMesh );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_api.h
|
||||||
|
* defines the API calls for the manipulation of SG* classes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFSG_API_H
|
||||||
|
#define IFSG_API_H
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
|
||||||
|
class SGNODE;
|
||||||
|
class SCENEGRAPH;
|
||||||
|
struct S3D_INFO;
|
||||||
|
struct S3D_POINT;
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function WriteCache
|
||||||
|
* writes the SGNODE tree to a binary cache file
|
||||||
|
*
|
||||||
|
* @param aFileName is the name of the file to write
|
||||||
|
* @param overwrite must be set to true to overwrite an existing file
|
||||||
|
* @param aNode is any node within the node tree which is to be written
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool WriteCache( const wxString& aFileName, bool overwrite, SGNODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReadCache
|
||||||
|
* reads a binary cache file and creates an SGNODE tree
|
||||||
|
*
|
||||||
|
* @param aFileName is the name of the binary cache file to be read
|
||||||
|
* @return NULL on failure, on success a pointer to the top level SCENEGRAPH node;
|
||||||
|
* if desired this node can be associated with an IFSG_TRANSFORM wrapper via
|
||||||
|
* the IFSG_TRANSFORM::Attach() function.
|
||||||
|
*/
|
||||||
|
SGNODE* ReadCache( const wxString& aFileName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WriteVRML
|
||||||
|
* writes out the given node and its subnodes to a VRML2 file
|
||||||
|
*
|
||||||
|
* @param filename is the name of the output file
|
||||||
|
* @param overwrite should be set to true to overwrite an existing VRML file
|
||||||
|
* @param aTopNode is a pointer to a SCENEGRAPH object representing the VRML scene
|
||||||
|
* @param reuse should be set to true to make use of VRML DEF/USE features
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool WriteVRML( const wxString& filename, bool overwrite, SGNODE* aTopNode,
|
||||||
|
bool reuse, bool renameNodes );
|
||||||
|
|
||||||
|
// NOTE: The following functions are used in combination to create a VRML
|
||||||
|
// assembly which may use various instances of each SG* representation of a module.
|
||||||
|
// A typical use case would be:
|
||||||
|
// 1. invoke 'ResetNodeIndex()' to reset the global node name indices
|
||||||
|
// 2. for each model pointer provided by 'S3DCACHE->Load()', invoke 'RenameNodes()' once;
|
||||||
|
// this ensures that all nodes have a unique name to present to the final output file.
|
||||||
|
// Internally, RenameNodes() will only rename the given node and all Child subnodes;
|
||||||
|
// nodes which are only referenced will not be renamed. Using the pointer supplied
|
||||||
|
// by 'S3DCACHE->Load()' ensures that all nodes but the returned node (top node) are
|
||||||
|
// children of at least one node, so all nodes are given unique names.
|
||||||
|
// 3. if SG* trees are created independently of S3DCACHE->Load() the user must invoke
|
||||||
|
// RenameNodes() as appropriate to ensure that all nodes have a unique name
|
||||||
|
// 4. create an assembly structure by creating new IFSG_TRANSFORM nodes as appropriate
|
||||||
|
// for each instance of a component; the component base model as returned by
|
||||||
|
// S3DCACHE->Load() may be added to these IFSG_TRANSFORM nodes via 'AddRefNode()';
|
||||||
|
// set the offset, rotation, etc of the IFSG_TRANSFORM node to ensure correct
|
||||||
|
// 5. Ensure that all new IFSG_TRANSFORM nodes are placed as child nodes within a
|
||||||
|
// top level IFSG_TRANSFORM node in preparation for final node naming and output
|
||||||
|
// 6. Invoke RenameNodes() on the top level assembly node
|
||||||
|
// 7. Invoke WriteVRML() as normal, with renameNodes = false, to write the entire assembly
|
||||||
|
// structure to a single VRML file
|
||||||
|
// 8. Clean up by deleting any extra IFSG_TRANSFORM wrappers and their underlying SG*
|
||||||
|
// classes which have been created solely for the assembly output
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ResetNodeIndex
|
||||||
|
* resets the global SG* class indices
|
||||||
|
*
|
||||||
|
* @param aNode may be any valid SGNODE
|
||||||
|
*/
|
||||||
|
void ResetNodeIndex( SGNODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function RenameNodes
|
||||||
|
* renames a node and all children nodes based on the current
|
||||||
|
* values of the global SG* class indices
|
||||||
|
*
|
||||||
|
* @param aNode is a top level node
|
||||||
|
*/
|
||||||
|
void RenameNodes( SGNODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function DestroyNode
|
||||||
|
* deletes the given SG* class node. This function makes it possible
|
||||||
|
* to safely delete an SG* node without associating the node with
|
||||||
|
* its corresponding IFSG* wrapper.
|
||||||
|
*/
|
||||||
|
void DestroyNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
// NOTE: The following functions facilitate the creation and destruction
|
||||||
|
// of data structures for rendering
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Prepare
|
||||||
|
* creates an S3DMODEL representation of aNode transformed by aTransform.
|
||||||
|
*
|
||||||
|
* @param aNode is the node to be transcribed into an S3DMODEL representation
|
||||||
|
* @param aTransform is the transform (Translation * Rotation * Scale) to apply
|
||||||
|
* to the representation of aNode; it must be a pointer to a glm::dmat4 entity
|
||||||
|
*
|
||||||
|
* @return an S3DMODEL representation of aNode on success, otherwise NULL
|
||||||
|
*/
|
||||||
|
S3DMODEL* Prepare( SCENEGRAPH* aNode, const glm::dmat4* aTransform );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Destroy3DModel
|
||||||
|
* frees memory used by an S3DMODEL structure and sets the pointer to
|
||||||
|
* the structure to NULL
|
||||||
|
*/
|
||||||
|
void Destroy3DModel( S3DMODEL** aModel );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Free3DModel
|
||||||
|
* frees memory used internally by an S3DMODEL structure
|
||||||
|
*/
|
||||||
|
void Free3DModel( S3DMODEL& aModel );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Free3DMesh
|
||||||
|
* frees memory used internally by an SMESH structure
|
||||||
|
*/
|
||||||
|
void Free3DMesh( SMESH& aMesh );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function New3DModel
|
||||||
|
* creates and initializes an S3DMODEL struct
|
||||||
|
*/
|
||||||
|
S3DMODEL* New3DModel( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Init3DMaterial
|
||||||
|
* initializes an SMATERIAL struct
|
||||||
|
*/
|
||||||
|
void Init3DMaterial( SMATERIAL& aMat );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Init3DMesh
|
||||||
|
* creates and initializes an SMESH struct
|
||||||
|
*/
|
||||||
|
void Init3DMesh( SMESH& aMesh );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_API_H
|
|
@ -0,0 +1,344 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_appearance.h>
|
||||||
|
#include <3d_cache/sg/sg_appearance.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_APPEARANCE::IFSG_APPEARANCE( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SGAPPEARANCE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_APPEARANCE::IFSG_APPEARANCE( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGAPPEARANCE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_APPEARANCE::IFSG_APPEARANCE( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGAPPEARANCE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGAPPEARANCE( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGAPPEARANCE\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetEmissive( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetDiffuse( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGAPPEARANCE*)m_node)->SetSpecular( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetAmbient( float aAmbientLight )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aAmbientLight < 0 || aAmbientLight > 1.0 )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] ambient intensity out of range [0..1]\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGAPPEARANCE*)m_node)->ambient = aAmbientLight;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetShininess( float aShininess )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aShininess < 0 || aShininess > 1.0 )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] shininess out of range [0..1]\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGAPPEARANCE*)m_node)->shininess = aShininess;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_APPEARANCE::SetTransparency( float aTransparency )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aTransparency < 0 || aTransparency > 1.0 )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] shininess out of range [0..1]\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGAPPEARANCE*)m_node)->transparency = aTransparency;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_appearance.h
|
||||||
|
* defines the wrapper of the SGAPPEARANCE class
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFSG_APPEARANCE_H
|
||||||
|
#define IFSG_APPEARANCE_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
class IFSG_APPEARANCE : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_APPEARANCE( bool create );
|
||||||
|
IFSG_APPEARANCE( SGNODE* aParent );
|
||||||
|
IFSG_APPEARANCE( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool SetEmissive( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetEmissive( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetEmissive( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetDiffuse( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetDiffuse( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetDiffuse( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetSpecular( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetSpecular( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetSpecular( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetAmbient( float aAmbientLight );
|
||||||
|
bool SetShininess( float aShininess );
|
||||||
|
bool SetTransparency( float aTransparency );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_APPEARANCE_H
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_colorindex.h>
|
||||||
|
#include <3d_cache/sg/sg_colorindex.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORINDEX::IFSG_COLORINDEX( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node = new SGCOLORINDEX( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORINDEX::IFSG_COLORINDEX( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGCOLORINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORINDEX::IFSG_COLORINDEX( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( !pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGCOLORINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORINDEX::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_COLORINDEX != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORINDEX::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGCOLORINDEX( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGCOLORINDEX\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORINDEX::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_colorindex.h
|
||||||
|
* defines the ColorIndex node wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_COLORINDEX_H
|
||||||
|
#define IFSG_COLORINDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_index.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_COLORINDEX
|
||||||
|
* is the wrapper for SGCOLORINDEX
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_COLORINDEX : public IFSG_INDEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_COLORINDEX( bool create );
|
||||||
|
IFSG_COLORINDEX( SGNODE* aParent );
|
||||||
|
IFSG_COLORINDEX( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_COLORINDEX_H
|
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_colors.h>
|
||||||
|
#include <3d_cache/sg/sg_colors.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORS::IFSG_COLORS( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SGCOLORS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORS::IFSG_COLORS( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGCOLORS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COLORS::IFSG_COLORS( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGCOLORS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_COLORS != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGCOLORS( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGCOLORS\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGCOLORS*)m_node)->GetColorList( aListSize, aColorList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::SetColorList( size_t& aListSize, const SGCOLOR* aColorList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOLORS*)m_node)->SetColorList( aListSize, aColorList );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOLORS*)m_node)->AddColor( aRedValue, aGreenValue, aBlueValue );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COLORS::AddColor( const SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOLORS*)m_node)->AddColor( aColor );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_colors.h
|
||||||
|
* defines the color list wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_COLORS_H
|
||||||
|
#define IFSG_COLORS_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_INDEX
|
||||||
|
* is the wrapper for SGCOLORS
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_COLORS : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_COLORS( bool create );
|
||||||
|
IFSG_COLORS( SGNODE* aParent );
|
||||||
|
IFSG_COLORS( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||||
|
bool SetColorList( size_t& aListSize, const SGCOLOR* aColorList );
|
||||||
|
bool AddColor( double aRedValue, double aGreenValue, double aBlueValue );
|
||||||
|
bool AddColor( const SGCOLOR& aColor );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_COLORS_H
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/sg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDINDEX::IFSG_COORDINDEX( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node = new SGCOORDINDEX( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDINDEX::IFSG_COORDINDEX( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGCOORDINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDINDEX::IFSG_COORDINDEX( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( !pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGCOORDINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDINDEX::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_COORDINDEX != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDINDEX::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGCOORDINDEX( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGCOORDINDEX\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDINDEX::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_coordindex.h
|
||||||
|
* defines the CoordIndex node wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_COORDINDEX_H
|
||||||
|
#define IFSG_COORDINDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_index.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_COORDINDEX
|
||||||
|
* is the wrapper for SGCOORDINDEX
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_COORDINDEX : public IFSG_INDEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_COORDINDEX( bool create );
|
||||||
|
IFSG_COORDINDEX( SGNODE* aParent );
|
||||||
|
IFSG_COORDINDEX( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_COORDINDEX_H
|
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_coords.h>
|
||||||
|
#include <3d_cache/sg/sg_coords.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDS::IFSG_COORDS( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SGCOORDS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDS::IFSG_COORDS( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGCOORDS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_COORDS::IFSG_COORDS( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGCOORDS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_COORDS != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGCOORDS( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGCOORDS\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGCOORDS*)m_node)->GetCoordsList( aListSize, aCoordsList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOORDS*)m_node)->SetCoordsList( aListSize, aCoordsList );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOORDS*)m_node)->AddCoord( aXValue, aYValue, aZValue );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_COORDS::AddCoord( const SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGCOORDS*)m_node)->AddCoord( aPoint );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_coords.h
|
||||||
|
* defines the coordinate list wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_COORDS_H
|
||||||
|
#define IFSG_COORDS_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_INDEX
|
||||||
|
* is the wrapper for SGCOORDS
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_COORDS : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_COORDS( bool create );
|
||||||
|
IFSG_COORDS( SGNODE* aParent );
|
||||||
|
IFSG_COORDS( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||||
|
bool SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||||
|
bool AddCoord( double aXValue, double aYValue, double aZValue );
|
||||||
|
bool AddCoord( const SGPOINT& aPoint );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_COORDS_H
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFSG_DEFS_H
|
||||||
|
#define IFSG_DEFS_H
|
||||||
|
|
||||||
|
#if defined( MSVC )
|
||||||
|
#if defined( DLL_SGIF )
|
||||||
|
// we are building the library
|
||||||
|
#define SG_DLL __declspec( dllexport )
|
||||||
|
#else
|
||||||
|
// we must be using the library
|
||||||
|
#define SG_DLL __declspec( dllimport )
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SG_DLL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // IFSG_DEFS_H
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_faceset.h>
|
||||||
|
#include <3d_cache/sg/sg_faceset.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_FACESET::IFSG_FACESET( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SGFACESET( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_FACESET::IFSG_FACESET( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGFACESET( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_FACESET::IFSG_FACESET( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGFACESET( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_FACESET::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_FACESET != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_FACESET::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGFACESET( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGFACESET\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_FACESET::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_faceset.h
|
||||||
|
* defines the wrapper for the SGFACESET class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_FACESET_H
|
||||||
|
#define IFSG_FACESET_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_FACESET
|
||||||
|
* is the wrapper for the SGFACESET class
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_FACESET : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_FACESET( bool create );
|
||||||
|
IFSG_FACESET( SGNODE* aParent );
|
||||||
|
IFSG_FACESET( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_FACESET_H
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_index.h>
|
||||||
|
#include <3d_cache/sg/sg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/sg_colorindex.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_INDEX::IFSG_INDEX() : IFSG_NODE()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_INDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGINDEX*)m_node)->GetIndices( nIndices, aIndexList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_INDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGINDEX*)m_node)->SetIndices( nIndices, aIndexList );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_INDEX::AddIndex( int aIndex )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGINDEX*)m_node)->AddIndex( aIndex );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_index.h
|
||||||
|
* defines the index nodes wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_INDEX_H
|
||||||
|
#define IFSG_INDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_INDEX
|
||||||
|
* is the wrapper for SGINDEX
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_INDEX : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_INDEX();
|
||||||
|
|
||||||
|
virtual bool Attach( SGNODE* aNode ) = 0;
|
||||||
|
virtual bool NewNode( SGNODE* aParent ) = 0;
|
||||||
|
virtual bool NewNode( IFSG_NODE& aParent ) = 0;
|
||||||
|
|
||||||
|
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetIndices
|
||||||
|
* sets the number of indices and creates a copy of the given index data.
|
||||||
|
*
|
||||||
|
* @param nIndices [in] the number of indices to be stored
|
||||||
|
* @param aIndexList [in] the index data
|
||||||
|
*/
|
||||||
|
bool SetIndices( size_t nIndices, int* aIndexList );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function AddIndex
|
||||||
|
* adds a single index to the list
|
||||||
|
*
|
||||||
|
* @param nIndices [in] the number of indices to be stored
|
||||||
|
* @param aIndexList [in] the index data
|
||||||
|
*/
|
||||||
|
bool AddIndex( int aIndex );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_INDEX_H
|
|
@ -0,0 +1,216 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_node.h>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
#include <3d_cache/sg/ifsg_api.h>
|
||||||
|
|
||||||
|
// collection of common error strings used by the wrappers
|
||||||
|
char BadObject[] = " * [BUG] operating on an invalid wrapper (object may have been deleted)";
|
||||||
|
char BadOperand[] = " * [BUG] parameter aNode is an invalid wrapper; its data may have been deleted";
|
||||||
|
char BadParent[] = " * [BUG] invalid parent node (data may have been deleted)";
|
||||||
|
char WrongParent[] = " * [BUG] parent node type is incompatible";
|
||||||
|
|
||||||
|
IFSG_NODE::IFSG_NODE()
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NODE::~IFSG_NODE()
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* IFSG_NODE::GetRawPtr( void )
|
||||||
|
{
|
||||||
|
return m_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D::SGTYPES IFSG_NODE::GetNodeType( void ) const
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return S3D::SGTYPE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->GetNodeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* IFSG_NODE::GetParent( void ) const
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->GetParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::SetParent( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->SetParent( aParent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* IFSG_NODE::GetName( void )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::SetName( const char *aName )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->SetName( aName );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * IFSG_NODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->GetNodeTypeName( aNodeType );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* IFSG_NODE::FindNode( const char *aNodeName )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->FindNode( aNodeName, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->AddRefNode( aNode );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::AddRefNode( IFSG_NODE& aNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = aNode.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadOperand << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->AddRefNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->AddChildNode( aNode );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NODE::AddChildNode( IFSG_NODE& aNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = aNode.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadOperand << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_node->AddChildNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_node.h
|
||||||
|
* defines the wrapper of the base class SG_NODE
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTES:
|
||||||
|
* 1. The IFSG wrapper classes shall be aimed at creating a VRML-like
|
||||||
|
* intermediate scenegraph representation. Although objects are
|
||||||
|
* readily created and added to the structure, no provision shall
|
||||||
|
* be made to inspect the structures in detail. For example the
|
||||||
|
* SCENEGRAPH class may contain various SGSHAPE and SCENEGRAPH
|
||||||
|
* nodes but there shall be no provision to extract those nodes.
|
||||||
|
* This was done because in principle all the detailed data shall
|
||||||
|
* only be handled within the SG* classes and only data processed
|
||||||
|
* via GetRenderData() shall be available via the wrappers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IFSG_NODE_H
|
||||||
|
#define IFSG_NODE_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
#include <3d_cache/sg/ifsg_defs.h>
|
||||||
|
|
||||||
|
class SGNODE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_NODE
|
||||||
|
* represents the base class of all DLL-safe Scene Graph nodes
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_NODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// hide the copy constructors and assignment operator to avoid accidental misuse
|
||||||
|
IFSG_NODE( const IFSG_NODE& aParent );
|
||||||
|
IFSG_NODE( IFSG_NODE& aParent );
|
||||||
|
IFSG_NODE( volatile const IFSG_NODE& aParent );
|
||||||
|
IFSG_NODE( volatile IFSG_NODE& aParent );
|
||||||
|
IFSG_NODE& operator= ( const IFSG_NODE& );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SGNODE* m_node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
IFSG_NODE();
|
||||||
|
virtual ~IFSG_NODE();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Destroy
|
||||||
|
* deletes the object held by this wrapper
|
||||||
|
*/
|
||||||
|
void Destroy( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Attach
|
||||||
|
* associates a given SGNODE* with this wrapper
|
||||||
|
*/
|
||||||
|
virtual bool Attach( SGNODE* aNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function NewNode
|
||||||
|
* creates a new node to associate with this wrapper
|
||||||
|
*/
|
||||||
|
virtual bool NewNode( SGNODE* aParent ) = 0;
|
||||||
|
virtual bool NewNode( IFSG_NODE& aParent ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetRawPtr()
|
||||||
|
* returns the raw internal SGNODE pointer
|
||||||
|
*/
|
||||||
|
SGNODE* GetRawPtr( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetNodeType
|
||||||
|
* returns the type of this node instance
|
||||||
|
*/
|
||||||
|
S3D::SGTYPES 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).
|
||||||
|
*/
|
||||||
|
SGNODE* GetParent( void ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetParent
|
||||||
|
* sets the parent SGNODE of this object.
|
||||||
|
*
|
||||||
|
* @param aParent [in] is the desired parent node
|
||||||
|
* @return true if the operation succeeds; false if
|
||||||
|
* the given node is not allowed to be a parent to
|
||||||
|
* the derived object
|
||||||
|
*/
|
||||||
|
bool SetParent( SGNODE* aParent );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetName
|
||||||
|
* returns a pointer to the node name (NULL if no name assigned)
|
||||||
|
*/
|
||||||
|
const char* GetName( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetName
|
||||||
|
* sets the node's name; if the pointer passed is NULL
|
||||||
|
* then the node's name is erased
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool SetName( const char *aName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetNodeTypeName
|
||||||
|
* returns the text representation of the node type
|
||||||
|
* or NULL if the node somehow has an invalid type
|
||||||
|
*/
|
||||||
|
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindNode searches the tree of linked nodes and returns a
|
||||||
|
* reference to the first node found 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
|
||||||
|
* @param aCaller is a pointer to the node invoking this function
|
||||||
|
* @return is a valid node pointer on success, otherwise NULL
|
||||||
|
*/
|
||||||
|
SGNODE* FindNode( const char *aNodeName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function AddRefNode
|
||||||
|
* adds a reference to an existing node which is not owned by
|
||||||
|
* (not a child of) this node.
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddRefNode( IFSG_NODE& aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function AddChildNode
|
||||||
|
* adds a node as a child owned by this node.
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( IFSG_NODE& aNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_NODE_H
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_normalindex.h>
|
||||||
|
#include <3d_cache/sg/sg_normalindex.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALINDEX::IFSG_NORMALINDEX( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node = new SGNORMALINDEX( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALINDEX::IFSG_NORMALINDEX( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGNORMALINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALINDEX::IFSG_NORMALINDEX( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( !pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGNORMALINDEX( NULL );
|
||||||
|
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALINDEX::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_NORMALINDEX != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALINDEX::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGNORMALINDEX( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGNORMALINDEX\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALINDEX::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_coordindex.h
|
||||||
|
* defines the CoordIndex node wrapper
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_NORMALINDEX_H
|
||||||
|
#define IFSG_NORMALINDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_index.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_NORMALINDEX
|
||||||
|
* is the wrapper for SGNORMALINDEX
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_NORMALINDEX : public IFSG_INDEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_NORMALINDEX( bool create );
|
||||||
|
IFSG_NORMALINDEX( SGNODE* aParent );
|
||||||
|
IFSG_NORMALINDEX( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_NORMALINDEX_H
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_normals.h>
|
||||||
|
#include <3d_cache/sg/sg_normals.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALS::IFSG_NORMALS( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_node = new SGNORMALS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALS::IFSG_NORMALS( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGNORMALS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_NORMALS::IFSG_NORMALS( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGNORMALS( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_NORMALS != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGNORMALS( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGNORMALS\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((SGNORMALS*)m_node)->GetNormalList( aListSize, aNormalList );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGNORMALS*)m_node)->SetNormalList( aListSize, aNormalList );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGNORMALS*)m_node)->AddNormal( aXValue, aYValue, aZValue );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_NORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SGNORMALS*)m_node)->AddNormal( aNormal );
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_transform.h
|
||||||
|
* defines the wrapper for the SGNORMALS class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_NORMALS_H
|
||||||
|
#define IFSG_NORMALS_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_NORMALS
|
||||||
|
* is the wrapper for the SGNORMALS class
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_NORMALS : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_NORMALS( bool create );
|
||||||
|
IFSG_NORMALS( SGNODE* aParent );
|
||||||
|
IFSG_NORMALS( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||||
|
bool SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||||
|
bool AddNormal( double aXValue, double aYValue, double aZValue );
|
||||||
|
bool AddNormal( const SGVECTOR& aNormal );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_NORMALS_H
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_shape.h>
|
||||||
|
#include <3d_cache/sg/sg_shape.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_SHAPE::IFSG_SHAPE( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SGSHAPE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_SHAPE::IFSG_SHAPE( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SGSHAPE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_SHAPE::IFSG_SHAPE( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* pp = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( ! pp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = new SGSHAPE( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( pp ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_SHAPE::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_SHAPE != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_SHAPE::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SGSHAPE( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SGSHAPE\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_SHAPE::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_shape.h
|
||||||
|
* defines the wrapper for the SGSHAPE class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_SHAPE_H
|
||||||
|
#define IFSG_SHAPE_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_SHAPE
|
||||||
|
* is the wrapper for the SGSHAPE class
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_SHAPE : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_SHAPE( bool create );
|
||||||
|
IFSG_SHAPE( SGNODE* aParent );
|
||||||
|
IFSG_SHAPE( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_SHAPE_H
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/ifsg_transform.h>
|
||||||
|
#include <3d_cache/sg/scenegraph.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern char BadObject[];
|
||||||
|
extern char BadOperand[];
|
||||||
|
extern char BadParent[];
|
||||||
|
extern char WrongParent[];
|
||||||
|
|
||||||
|
IFSG_TRANSFORM::IFSG_TRANSFORM( bool create )
|
||||||
|
{
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
return ;
|
||||||
|
|
||||||
|
m_node = new SCENEGRAPH( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
IFSG_TRANSFORM::IFSG_TRANSFORM( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_node = new SCENEGRAPH( NULL );
|
||||||
|
|
||||||
|
if( m_node )
|
||||||
|
{
|
||||||
|
if( !m_node->SetParent( aParent ) )
|
||||||
|
{
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << WrongParent << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::Attach( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = NULL;
|
||||||
|
|
||||||
|
if( !aNode )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node = aNode;
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::NewNode( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
if( m_node )
|
||||||
|
m_node->DisassociateWrapper( &m_node );
|
||||||
|
|
||||||
|
m_node = new SCENEGRAPH( aParent );
|
||||||
|
|
||||||
|
if( aParent != m_node->GetParent() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid SGNODE parent (";
|
||||||
|
std::cerr << aParent->GetNodeTypeName( aParent->GetNodeType() );
|
||||||
|
std::cerr << ") to SCENEGRAPH\n";
|
||||||
|
delete m_node;
|
||||||
|
m_node = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_node->AssociateWrapper( &m_node );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::NewNode( IFSG_NODE& aParent )
|
||||||
|
{
|
||||||
|
SGNODE* np = aParent.GetRawPtr();
|
||||||
|
|
||||||
|
if( NULL == np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadParent << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewNode( np );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetRotation( const SGVECTOR& aRotationAxis, double aAngle )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->rotation_axis = aRotationAxis;
|
||||||
|
((SCENEGRAPH*)m_node)->rotation_angle = aAngle;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetScale( const SGPOINT& aScale )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->scale = aScale;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetScale( double aScale )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aScale < 1e-8 && aScale > -1e-8 )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] |scale| is < 1e-8 - this seems strange\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->scale = SGPOINT( aScale, aScale, aScale );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetTranslation( const SGPOINT& aTranslation )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->translation = aTranslation;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->scale_axis = aScaleAxis;
|
||||||
|
((SCENEGRAPH*)m_node)->scale_angle = aAngle;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IFSG_TRANSFORM::SetCenter( const SGPOINT& aCenter )
|
||||||
|
{
|
||||||
|
if( NULL == m_node )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << BadObject << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
((SCENEGRAPH*)m_node)->center = aCenter;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 ifsg_transform.h
|
||||||
|
* defines the wrapper for the SCENEGRAPH class
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef IFSG_TRANSFORM_H
|
||||||
|
#define IFSG_TRANSFORM_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/ifsg_node.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class IFSG_TRANSFORM
|
||||||
|
* is the wrapper for the VRML compatible TRANSFORM block class SCENEGRAPH
|
||||||
|
*/
|
||||||
|
class SG_DLL IFSG_TRANSFORM : public IFSG_NODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IFSG_TRANSFORM( bool create );
|
||||||
|
IFSG_TRANSFORM( SGNODE* aParent );
|
||||||
|
// note: IFSG_TRANSFORM( IFSG_NODE& aParent ) does not exist
|
||||||
|
// since a transform may own another transform and that construct
|
||||||
|
// invites accidental misuse of the copy constructor
|
||||||
|
|
||||||
|
bool Attach( SGNODE* aNode );
|
||||||
|
bool NewNode( SGNODE* aParent );
|
||||||
|
bool NewNode( IFSG_NODE& aParent );
|
||||||
|
|
||||||
|
bool SetScaleOrientation( const SGVECTOR& aScaleAxis, double aAngle );
|
||||||
|
bool SetRotation( const SGVECTOR& aRotationAxis, double aAngle );
|
||||||
|
bool SetScale( const SGPOINT& aScale );
|
||||||
|
bool SetScale( double aScale );
|
||||||
|
bool SetCenter( const SGPOINT& aCenter );
|
||||||
|
bool SetTranslation( const SGPOINT& aTranslation );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IFSG_TRANSFORM_H
|
|
@ -0,0 +1,636 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <glm/gtx/transform.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <3d_cache/sg/scenegraph.h>
|
||||||
|
#include <3d_cache/sg/sg_shape.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
|
||||||
|
SCENEGRAPH::SCENEGRAPH( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_TRANSFORM;
|
||||||
|
rotation_angle = 0.0;
|
||||||
|
scale.x = 1.0;
|
||||||
|
scale.y = 1.0;
|
||||||
|
scale.z = 1.0;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SCENEGRAPH (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCENEGRAPH::~SCENEGRAPH()
|
||||||
|
{
|
||||||
|
// drop references
|
||||||
|
DROP_REFS( SCENEGRAPH, m_RTransforms );
|
||||||
|
DROP_REFS( SGSHAPE, m_RShape );
|
||||||
|
|
||||||
|
// delete owned objects
|
||||||
|
DEL_OBJS( SCENEGRAPH, m_Transforms );
|
||||||
|
DEL_OBJS( SGSHAPE, m_Shape );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a transform may be parent to a transform
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SCENEGRAPH::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
FIND_NODE( SCENEGRAPH, aNodeName, m_Transforms, aCaller );
|
||||||
|
FIND_NODE( SGSHAPE, aNodeName, m_Shape, aCaller );
|
||||||
|
|
||||||
|
// query the parent if appropriate
|
||||||
|
if( aCaller == m_Parent || NULL == m_Parent )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_Parent->FindNode( aNodeName, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCENEGRAPH::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
return;
|
||||||
|
|
||||||
|
UNLINK_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||||
|
UNLINK_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unlinkNode() did not find its target\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCENEGRAPH::unlinkChildNode( const SGNODE* aNode )
|
||||||
|
{
|
||||||
|
unlinkNode( aNode, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCENEGRAPH::unlinkRefNode( const SGNODE* aNode )
|
||||||
|
{
|
||||||
|
unlinkNode( aNode, false );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::addNode( SGNODE* aNode, bool isChild )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aNode\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_NODE( S3D::SGTYPE_TRANSFORM, SCENEGRAPH, aNode, m_Transforms, m_RTransforms, isChild );
|
||||||
|
ADD_NODE( S3D::SGTYPE_SHAPE, SGSHAPE, aNode, m_Shape, m_RShape, isChild );
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] object '" << aNode->GetName();
|
||||||
|
std::cerr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
return addNode( aNode, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
return addNode( aNode, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCENEGRAPH::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
|
||||||
|
// rename all shapes
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||||
|
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->ReNameNodes();
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
// rename all transforms
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||||
|
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->ReNameNodes();
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( m_Transforms.empty() && m_RTransforms.empty()
|
||||||
|
&& m_Shape.empty() && m_RShape.empty() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << "DEF " << GetName() << " Transform {\n";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << "USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " Transform {\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
S3D::FormatPoint( tmp, center );
|
||||||
|
aFile << " center " << tmp << "\n";
|
||||||
|
S3D::FormatOrientation( tmp, rotation_axis, rotation_angle );
|
||||||
|
aFile << " rotation " << tmp << "\n";
|
||||||
|
S3D::FormatPoint( tmp, scale );
|
||||||
|
aFile << " scale " << tmp << "\n";
|
||||||
|
S3D::FormatOrientation( tmp, scale_axis, scale_angle );
|
||||||
|
aFile << " scaleOrientation " << tmp << "\n";
|
||||||
|
S3D::FormatPoint( tmp, translation );
|
||||||
|
aFile << " translation " << tmp << "\n";
|
||||||
|
|
||||||
|
aFile << " children [\n";
|
||||||
|
|
||||||
|
if( !m_Transforms.empty() )
|
||||||
|
{
|
||||||
|
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||||
|
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_RTransforms.empty() )
|
||||||
|
{
|
||||||
|
std::vector< SCENEGRAPH* >::iterator sL = m_RTransforms.begin();
|
||||||
|
std::vector< SCENEGRAPH* >::iterator eL = m_RTransforms.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_Shape.empty() )
|
||||||
|
{
|
||||||
|
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||||
|
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !m_RShape.empty() )
|
||||||
|
{
|
||||||
|
std::vector< SGSHAPE* >::iterator sL = m_RShape.begin();
|
||||||
|
std::vector< SGSHAPE* >::iterator eL = m_RShape.end();
|
||||||
|
|
||||||
|
while( sL != eL )
|
||||||
|
{
|
||||||
|
(*sL)->WriteVRML( aFile, aReuseFlag );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "] }\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode && NULL != m_Parent )
|
||||||
|
{
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
// ensure unique node names
|
||||||
|
ResetNodeIndex();
|
||||||
|
ReNameNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
S3D::WritePoint( aFile, center );
|
||||||
|
S3D::WritePoint( aFile, translation );
|
||||||
|
S3D::WriteVector( aFile, rotation_axis );
|
||||||
|
aFile.write( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||||
|
S3D::WritePoint( aFile, scale );
|
||||||
|
S3D::WriteVector( aFile, scale_axis );
|
||||||
|
aFile.write( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||||
|
|
||||||
|
size_t asize = m_Transforms.size();
|
||||||
|
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||||
|
asize = m_RTransforms.size();
|
||||||
|
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||||
|
asize = m_Shape.size();
|
||||||
|
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||||
|
asize = m_RShape.size();
|
||||||
|
aFile.write( (char*)&asize, sizeof( size_t ) );
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
asize = m_Transforms.size();
|
||||||
|
|
||||||
|
// write child transforms
|
||||||
|
for( i = 0; i < asize; ++i )
|
||||||
|
{
|
||||||
|
if( !m_Transforms[i]->WriteCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream while writing child transforms\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write referenced transform names
|
||||||
|
asize = m_RTransforms.size();
|
||||||
|
for( i = 0; i < asize; ++i )
|
||||||
|
aFile << "[" << m_RTransforms[i]->GetName() << "]";
|
||||||
|
|
||||||
|
// write child shapes
|
||||||
|
asize = m_Shape.size();
|
||||||
|
for( i = 0; i < asize; ++i )
|
||||||
|
{
|
||||||
|
if( !m_Shape[i]->WriteCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream while writing child shapes\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write referenced transform names
|
||||||
|
asize = m_RShape.size();
|
||||||
|
for( i = 0; i < asize; ++i )
|
||||||
|
aFile << "[" << m_RShape[i]->GetName() << "]";
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( !m_Transforms.empty() || !m_RTransforms.empty()
|
||||||
|
|| !m_Shape.empty() || !m_RShape.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name; // name of the node
|
||||||
|
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
// we need to read the tag and verify its type
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; tag mismatch at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read fixed member data
|
||||||
|
S3D::ReadPoint( aFile, center );
|
||||||
|
S3D::ReadPoint( aFile, translation );
|
||||||
|
S3D::ReadVector( aFile, rotation_axis );
|
||||||
|
aFile.read( (char*)&rotation_angle, sizeof( rotation_angle ) );
|
||||||
|
S3D::ReadPoint( aFile, scale );
|
||||||
|
S3D::ReadVector( aFile, scale_axis );
|
||||||
|
aFile.read( (char*)&scale_angle, sizeof( scale_angle ) );
|
||||||
|
|
||||||
|
size_t sizeCT = 0; // child transforms
|
||||||
|
size_t sizeRT = 0; // referenced transforms
|
||||||
|
size_t sizeCS = 0; // child shapes
|
||||||
|
size_t sizeRS = 0; // referenced shapes
|
||||||
|
|
||||||
|
aFile.read( (char*)&sizeCT, sizeof( size_t ) );
|
||||||
|
aFile.read( (char*)&sizeRT, sizeof( size_t ) );
|
||||||
|
aFile.read( (char*)&sizeCS, sizeof( size_t ) );
|
||||||
|
aFile.read( (char*)&sizeRS, sizeof( size_t ) );
|
||||||
|
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
// read child transforms
|
||||||
|
for( i = 0; i < sizeCT; ++i )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad child transform tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SCENEGRAPH* sp = new SCENEGRAPH( this );
|
||||||
|
sp->SetName( name.c_str() );
|
||||||
|
|
||||||
|
if( !sp->ReadCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data while reading transform '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read referenced transforms
|
||||||
|
for( i = 0; i < sizeRT; ++i )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad ref transform tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* sp = FindNode( name.c_str(), this );
|
||||||
|
|
||||||
|
if( !sp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: cannot find ref transform '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_TRANSFORM != sp->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: type is not TRANSFORM '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddRefNode( sp );
|
||||||
|
}
|
||||||
|
|
||||||
|
// read child shapes
|
||||||
|
for( i = 0; i < sizeCS; ++i )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad child shape tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGSHAPE* sp = new SGSHAPE( this );
|
||||||
|
sp->SetName( name.c_str() );
|
||||||
|
|
||||||
|
if( !sp->ReadCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data while reading shape '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read referenced shapes
|
||||||
|
for( i = 0; i < sizeRS; ++i )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_SHAPE != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad ref shape tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* sp = FindNode( name.c_str(), this );
|
||||||
|
|
||||||
|
if( !sp )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: cannot find ref shape '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_SHAPE != sp->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: type is not SGSHAPE '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddRefNode( sp );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SCENEGRAPH::Prepare( const glm::dmat4* aTransform,
|
||||||
|
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||||
|
{
|
||||||
|
// calculate the accumulated transform
|
||||||
|
double rX, rY, rZ;
|
||||||
|
rotation_axis.GetVector( rX, rY, rZ );
|
||||||
|
glm::dmat4 rM = glm::rotate( glm::degrees( rotation_angle ), glm::dvec3( rX, rY, rZ ) );
|
||||||
|
glm::dmat4 tM = glm::translate( glm::dvec3( translation.x, translation.y, translation.z ) );
|
||||||
|
glm::dmat4 tx0 = (*aTransform) * tM * rM;
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
// prepare all shapes
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::vector< SGSHAPE* >::iterator sL = m_Shape.begin();
|
||||||
|
std::vector< SGSHAPE* >::iterator eL = m_Shape.end();
|
||||||
|
|
||||||
|
while( sL != eL && ok )
|
||||||
|
{
|
||||||
|
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sL = m_RShape.begin();
|
||||||
|
eL = m_RShape.end();
|
||||||
|
|
||||||
|
while( sL != eL && ok )
|
||||||
|
{
|
||||||
|
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
// prepare all transforms
|
||||||
|
do
|
||||||
|
{
|
||||||
|
std::vector< SCENEGRAPH* >::iterator sL = m_Transforms.begin();
|
||||||
|
std::vector< SCENEGRAPH* >::iterator eL = m_Transforms.end();
|
||||||
|
|
||||||
|
while( sL != eL && ok )
|
||||||
|
{
|
||||||
|
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sL = m_RTransforms.begin();
|
||||||
|
eL = m_RTransforms.end();
|
||||||
|
|
||||||
|
while( sL != eL && ok )
|
||||||
|
{
|
||||||
|
ok = (*sL)->Prepare( &tx0, materials, meshes );
|
||||||
|
++sL;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 scenegraph.h
|
||||||
|
* defines the basic data set required to represent a 3D model;
|
||||||
|
* this model must remain compatible with VRML2.0 in order to
|
||||||
|
* facilitate VRML export of scene graph data created by avaiable
|
||||||
|
* 3D plugins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SCENE_GRAPH_H
|
||||||
|
#define SCENE_GRAPH_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGSHAPE;
|
||||||
|
|
||||||
|
class SCENEGRAPH : public SGNODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The following are items which may be defined for reuse
|
||||||
|
// in a VRML output file. They do not necessarily correspond
|
||||||
|
// to the use of DEF within a VRML input file; it is the
|
||||||
|
// responsibility of the plugin to perform any necessary
|
||||||
|
// conversions to comply with the restrictions imposed by
|
||||||
|
// this scene graph structure
|
||||||
|
std::vector< SCENEGRAPH* > m_Transforms; // local Transform nodes
|
||||||
|
std::vector< SGSHAPE* > m_Shape; // local Shape nodes
|
||||||
|
|
||||||
|
std::vector< SCENEGRAPH* > m_RTransforms; // referenced Transform nodes
|
||||||
|
std::vector< SGSHAPE* > m_RShape; // referenced Shape nodes
|
||||||
|
|
||||||
|
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||||
|
bool addNode( SGNODE* aNode, bool isChild );
|
||||||
|
|
||||||
|
public:
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// note: order of transformation is Translate, Rotate, Offset
|
||||||
|
SGPOINT center;
|
||||||
|
SGPOINT translation;
|
||||||
|
SGVECTOR rotation_axis;
|
||||||
|
double rotation_angle; // radians
|
||||||
|
SGPOINT scale;
|
||||||
|
SGVECTOR scale_axis;
|
||||||
|
double scale_angle; // radians
|
||||||
|
|
||||||
|
SCENEGRAPH( SGNODE* aParent );
|
||||||
|
virtual ~SCENEGRAPH();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
|
||||||
|
bool Prepare( const glm::dmat4* aTransform,
|
||||||
|
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
p.120
|
||||||
|
Transform {
|
||||||
|
center 0 0 0
|
||||||
|
children []
|
||||||
|
rotation 0 0 1 0
|
||||||
|
scale 1 1 1
|
||||||
|
scaleOrientation 0 0 1 0
|
||||||
|
translation 0 0 0
|
||||||
|
bboxCenter 0 0 0
|
||||||
|
bboxSize -1 -1 -1
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // SCENE_GRAPH_H
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_api.h
|
||||||
|
* provides the API which plugins require to manipulate the SG* classes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_API_H
|
||||||
|
#define SG_API_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
|
||||||
|
class SGCOLOR;
|
||||||
|
class SGPOINT;
|
||||||
|
class SGVECTOR;
|
||||||
|
class SGNODE;
|
||||||
|
class SCENEGRAPH;
|
||||||
|
|
||||||
|
// creation and manipulation of base types
|
||||||
|
typedef SGCOLOR* (*NEW_SGBASE_COLOR)(void);
|
||||||
|
typedef bool ( *SET_SGBASE_COLOR )( SGCOLOR* aColor,
|
||||||
|
float aRedVal, float aGreenVal, float aBlueVal );
|
||||||
|
typedef bool ( *GET_SGBASE_COLOR )( SGCOLOR* aColor,
|
||||||
|
float& aRedVal, float& aGreenVal, float& aBlueVal );
|
||||||
|
|
||||||
|
typedef SGPOINT* ( *NEW_SGBASE_POINT )(void);
|
||||||
|
typedef bool ( *SET_SGBASE_POINT )( SGPOINT* aPoint,
|
||||||
|
double aXVal, double aYVal, double aZVal );
|
||||||
|
typedef bool ( *GET_SGBASE_POINT )( SGPOINT* aPoint,
|
||||||
|
double& aXVal, double& aYVal, double& aZVal );
|
||||||
|
|
||||||
|
typedef SGVECTOR* (*NEW_SGBASE_VECTOR)(void);
|
||||||
|
typedef bool ( *SET_SGBASE_VECTOR )( SGPOINT* aVector,
|
||||||
|
double aXVal, double aYVal, double aZVal );
|
||||||
|
typedef bool ( *GET_SGBASE_VECTOR )( SGPOINT* aVector,
|
||||||
|
double& aXVal, double& aYVal, double& aZVal );
|
||||||
|
// creation of scenegraph nodes:
|
||||||
|
typedef SGNODE* (*NEW_SG_NODE)( SGNODE* aParent, S3D::SGTYPES aNodeType);
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
struct SG_API
|
||||||
|
{
|
||||||
|
// creation of basic SG types
|
||||||
|
NEW_SGBASE_COLOR NewColor;
|
||||||
|
NEW_SGBASE_POINT NewPoint;
|
||||||
|
NEW_SGBASE_VECTOR NewVector;
|
||||||
|
// manipulators for basic SG types
|
||||||
|
SET_SGBASE_COLOR SetSGColor;
|
||||||
|
GET_SGBASE_COLOR GetSGColor;
|
||||||
|
SET_SGBASE_POINT SetSGPoint;
|
||||||
|
GET_SGBASE_POINT GetSGPoint;
|
||||||
|
SET_SGBASE_VECTOR SetSGVector;
|
||||||
|
GET_SGBASE_VECTOR GetSGVector;
|
||||||
|
|
||||||
|
// creation of nodes
|
||||||
|
NEW_SG_NODE NewNode;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// generic node class; this must never be instantiated as an underived class
|
||||||
|
class API_SGNODE
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
SGNODE* node;
|
||||||
|
S3D::SGTYPES nodeType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
API_SGNODE();
|
||||||
|
|
||||||
|
SGNODE* GetNode( void );
|
||||||
|
|
||||||
|
bool AttachNode( SGNODE* aNode );
|
||||||
|
bool GetNodeType( S3D::SGTYPES& aNodeType ) const;
|
||||||
|
|
||||||
|
bool GetParent( SGNODE const*& aParent ) const;
|
||||||
|
bool SetParent( SGNODE* aParent );
|
||||||
|
|
||||||
|
bool GetName( const char*& aName );
|
||||||
|
bool SetName( const char *aName );
|
||||||
|
bool GetNodeTypeName( S3D::SGTYPES aNodeType, const char*& aName ) const;
|
||||||
|
|
||||||
|
bool FindNode( const char *aNodeName, const SGNODE *aCaller, SGNODE*& aNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transforms and operations
|
||||||
|
class API_TRANSFORM : public API_SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
API_TRANSFORM( SGNODE* aParent );
|
||||||
|
|
||||||
|
bool GetLocalTransforms( SGNODE** aNodeList, int& nListItems );
|
||||||
|
bool GetOtherTransforms( SGNODE** aNodeList, int& nListItems );
|
||||||
|
bool AddOtherTransform( SGNODE* aTransformNode );
|
||||||
|
|
||||||
|
bool GetLocalShapes( SGNODE** aNodeList, int& nListItems );
|
||||||
|
bool GetOtherShapes( SGNODE** aNodeList, int& nListItems );
|
||||||
|
bool AddOtherShape( SGNODE* aTransformNode );
|
||||||
|
|
||||||
|
bool GetTranslation( SGPOINT& aPoint ) const;
|
||||||
|
bool GetRotation( SGVECTOR& aVector, double& aAngle ) const;
|
||||||
|
bool GetScale( SGPOINT& aScale ) const;
|
||||||
|
|
||||||
|
bool SetTranslation( const SGPOINT& aPoint );
|
||||||
|
bool SetRotation( const SGVECTOR& aVector, double aAngle );
|
||||||
|
bool SetScale( const SGPOINT& aScale );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Appearance and operations
|
||||||
|
class API_APPEARANCE : public API_SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
API_APPEARANCE( SGNODE *aParent );
|
||||||
|
|
||||||
|
bool SetEmissive( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetEmissive( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetEmissive( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetDiffuse( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetDiffuse( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetDiffuse( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetSpecular( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetSpecular( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetSpecular( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetAmbient( double aVal );
|
||||||
|
bool SetShininess( double aVal );
|
||||||
|
bool SetTransparency( double aVal );
|
||||||
|
|
||||||
|
bool GetEmissive( SGCOLOR& aRGBColor );
|
||||||
|
bool GetDiffuse( SGCOLOR& aRGBColor );
|
||||||
|
bool GetSpecular( SGCOLOR& aRGBColor );
|
||||||
|
bool GetAmbient( double& aVal );
|
||||||
|
bool GetShininess( double& aVal );
|
||||||
|
bool GetTransparency( double& aVal );
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX - Color Index and operations
|
||||||
|
// XXX - Colors and operations
|
||||||
|
// XXX - Coordinate Index and operations
|
||||||
|
// XXX - Coordinates and operations
|
||||||
|
// XXX - Face Set and operations
|
||||||
|
// XXX - Face Set Index (base class for other indices) and operations
|
||||||
|
// XXX - Normals Index and operations
|
||||||
|
// XXX - Normals and operations
|
||||||
|
// XXX - Shape and operations
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_API_H
|
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <utility>
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_appearance.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
|
||||||
|
SGAPPEARANCE::SGAPPEARANCE( SGNODE* aParent ) : SGNODE( aParent)
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_APPEARANCE;
|
||||||
|
|
||||||
|
// defaults in accord with VRML2.0 spec
|
||||||
|
ambient = 0.2;
|
||||||
|
shininess = 0.2;
|
||||||
|
transparency = 0.0;
|
||||||
|
diffuse.SetColor( 0.8, 0.8, 0.8 );
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGAPPEARANCE (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGAPPEARANCE::~SGAPPEARANCE()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGSHAPE may be parent to a SGAPPEARANCE
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetEmissive( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
return emissive.SetColor( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetEmissive( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == aRGBColor )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aRGBColor\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emissive.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetEmissive( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
return emissive.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetDiffuse( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
return diffuse.SetColor( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == aRGBColor )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aRGBColor\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return diffuse.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetDiffuse( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
return diffuse.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetSpecular( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
return specular.SetColor( aRVal, aGVal, aBVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetSpecular( const SGCOLOR* aRGBColor )
|
||||||
|
{
|
||||||
|
if( NULL == aRGBColor )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aRGBColor\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return specular.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::SetSpecular( const SGCOLOR& aRGBColor )
|
||||||
|
{
|
||||||
|
return specular.SetColor( aRGBColor );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGAPPEARANCE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGAPPEARANCE::unlinkChildNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGAPPEARANCE::unlinkRefNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGAPPEARANCE::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << " appearance DEF " << GetName() << " Appearance {\n";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " appearance USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " appearance Appearance {\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << " material Material {\n";
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
S3D::FormatFloat( tmp, ambient );
|
||||||
|
aFile << " ambientIntensity " << tmp << "\n";
|
||||||
|
|
||||||
|
float red, green, blue;
|
||||||
|
diffuse.GetColor( red, green, blue );
|
||||||
|
S3D::FormatFloat( tmp, red );
|
||||||
|
aFile << " diffuseColor " << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, green );
|
||||||
|
aFile << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, blue);
|
||||||
|
aFile << tmp << "\n";
|
||||||
|
|
||||||
|
emissive.GetColor( red, green, blue );
|
||||||
|
S3D::FormatFloat( tmp, red );
|
||||||
|
aFile << " emissiveColor " << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, green );
|
||||||
|
aFile << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, blue);
|
||||||
|
aFile << tmp << "\n";
|
||||||
|
|
||||||
|
S3D::FormatFloat( tmp, shininess );
|
||||||
|
aFile << " shininess " << tmp << "\n";
|
||||||
|
|
||||||
|
specular.GetColor( red, green, blue );
|
||||||
|
S3D::FormatFloat( tmp, red );
|
||||||
|
aFile << " specularColor " << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, green );
|
||||||
|
aFile << tmp << " ";
|
||||||
|
S3D::FormatFloat( tmp, blue);
|
||||||
|
aFile << tmp << "\n";
|
||||||
|
|
||||||
|
S3D::FormatFloat( tmp, transparency );
|
||||||
|
aFile << " transparency " << tmp << "\n";
|
||||||
|
|
||||||
|
aFile << "} }\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
aFile.write( (char*)&ambient, sizeof(ambient) );
|
||||||
|
aFile.write( (char*)&shininess, sizeof(shininess) );
|
||||||
|
aFile.write( (char*)&transparency, sizeof(transparency) );
|
||||||
|
S3D::WriteColor( aFile, diffuse );
|
||||||
|
S3D::WriteColor( aFile, emissive );
|
||||||
|
S3D::WriteColor( aFile, specular );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGAPPEARANCE::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
aFile.read( (char*)&ambient, sizeof(ambient) );
|
||||||
|
aFile.read( (char*)&shininess, sizeof(shininess) );
|
||||||
|
aFile.read( (char*)&transparency, sizeof(transparency) );
|
||||||
|
S3D::ReadColor( aFile, diffuse );
|
||||||
|
S3D::ReadColor( aFile, emissive );
|
||||||
|
S3D::ReadColor( aFile, specular );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_appearance.h
|
||||||
|
* defines the generic material appearance of a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_APPEARANCE_H
|
||||||
|
#define SG_APPEARANCE_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGAPPEARANCE : public SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float ambient; // default 0.2
|
||||||
|
float shininess; // default 0.2
|
||||||
|
float transparency; // default 0.0
|
||||||
|
SGCOLOR diffuse; // default 0.8 0.8 0.8
|
||||||
|
SGCOLOR emissive; // default 0.0 0.0 0.0
|
||||||
|
SGCOLOR specular; // default 0.0 0.0 0.0
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGAPPEARANCE( SGNODE* aParent );
|
||||||
|
virtual ~SGAPPEARANCE();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
bool SetEmissive( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetEmissive( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetEmissive( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetDiffuse( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetDiffuse( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetDiffuse( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
bool SetSpecular( float aRVal, float aGVal, float aBVal );
|
||||||
|
bool SetSpecular( const SGCOLOR* aRGBColor );
|
||||||
|
bool SetSpecular( const SGCOLOR& aRGBColor );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_APPEARANCE_H
|
|
@ -0,0 +1,325 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <cmath>
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGCOLOR::SGCOLOR()
|
||||||
|
{
|
||||||
|
red = 0.0;
|
||||||
|
green = 0.0;
|
||||||
|
blue = 0.0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGCOLOR::SGCOLOR( float aRVal, float aGVal, float aBVal )
|
||||||
|
{
|
||||||
|
if( !checkRange( aRVal, aGVal, aBVal ) )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid value passed to constructor\n";
|
||||||
|
#endif
|
||||||
|
red = 0.0;
|
||||||
|
green = 0.0;
|
||||||
|
blue = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
red = aRVal;
|
||||||
|
green = aGVal;
|
||||||
|
blue = aBVal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLOR::GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const
|
||||||
|
{
|
||||||
|
aRedVal = red;
|
||||||
|
aGreenVal = green;
|
||||||
|
aBlueVal = blue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLOR::GetColor( SGCOLOR& aColor ) const
|
||||||
|
{
|
||||||
|
aColor.red = red;
|
||||||
|
aColor.green = green;
|
||||||
|
aColor.blue = blue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLOR::GetColor( SGCOLOR* aColor ) const
|
||||||
|
{
|
||||||
|
if( NULL == aColor )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aColor\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aColor->red = red;
|
||||||
|
aColor->green = green;
|
||||||
|
aColor->blue = blue;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLOR::SetColor( float aRedVal, float aGreenVal, float aBlueVal )
|
||||||
|
{
|
||||||
|
if( !checkRange( aRedVal, aGreenVal, aBlueVal ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
red = aRedVal;
|
||||||
|
green = aGreenVal;
|
||||||
|
blue = aBlueVal;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLOR::SetColor( const SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
red = aColor.red;
|
||||||
|
green = aColor.green;
|
||||||
|
blue = aColor.blue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLOR::SetColor( const SGCOLOR* aColor )
|
||||||
|
{
|
||||||
|
if( NULL == aColor )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aColor\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
red = aColor->red;
|
||||||
|
green = aColor->green;
|
||||||
|
blue = aColor->blue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLOR::checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const
|
||||||
|
{
|
||||||
|
bool ok = true;
|
||||||
|
|
||||||
|
if( aRedVal < 0.0 || aRedVal > 1.0 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid RED value: " << aRedVal << "\n";
|
||||||
|
#endif
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aGreenVal < 0.0 || aGreenVal > 1.0 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if( ok )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
}
|
||||||
|
std::cerr << " * [BUG] invalid GREEN value: " << aGreenVal << "\n";
|
||||||
|
#endif
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aBlueVal < 0.0 || aBlueVal > 1.0 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
if( ok )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
}
|
||||||
|
std::cerr << " * [BUG] invalid BLUE value: " << aBlueVal << "\n";
|
||||||
|
#endif
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGPOINT::SGPOINT()
|
||||||
|
{
|
||||||
|
x = 0.0;
|
||||||
|
y = 0.0;
|
||||||
|
z = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGPOINT::SGPOINT( double aXVal, double aYVal, double aZVal )
|
||||||
|
{
|
||||||
|
x = aXVal;
|
||||||
|
y = aYVal;
|
||||||
|
z = aZVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGPOINT::GetPoint( double& aXVal, double& aYVal, double& aZVal )
|
||||||
|
{
|
||||||
|
x = aXVal;
|
||||||
|
y = aYVal;
|
||||||
|
z = aZVal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGPOINT::GetPoint( SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
x = aPoint.x;
|
||||||
|
y = aPoint.y;
|
||||||
|
z = aPoint.z;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGPOINT::GetPoint( SGPOINT* aPoint )
|
||||||
|
{
|
||||||
|
if( NULL == aPoint )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aPoint\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = aPoint->x;
|
||||||
|
y = aPoint->y;
|
||||||
|
z = aPoint->z;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGPOINT::SetPoint( double aXVal, double aYVal, double aZVal )
|
||||||
|
{
|
||||||
|
x = aXVal;
|
||||||
|
y = aYVal;
|
||||||
|
z = aZVal;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGPOINT::SetPoint( const SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
x = aPoint.x;
|
||||||
|
y = aPoint.y;
|
||||||
|
z = aPoint.z;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGVECTOR::SGVECTOR()
|
||||||
|
{
|
||||||
|
vx = 0.0;
|
||||||
|
vy = 0.0;
|
||||||
|
vz = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGVECTOR::SGVECTOR( double aXVal, double aYVal, double aZVal )
|
||||||
|
{
|
||||||
|
vx = aXVal;
|
||||||
|
vy = aYVal;
|
||||||
|
vz = aZVal;
|
||||||
|
normalize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGVECTOR::GetVector( double& aXVal, double& aYVal, double& aZVal ) const
|
||||||
|
{
|
||||||
|
aXVal = vx;
|
||||||
|
aYVal = vy;
|
||||||
|
aZVal = vz;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGVECTOR::SetVector( double aXVal, double aYVal, double aZVal )
|
||||||
|
{
|
||||||
|
vx = aXVal;
|
||||||
|
vy = aYVal;
|
||||||
|
vz = aZVal;
|
||||||
|
normalize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGVECTOR::SetVector( const SGVECTOR& aVector )
|
||||||
|
{
|
||||||
|
aVector.GetVector( vx, vy, vz );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGVECTOR::normalize( void )
|
||||||
|
{
|
||||||
|
double dx = vx * vx;
|
||||||
|
double dy = vy * vy;
|
||||||
|
double dz = vz * vz;
|
||||||
|
double dv2 = dx + dy + dz;
|
||||||
|
|
||||||
|
// note: placing the limit at 1e-14 ensures that
|
||||||
|
// models representing mm to 1e-4 precision can
|
||||||
|
// be accepted before the calculations blow up
|
||||||
|
if( (dx + dy + dz) < 1e-14 )
|
||||||
|
{
|
||||||
|
// use the default; the numbers are too small
|
||||||
|
// to be believable
|
||||||
|
vx = 0.0;
|
||||||
|
vy = 0.0;
|
||||||
|
vz = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dx /= dv2;
|
||||||
|
dy /= dv2;
|
||||||
|
dz /= dv2;
|
||||||
|
|
||||||
|
vx = sqrt( dx );
|
||||||
|
vy = sqrt( dy );
|
||||||
|
vz = sqrt( dz );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGVECTOR& SGVECTOR::operator=( const SGVECTOR& source )
|
||||||
|
{
|
||||||
|
vx = source.vx;
|
||||||
|
vy = source.vy;
|
||||||
|
vz = source.vz;
|
||||||
|
return *this;
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_base.h
|
||||||
|
* defines the low level classes common to scene graph nodes
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SG_BASE_H
|
||||||
|
#define SG_BASE_H
|
||||||
|
|
||||||
|
|
||||||
|
class SGCOLOR
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
float red;
|
||||||
|
float green;
|
||||||
|
float blue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGCOLOR();
|
||||||
|
SGCOLOR( float aRVal, float aGVal, float aBVal );
|
||||||
|
|
||||||
|
void GetColor( float& aRedVal, float& aGreenVal, float& aBlueVal ) const;
|
||||||
|
void GetColor( SGCOLOR& aColor ) const;
|
||||||
|
void GetColor( SGCOLOR* aColor ) const;
|
||||||
|
|
||||||
|
bool SetColor( float aRedVal, float aGreenVal, float aBlueVal );
|
||||||
|
bool SetColor( const SGCOLOR& aColor );
|
||||||
|
bool SetColor( const SGCOLOR* aColor );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool checkRange( float aRedVal, float aGreenVal, float aBlueVal ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SGPOINT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGPOINT();
|
||||||
|
SGPOINT( double aXVal, double aYVal, double aZVal );
|
||||||
|
|
||||||
|
void GetPoint( double& aXVal, double& aYVal, double& aZVal );
|
||||||
|
void GetPoint( SGPOINT& aPoint );
|
||||||
|
void GetPoint( SGPOINT* aPoint );
|
||||||
|
|
||||||
|
void SetPoint( double aXVal, double aYVal, double aZVal );
|
||||||
|
void SetPoint( const SGPOINT& aPoint );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class SGVECTOR
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void normalize( void );
|
||||||
|
|
||||||
|
double vx;
|
||||||
|
double vy;
|
||||||
|
double vz;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGVECTOR();
|
||||||
|
SGVECTOR( double aXVal, double aYVal, double aZVal );
|
||||||
|
|
||||||
|
void GetVector( double& aXVal, double& aYVal, double& aZVal ) const;
|
||||||
|
|
||||||
|
void SetVector( double aXVal, double aYVal, double aZVal );
|
||||||
|
void SetVector( const SGVECTOR& aVector );
|
||||||
|
|
||||||
|
SGVECTOR& operator=( const SGVECTOR& source );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SG_BASE_H
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_colorindex.h>
|
||||||
|
|
||||||
|
SGCOLORINDEX::SGCOLORINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_COLORINDEX;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGCOLORINDEX::~SGCOLORINDEX()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_colorindex.h
|
||||||
|
* defines an RGB color index mapping for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_COLORINDEX_H
|
||||||
|
#define SG_COLORINDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_index.h>
|
||||||
|
|
||||||
|
class SGCOLORINDEX : public SGINDEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SGCOLORINDEX( SGNODE* aParent );
|
||||||
|
virtual ~SGCOLORINDEX();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_COLORINDEX_H
|
|
@ -0,0 +1,313 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_colors.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
|
||||||
|
SGCOLORS::SGCOLORS( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_COLORS;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGCOLORS (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGCOLORS::~SGCOLORS()
|
||||||
|
{
|
||||||
|
colors.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGFACESET may be parent to a SGCOLORS
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGCOLORS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::unlinkChildNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::unlinkRefNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::GetColorList( size_t& aListSize, SGCOLOR*& aColorList )
|
||||||
|
{
|
||||||
|
if( colors.size() )
|
||||||
|
{
|
||||||
|
aListSize = 0;
|
||||||
|
aColorList = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aListSize = colors.size();
|
||||||
|
aColorList = &colors[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::SetColorList( size_t& aListSize, const SGCOLOR* aColorList )
|
||||||
|
{
|
||||||
|
colors.clear();
|
||||||
|
|
||||||
|
if( 0 == aListSize || NULL == aColorList )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < aListSize; ++i )
|
||||||
|
colors.push_back( aColorList[i] );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::AddColor( double aRedValue, double aGreenValue, double aBlueValue )
|
||||||
|
{
|
||||||
|
colors.push_back( SGCOLOR( aRedValue, aGreenValue, aBlueValue ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::AddColor( const SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
colors.push_back( aColor );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOLORS::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( colors.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << "color DEF " << GetName() << " Color { color [\n ";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << "color USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << "color Color { color [\n ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
size_t n = colors.size();
|
||||||
|
bool nline = false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < n; )
|
||||||
|
{
|
||||||
|
S3D::FormatColor( tmp, colors[i] );
|
||||||
|
aFile << tmp ;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i < n )
|
||||||
|
{
|
||||||
|
aFile << ",";
|
||||||
|
|
||||||
|
if( nline )
|
||||||
|
{
|
||||||
|
aFile << "\n ";
|
||||||
|
nline = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nline = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "] }\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
size_t ncolors = colors.size();
|
||||||
|
aFile.write( (char*)&ncolors, sizeof(size_t) );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < ncolors; ++i )
|
||||||
|
S3D::WriteColor( aFile, colors[i] );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOLORS::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( !colors.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ncolors;
|
||||||
|
aFile.read( (char*)&ncolors, sizeof(size_t) );
|
||||||
|
SGCOLOR tmp;
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < ncolors; ++i )
|
||||||
|
{
|
||||||
|
if( !S3D::ReadColor( aFile, tmp ) || aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
colors.push_back( tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_colors.h
|
||||||
|
* defines an RGB color set for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_COLORS_H
|
||||||
|
#define SG_COLORS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGCOLORS : public SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector< SGCOLOR > colors;
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGCOLORS( SGNODE* aParent );
|
||||||
|
virtual ~SGCOLORS();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
bool GetColorList( size_t& aListSize, SGCOLOR*& aColorList );
|
||||||
|
void SetColorList( size_t& aListSize, const SGCOLOR* aColorList );
|
||||||
|
void AddColor( double aRedValue, double aGreenValue, double aBlueValue );
|
||||||
|
void AddColor( const SGCOLOR& aColor );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_COLORS_H
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_coordindex.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGCOORDINDEX::SGCOORDINDEX( SGNODE* aParent ) : SGINDEX( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_COORDINDEX;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGCOORDINDEX::~SGCOORDINDEX()
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_coordindex.h
|
||||||
|
* defines an coordinate index set for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_COORDINDEX_H
|
||||||
|
#define SG_COORDINDEX_H
|
||||||
|
|
||||||
|
#include <3d_cache/sg/sg_index.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SGCOORDINDEX
|
||||||
|
* is a class which maintains a coordinate index list. Users
|
||||||
|
* must ensure that coordinate indices are specified as
|
||||||
|
* triplets (triangular faces) since no checking is performed.
|
||||||
|
* In instances where it is not possible to determine which
|
||||||
|
* side of the triangle is to be rendered (for example IGES
|
||||||
|
* entities) then the user must supply each triplet in both
|
||||||
|
* point orders.
|
||||||
|
*/
|
||||||
|
class SGCOORDINDEX : public SGINDEX
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SGCOORDINDEX( SGNODE* aParent );
|
||||||
|
virtual ~SGCOORDINDEX();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_COORDINDEX_H
|
|
@ -0,0 +1,314 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_coords.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGCOORDS::SGCOORDS( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_COORDS;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGCOORDS (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGCOORDS::~SGCOORDS()
|
||||||
|
{
|
||||||
|
coords.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGFACESET may be parent to a SGCOORDS
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGCOORDS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::unlinkChildNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::unlinkRefNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList )
|
||||||
|
{
|
||||||
|
if( coords.empty() )
|
||||||
|
{
|
||||||
|
aListSize = 0;
|
||||||
|
aCoordsList = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aListSize = coords.size();
|
||||||
|
aCoordsList = &coords[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList )
|
||||||
|
{
|
||||||
|
coords.clear();
|
||||||
|
|
||||||
|
if( 0 == aListSize || NULL == aCoordsList )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < aListSize; ++i )
|
||||||
|
coords.push_back( aCoordsList[i] );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::AddCoord( double aXValue, double aYValue, double aZValue )
|
||||||
|
{
|
||||||
|
coords.push_back( SGPOINT( aXValue, aYValue, aZValue ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::AddCoord( const SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
coords.push_back( aPoint );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGCOORDS::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( coords.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << " coord DEF " << GetName() << " Coordinate { point [\n ";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " coord USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " coord Coordinate { point [\n ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
size_t n = coords.size();
|
||||||
|
bool nline = false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < n; )
|
||||||
|
{
|
||||||
|
S3D::FormatPoint( tmp, coords[i] );
|
||||||
|
aFile << tmp ;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i < n )
|
||||||
|
{
|
||||||
|
aFile << ",";
|
||||||
|
|
||||||
|
if( nline )
|
||||||
|
{
|
||||||
|
aFile << "\n ";
|
||||||
|
nline = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nline = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "] }\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
size_t npts = coords.size();
|
||||||
|
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
S3D::WritePoint( aFile, coords[i] );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGCOORDS::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( !coords.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t npts;
|
||||||
|
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||||
|
SGPOINT tmp;
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
{
|
||||||
|
if( !S3D::ReadPoint( aFile, tmp ) || aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
coords.push_back( tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_coords.h
|
||||||
|
* defines a vertex coordinate set for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_COORDS_H
|
||||||
|
#define SG_COORDS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGCOORDS : public SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector< SGPOINT > coords;
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGCOORDS( SGNODE* aParent );
|
||||||
|
virtual ~SGCOORDS();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
bool GetCoordsList( size_t& aListSize, SGPOINT*& aCoordsList );
|
||||||
|
void SetCoordsList( size_t aListSize, const SGPOINT* aCoordsList );
|
||||||
|
void AddCoord( double aXValue, double aYValue, double aZValue );
|
||||||
|
void AddCoord( const SGPOINT& aPoint );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_COORDS_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_faceset.h
|
||||||
|
* defines an indexed face set for a scenegraph
|
||||||
|
*/
|
||||||
|
|
||||||
|
// BUG:
|
||||||
|
// 1. Since we always use Normal Per Vertex we can deprecate SGNORMALINDEX
|
||||||
|
// 2. There is no such thing as a Referenced Index so deprecate these
|
||||||
|
|
||||||
|
#ifndef SG_FACESET_H
|
||||||
|
#define SG_FACESET_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
// BUG: eliminate NormalIndices; they are not necessary since
|
||||||
|
// we use per-vertex normals
|
||||||
|
|
||||||
|
class SGCOLORS;
|
||||||
|
class SGCOORDS;
|
||||||
|
class SGNORMALS;
|
||||||
|
class SGCOLORINDEX;
|
||||||
|
class SGCOORDINDEX;
|
||||||
|
class SGNORMALINDEX;
|
||||||
|
|
||||||
|
class SGFACESET : public SGNODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool valid;
|
||||||
|
bool validated;
|
||||||
|
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||||
|
bool addNode( SGNODE* aNode, bool isChild );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// owned objects
|
||||||
|
SGCOLORS* m_Colors;
|
||||||
|
SGCOLORINDEX* m_ColorIndices;
|
||||||
|
SGCOORDS* m_Coords;
|
||||||
|
SGCOORDINDEX* m_CoordIndices;
|
||||||
|
SGNORMALS* m_Normals;
|
||||||
|
|
||||||
|
// referenced objects
|
||||||
|
SGCOLORS* m_RColors;
|
||||||
|
SGCOORDS* m_RCoords;
|
||||||
|
SGNORMALS* m_RNormals;
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
// validate the data held by this face set
|
||||||
|
bool validate( void );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGFACESET( SGNODE* aParent );
|
||||||
|
virtual ~SGFACESET();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller );
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
p.88
|
||||||
|
IndexedFaceSet {
|
||||||
|
color NULL
|
||||||
|
coord NULL
|
||||||
|
normal NULL
|
||||||
|
texCoord NULL
|
||||||
|
ccw TRUE
|
||||||
|
colorIndex []
|
||||||
|
colorPerVertex TRUE
|
||||||
|
convex TRUE
|
||||||
|
coordIndex []
|
||||||
|
creaseAngle 0
|
||||||
|
normalIndex []
|
||||||
|
normalPerVertex TRUE
|
||||||
|
solid TRUE
|
||||||
|
texCoordIndex []
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // SG_FACESET_H
|
|
@ -0,0 +1,306 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <sstream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <string>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
// formats a floating point number for text output to a VRML file
|
||||||
|
void S3D::FormatFloat( std::string& result, double value )
|
||||||
|
{
|
||||||
|
if( value < 1e-8 && value > -1e-8 )
|
||||||
|
{
|
||||||
|
result = "0";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note: many VRML implementations use float so we use the max.
|
||||||
|
// precision here of 8 digits.
|
||||||
|
std::ostringstream out;
|
||||||
|
out << std::setprecision( 8 ) << value;
|
||||||
|
|
||||||
|
result = out.str();
|
||||||
|
|
||||||
|
size_t p = result.find( "." );
|
||||||
|
|
||||||
|
// trim trailing 0 if appropriate
|
||||||
|
|
||||||
|
if( std::string::npos == p )
|
||||||
|
return;
|
||||||
|
|
||||||
|
p = result.find_first_of( "eE" );
|
||||||
|
|
||||||
|
if( std::string::npos == p )
|
||||||
|
{
|
||||||
|
while( '0' == *(result.rbegin()) )
|
||||||
|
result.erase( result.size() - 1 );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( '0' != result.at( p -1 ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// trim all 0 to the left of 'p'
|
||||||
|
std::string tmp = result.substr( p );
|
||||||
|
result = result.substr( 0, p );
|
||||||
|
|
||||||
|
while( '0' == *(result.rbegin()) )
|
||||||
|
result.erase( result.size() - 1 );
|
||||||
|
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format orientation data for VRML output
|
||||||
|
void S3D::FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation )
|
||||||
|
{
|
||||||
|
double aX;
|
||||||
|
double aY;
|
||||||
|
double aZ;
|
||||||
|
|
||||||
|
axis.GetVector( aX, aY, aZ );
|
||||||
|
FormatFloat( result, aX );
|
||||||
|
std::string tmp;
|
||||||
|
FormatFloat( tmp, aY );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
FormatFloat( tmp, aZ );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
FormatFloat( tmp, rotation );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// format point data for VRML output
|
||||||
|
void S3D::FormatPoint( std::string& result, const SGPOINT& point )
|
||||||
|
{
|
||||||
|
FormatFloat( result, point.x );
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
FormatFloat( tmp, point.y );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
FormatFloat( tmp, point.z );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// format vector data for VRML output
|
||||||
|
void S3D::FormatVector( std::string& result, const SGVECTOR& aVector )
|
||||||
|
{
|
||||||
|
double X, Y, Z;
|
||||||
|
aVector.GetVector( X, Y, Z );
|
||||||
|
FormatFloat( result, X );
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
FormatFloat( tmp, Y );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
FormatFloat( tmp, Z );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// format Color data for VRML output
|
||||||
|
void S3D::FormatColor( std::string& result, const SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
float R, G, B;
|
||||||
|
aColor.GetColor( R, G, B );
|
||||||
|
FormatFloat( result, R );
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
FormatFloat( tmp, G );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
FormatFloat( tmp, B );
|
||||||
|
result.append( " " );
|
||||||
|
result.append( tmp );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::WritePoint( std::ofstream& aFile, const SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
aFile.write( (char*)&aPoint.x, sizeof(aPoint.x) );
|
||||||
|
aFile.write( (char*)&aPoint.y, sizeof(aPoint.y) );
|
||||||
|
aFile.write( (char*)&aPoint.z, sizeof(aPoint.z) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::WriteVector( std::ofstream& aFile, const SGVECTOR& aVector )
|
||||||
|
{
|
||||||
|
double x, y, z;
|
||||||
|
aVector.GetVector( x, y, z );
|
||||||
|
aFile.write( (char*)&x, sizeof(double) );
|
||||||
|
aFile.write( (char*)&y, sizeof(double) );
|
||||||
|
aFile.write( (char*)&z, sizeof(double) );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::WriteColor( std::ofstream& aFile, const SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
float r, g, b;
|
||||||
|
aColor.GetColor( r, g, b );
|
||||||
|
aFile.write( (char*)&r, sizeof(float) );
|
||||||
|
aFile.write( (char*)&g, sizeof(float) );
|
||||||
|
aFile.write( (char*)&b, sizeof(float) );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D::SGTYPES S3D::ReadTag( std::ifstream& aFile, std::string& aName )
|
||||||
|
{
|
||||||
|
char schar;
|
||||||
|
aFile.get( schar );
|
||||||
|
|
||||||
|
if( '[' != schar )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; missing left bracket at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return S3D::SGTYPE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
aFile.get( schar );
|
||||||
|
|
||||||
|
while( ']' != schar && aFile.good() )
|
||||||
|
{
|
||||||
|
name.push_back( schar );
|
||||||
|
aFile.get( schar );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( schar != ']' )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; could not find right bracket\n";
|
||||||
|
return S3D::SGTYPE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
aName = name;
|
||||||
|
size_t upos = name.find( '_' );
|
||||||
|
|
||||||
|
if( std::string::npos == upos )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; no underscore in name '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return S3D::SGTYPE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = name.substr( 0, upos );
|
||||||
|
S3D::SGTYPES types[S3D::SGTYPE_END] = {
|
||||||
|
SGTYPE_TRANSFORM,
|
||||||
|
SGTYPE_APPEARANCE,
|
||||||
|
SGTYPE_COLORS,
|
||||||
|
SGTYPE_COLORINDEX,
|
||||||
|
SGTYPE_FACESET,
|
||||||
|
SGTYPE_COORDS,
|
||||||
|
SGTYPE_COORDINDEX,
|
||||||
|
SGTYPE_NORMALS,
|
||||||
|
SGTYPE_SHAPE
|
||||||
|
};
|
||||||
|
|
||||||
|
for( int i = 0; i < S3D::SGTYPE_END; ++i )
|
||||||
|
{
|
||||||
|
if( !name.compare( S3D::GetNodeTypeName( types[i] ) ) )
|
||||||
|
return types[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; no node type matching '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return S3D::SGTYPE_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::ReadPoint( std::ifstream& aFile, SGPOINT& aPoint )
|
||||||
|
{
|
||||||
|
aFile.read( (char*)&aPoint.x, sizeof( aPoint.x ) );
|
||||||
|
aFile.read( (char*)&aPoint.y, sizeof( aPoint.y ) );
|
||||||
|
aFile.read( (char*)&aPoint.z, sizeof( aPoint.z ) );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::ReadVector( std::ifstream& aFile, SGVECTOR& aVector )
|
||||||
|
{
|
||||||
|
double x, y, z;
|
||||||
|
aFile.read( (char*)&x, sizeof(double) );
|
||||||
|
aFile.read( (char*)&y, sizeof(double) );
|
||||||
|
aFile.read( (char*)&z, sizeof(double) );
|
||||||
|
aVector.SetVector( x, y, z );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::ReadColor( std::ifstream& aFile, SGCOLOR& aColor )
|
||||||
|
{
|
||||||
|
float r, g, b;
|
||||||
|
aFile.read( (char*)&r, sizeof(float) );
|
||||||
|
aFile.read( (char*)&g, sizeof(float) );
|
||||||
|
aFile.read( (char*)&b, sizeof(float) );
|
||||||
|
aColor.SetColor( r, g, b );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_helpers.h
|
||||||
|
* defines a number of macro functions to aid in repetitious code which
|
||||||
|
* is probably best expressed as a preprocessor macro rather than as
|
||||||
|
* a template. This header also declares a number of functions which are
|
||||||
|
* only of use within the sg_* classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_HELPERS_H
|
||||||
|
#define SG_HELPERS_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
#include "sg_types.h"
|
||||||
|
|
||||||
|
// Function to drop references within an SGNODE
|
||||||
|
// The node being destroyed must remove itself from the object reference's
|
||||||
|
// backpointer list in order to avoid a segfault.
|
||||||
|
#define DROP_REFS( aType, aList ) do { \
|
||||||
|
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||||
|
std::vector< aType* >::iterator eL = aList.end(); \
|
||||||
|
while( sL != eL ) { \
|
||||||
|
((SGNODE*)*sL)->delNodeRef( this ); \
|
||||||
|
++sL; \
|
||||||
|
} \
|
||||||
|
aList.clear(); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
// Function to delete owned objects within an SGNODE
|
||||||
|
// The owned object's parent is set to NULL before
|
||||||
|
// deletion to avoid a redundant 'unlinkChildNode' call.
|
||||||
|
#define DEL_OBJS( aType, aList ) do { \
|
||||||
|
std::vector< aType* >::iterator sL = aList.begin(); \
|
||||||
|
std::vector< aType* >::iterator eL = aList.end(); \
|
||||||
|
while( sL != eL ) { \
|
||||||
|
((SGNODE*)*sL)->SetParent( NULL, false ); \
|
||||||
|
delete *sL; \
|
||||||
|
++sL; \
|
||||||
|
} \
|
||||||
|
aList.clear(); \
|
||||||
|
} while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
// Function to unlink a child or reference node when that child or
|
||||||
|
// reference node is being destroyed.
|
||||||
|
#define UNLINK_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||||
|
if( aNodeID == aNode->GetNodeType() ) { \
|
||||||
|
std::vector< aType* >* oSL; \
|
||||||
|
std::vector< aType* >::iterator sL; \
|
||||||
|
std::vector< aType* >::iterator eL; \
|
||||||
|
if( isChild ) { \
|
||||||
|
oSL = &aOwnedList; \
|
||||||
|
sL = aOwnedList.begin(); \
|
||||||
|
eL = aOwnedList.end(); \
|
||||||
|
} else { \
|
||||||
|
oSL = &aRefList; \
|
||||||
|
sL = aRefList.begin(); \
|
||||||
|
eL = aRefList.end(); \
|
||||||
|
} \
|
||||||
|
while( sL != eL ) { \
|
||||||
|
if( (SGNODE*)*sL == aNode ) { \
|
||||||
|
oSL->erase( sL ); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
++sL; \
|
||||||
|
} \
|
||||||
|
return; \
|
||||||
|
} } while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
// Function to check a node type, check for an existing reference,
|
||||||
|
// and add the node type to the reference list if applicable
|
||||||
|
#define ADD_NODE( aNodeID, aType, aNode, aOwnedList, aRefList, isChild ) do { \
|
||||||
|
if( aNodeID == aNode->GetNodeType() ) { \
|
||||||
|
std::vector< aType* >::iterator sL; \
|
||||||
|
SGNODE* psg = NULL; \
|
||||||
|
sL = std::find( aOwnedList.begin(), aOwnedList.end(), aNode ); \
|
||||||
|
if( sL != aOwnedList.end() ) return true; \
|
||||||
|
sL = std::find( aRefList.begin(), aRefList.end(), aNode ); \
|
||||||
|
if( sL != aRefList.end() ) return true; \
|
||||||
|
if( isChild ) { \
|
||||||
|
SGNODE* ppn = (SGNODE*)aNode->GetParent(); \
|
||||||
|
if( NULL != ppn ) { \
|
||||||
|
if( this != ppn ) { \
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||||
|
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||||
|
std::cerr << "' has multiple parents '" << ppn->GetName() << "', '"; \
|
||||||
|
std::cerr << m_Name << "'\n"; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
aOwnedList.push_back( (aType*)aNode ); \
|
||||||
|
aNode->SetParent( this, false ); \
|
||||||
|
} else { \
|
||||||
|
if( NULL == aNode->GetParent() ) { \
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; \
|
||||||
|
std::cerr << " * [BUG] object '" << aNode->GetName(); \
|
||||||
|
std::cerr << "' has no parent\n"; \
|
||||||
|
std::cerr << " * [INFO] possible copy assignment or copy constructor bug\n"; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
aRefList.push_back( (aType*)aNode ); \
|
||||||
|
aNode->addNodeRef( this ); \
|
||||||
|
} \
|
||||||
|
return true; \
|
||||||
|
} } while( 0 )
|
||||||
|
|
||||||
|
|
||||||
|
// Function to find a node object given a (non-unique) node name
|
||||||
|
#define FIND_NODE( aType, aName, aNodeList, aCallingNode ) do { \
|
||||||
|
std::vector< aType* >::iterator sLA = aNodeList.begin(); \
|
||||||
|
std::vector< aType* >::iterator eLA = aNodeList.end(); \
|
||||||
|
SGNODE* psg = NULL; \
|
||||||
|
while( sLA != eLA ) { \
|
||||||
|
if( (SGNODE*)*sLA != aCallingNode ) { \
|
||||||
|
psg = (SGNODE*) (*sLA)->FindNode( aName, this ); \
|
||||||
|
if( NULL != psg) \
|
||||||
|
return psg; \
|
||||||
|
} \
|
||||||
|
++sLA; \
|
||||||
|
} } while ( 0 )
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// VRML related functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// formats a floating point number for text output to a VRML file
|
||||||
|
void FormatFloat( std::string& result, double value );
|
||||||
|
|
||||||
|
// format orientation data for VRML output
|
||||||
|
void FormatOrientation( std::string& result, const SGVECTOR& axis, double rotation );
|
||||||
|
|
||||||
|
// format point data for VRML output
|
||||||
|
void FormatPoint( std::string& result, const SGPOINT& point );
|
||||||
|
|
||||||
|
// format vector data for VRML output
|
||||||
|
void FormatVector( std::string& result, const SGVECTOR& aVector );
|
||||||
|
|
||||||
|
// format Color data for VRML output
|
||||||
|
void FormatColor( std::string& result, const SGCOLOR& aColor );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cache related WRITE functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// write out an XYZ vertex
|
||||||
|
bool WritePoint( std::ofstream& aFile, const SGPOINT& aPoint );
|
||||||
|
|
||||||
|
// write out a unit vector
|
||||||
|
bool WriteVector( std::ofstream& aFile, const SGVECTOR& aVector );
|
||||||
|
|
||||||
|
// write out an RGB color
|
||||||
|
bool WriteColor( std::ofstream& aFile, const SGCOLOR& aColor );
|
||||||
|
|
||||||
|
//
|
||||||
|
// Cache related READ functions
|
||||||
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReadTag
|
||||||
|
* reads the text tag of a binary cache file which is the
|
||||||
|
* NodeTag and unique ID number combined
|
||||||
|
*
|
||||||
|
* @param aFile is a binary file open for reading
|
||||||
|
* @param aName will hold the tag name on successful return
|
||||||
|
* @return will be the NodeType which the tag represents or
|
||||||
|
* S3D::SGTYPES::SGTYPE_END on failure
|
||||||
|
*/
|
||||||
|
S3D::SGTYPES ReadTag( std::ifstream& aFile, std::string& aName );
|
||||||
|
|
||||||
|
// read an XYZ vertex
|
||||||
|
bool ReadPoint( std::ifstream& aFile, SGPOINT& aPoint );
|
||||||
|
|
||||||
|
// read a unit vector
|
||||||
|
bool ReadVector( std::ifstream& aFile, SGVECTOR& aVector );
|
||||||
|
|
||||||
|
// read an RGB color
|
||||||
|
bool ReadColor( std::ifstream& aFile, SGCOLOR& aColor );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_HELPERS_H
|
|
@ -0,0 +1,342 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <fstream>
|
||||||
|
#include <3d_cache/sg/sg_index.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGINDEX::SGINDEX( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGINDEX (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGINDEX::~SGINDEX()
|
||||||
|
{
|
||||||
|
index.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGFACESET may be parent to a SGINDEX and derived types
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGINDEX::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGINDEX::unlinkChildNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGINDEX::unlinkRefNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::GetIndices( size_t& nIndices, int*& aIndexList )
|
||||||
|
{
|
||||||
|
if( index.empty() )
|
||||||
|
{
|
||||||
|
nIndices = 0;
|
||||||
|
aIndexList = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nIndices = index.size();
|
||||||
|
aIndexList = & index[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGINDEX::SetIndices( size_t nIndices, int* aIndexList )
|
||||||
|
{
|
||||||
|
index.clear();
|
||||||
|
|
||||||
|
if( 0 == nIndices || NULL == aIndexList )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < nIndices; ++i )
|
||||||
|
index.push_back( aIndexList[i] );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGINDEX::AddIndex( int aIndex )
|
||||||
|
{
|
||||||
|
index.push_back( aIndex );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGINDEX::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( index.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_COORDINDEX == m_SGtype )
|
||||||
|
return writeCoordIndex( aFile );
|
||||||
|
|
||||||
|
return writeColorIndex( aFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::writeCoordIndex( std::ofstream& aFile )
|
||||||
|
{
|
||||||
|
size_t n = index.size();
|
||||||
|
|
||||||
|
if( n % 3 )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] coord index is not divisible by three (violates triangle constraint)\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << " coordIndex [\n ";
|
||||||
|
|
||||||
|
// indices to control formatting
|
||||||
|
int nv0 = 0;
|
||||||
|
int nv1 = 0;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < n; )
|
||||||
|
{
|
||||||
|
aFile << index[i];
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( ++nv0 == 3 )
|
||||||
|
{
|
||||||
|
aFile << ",-1";
|
||||||
|
++nv1;
|
||||||
|
nv0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i < n )
|
||||||
|
{
|
||||||
|
aFile << ",";
|
||||||
|
|
||||||
|
if( nv1 == 8 )
|
||||||
|
{
|
||||||
|
nv1 = 0;
|
||||||
|
aFile << "\n ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "]\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::writeColorIndex( std::ofstream& aFile )
|
||||||
|
{
|
||||||
|
aFile << " colorIndex [\n ";
|
||||||
|
return writeIndexList( aFile );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::writeIndexList( std::ofstream& aFile )
|
||||||
|
{
|
||||||
|
// index to control formatting
|
||||||
|
int nv = 0;
|
||||||
|
size_t n = index.size();
|
||||||
|
|
||||||
|
for( size_t i = 0; i < n; )
|
||||||
|
{
|
||||||
|
aFile << index[i];
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i < n )
|
||||||
|
{
|
||||||
|
aFile << ",";
|
||||||
|
|
||||||
|
if( ++nv == 20 )
|
||||||
|
{
|
||||||
|
aFile << "\n ";
|
||||||
|
nv = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "]\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
size_t npts = index.size();
|
||||||
|
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
aFile.write( (char*)&index[i], sizeof(int) );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGINDEX::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( !index.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t npts;
|
||||||
|
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||||
|
int tmp;
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
{
|
||||||
|
aFile.read( (char*)&tmp, sizeof(int) );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
index.push_back( tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_index.h
|
||||||
|
* defines a generic Index interface for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_INDEX_H
|
||||||
|
#define SG_INDEX_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGINDEX : public SGNODE
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
bool writeCoordIndex( std::ofstream& aFile );
|
||||||
|
bool writeColorIndex( std::ofstream& aFile );
|
||||||
|
bool writeIndexList( std::ofstream& aFile );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// for internal SG consumption only
|
||||||
|
std::vector< int > index;
|
||||||
|
void unlinkChildNode( const SGNODE* aCaller );
|
||||||
|
void unlinkRefNode( const SGNODE* aCaller );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGINDEX( SGNODE* aParent );
|
||||||
|
virtual ~SGINDEX();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetIndices
|
||||||
|
* retrieves the number of indices and a pointer to
|
||||||
|
* the list. Note: the returned pointer may be invalidated
|
||||||
|
* by future operations on the SGNODE; the caller must make
|
||||||
|
* immediate use of the data and must not rely on the pointer's
|
||||||
|
* validity in the future.
|
||||||
|
*
|
||||||
|
* @param nIndices [out] will hold the number of indices in the list
|
||||||
|
* @param aIndexList [out] will store a pointer to the data
|
||||||
|
* @return true if there was available data (nIndices > 0) otherwise false
|
||||||
|
*/
|
||||||
|
bool GetIndices( size_t& nIndices, int*& aIndexList );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetIndices
|
||||||
|
* sets the number of indices and creates a copy of the given index data.
|
||||||
|
*
|
||||||
|
* @param nIndices [in] the number of indices to be stored
|
||||||
|
* @param aIndexList [in] the index data
|
||||||
|
*/
|
||||||
|
void SetIndices( size_t nIndices, int* aIndexList );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function AddIndex
|
||||||
|
* adds a single index to the list
|
||||||
|
*
|
||||||
|
* @param nIndices [in] the number of indices to be stored
|
||||||
|
* @param aIndexList [in] the index data
|
||||||
|
*/
|
||||||
|
void AddIndex( int aIndex );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_INDEX_H
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <sstream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
|
||||||
|
static const std::string node_names[S3D::SGTYPE_END + 1] = {
|
||||||
|
"TXFM",
|
||||||
|
"APP",
|
||||||
|
"COL",
|
||||||
|
"COLIDX",
|
||||||
|
"FACE",
|
||||||
|
"COORD",
|
||||||
|
"COORDIDX",
|
||||||
|
"NORM",
|
||||||
|
"SHAPE",
|
||||||
|
"INVALID"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int node_counts[S3D::SGTYPE_END] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
|
||||||
|
char const* S3D::GetNodeTypeName( S3D::SGTYPES aType )
|
||||||
|
{
|
||||||
|
return node_names[aType].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void getNodeName( S3D::SGTYPES nodeType, std::string& aName )
|
||||||
|
{
|
||||||
|
if( nodeType < 0 || nodeType >= S3D::SGTYPE_END )
|
||||||
|
{
|
||||||
|
aName = node_names[S3D::SGTYPE_END];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int seqNum = node_counts[nodeType];
|
||||||
|
++node_counts[nodeType];
|
||||||
|
|
||||||
|
std::ostringstream ostr;
|
||||||
|
ostr << node_names[nodeType] << "_" << seqNum;
|
||||||
|
aName = ostr.str();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE::SGNODE( SGNODE* aParent )
|
||||||
|
{
|
||||||
|
m_Parent = aParent;
|
||||||
|
m_Association = NULL;
|
||||||
|
m_written = false;
|
||||||
|
m_SGtype = S3D::SGTYPE_END;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE::~SGNODE()
|
||||||
|
{
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
if( m_Association )
|
||||||
|
*m_Association = NULL;
|
||||||
|
|
||||||
|
std::list< SGNODE* >::iterator sBP = m_BackPointers.begin();
|
||||||
|
std::list< SGNODE* >::iterator eBP = m_BackPointers.end();
|
||||||
|
|
||||||
|
while( sBP != eBP )
|
||||||
|
{
|
||||||
|
(*sBP)->unlinkRefNode( this );
|
||||||
|
++sBP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
S3D::SGTYPES SGNODE::GetNodeType( void ) const
|
||||||
|
{
|
||||||
|
return m_SGtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGNODE::GetParent( void ) const
|
||||||
|
{
|
||||||
|
return m_Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* SGNODE::GetName( void )
|
||||||
|
{
|
||||||
|
if( m_Name.empty() )
|
||||||
|
getNodeName( m_SGtype, m_Name );
|
||||||
|
|
||||||
|
return m_Name.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNODE::SetName( const char *aName )
|
||||||
|
{
|
||||||
|
if( NULL == aName || 0 == aName[0] )
|
||||||
|
getNodeName( m_SGtype, m_Name );
|
||||||
|
else
|
||||||
|
m_Name = aName;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char * SGNODE::GetNodeTypeName( S3D::SGTYPES aNodeType ) const
|
||||||
|
{
|
||||||
|
return node_names[aNodeType].c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNODE::addNodeRef( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< SGNODE* >::iterator np =
|
||||||
|
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||||
|
|
||||||
|
if( np != m_BackPointers.end() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_BackPointers.push_back( aNode );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNODE::delNodeRef( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::list< SGNODE* >::iterator np =
|
||||||
|
std::find( m_BackPointers.begin(), m_BackPointers.end(), aNode );
|
||||||
|
|
||||||
|
if( np != m_BackPointers.end() )
|
||||||
|
{
|
||||||
|
m_BackPointers.erase( np );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] delNodeRef() did not find its target\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNODE::AssociateWrapper( SGNODE** aWrapperRef )
|
||||||
|
{
|
||||||
|
if( NULL == aWrapperRef )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL handle\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *aWrapperRef != this )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] handle value does not match this object's pointer\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there is an existing association then break it and emit a warning
|
||||||
|
// just in case the behavior is undesired
|
||||||
|
if( m_Association )
|
||||||
|
{
|
||||||
|
*m_Association = NULL;
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [WARNING] association being broken with previous wrapper\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Association = aWrapperRef;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SGNODE::DisassociateWrapper( SGNODE** aWrapperRef )
|
||||||
|
{
|
||||||
|
if( !m_Association )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !aWrapperRef )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] invalid handle value aWrapperRef\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *aWrapperRef != *m_Association || aWrapperRef != m_Association )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] *aWrapperRef (" << *aWrapperRef;
|
||||||
|
std::cerr << ") does not match *m_Association (" << *m_Association << ") in type ";
|
||||||
|
std::cerr << node_names[ m_SGtype] << "\n";
|
||||||
|
std::cerr << " * [INFO] OR aWrapperRef(" << aWrapperRef << ") != m_Association(";
|
||||||
|
std::cerr << m_Association << ")\n";
|
||||||
|
std::cerr << " * [INFO] node name: " << GetName() << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Association = NULL;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNODE::ResetNodeIndex( void )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < (int)S3D::SGTYPE_END; ++i )
|
||||||
|
node_counts[i] = 1;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool S3D::GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex )
|
||||||
|
{
|
||||||
|
aIndex = 0;
|
||||||
|
|
||||||
|
if( NULL == aNode || S3D::SGTYPE_APPEARANCE != aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << " * [BUG] aNode is NULL\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << " * [BUG] invalid node type (" << aNode->GetNodeType();
|
||||||
|
std::cerr << "), expected " << S3D::SGTYPE_APPEARANCE << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGAPPEARANCE* node = (SGAPPEARANCE*)aNode;
|
||||||
|
|
||||||
|
std::map< SGAPPEARANCE const*, int >::iterator it = aList.matmap.find( node );
|
||||||
|
|
||||||
|
if( it != aList.matmap.end() )
|
||||||
|
{
|
||||||
|
aIndex = it->second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = (int)aList.matorder.size();
|
||||||
|
aList.matorder.push_back( node );
|
||||||
|
aList.matmap.insert( std::pair< SGAPPEARANCE const*, int >( node, idx ) );
|
||||||
|
aIndex = idx;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::INIT_SMATERIAL( SMATERIAL& aMaterial )
|
||||||
|
{
|
||||||
|
memset( &aMaterial, 0, sizeof( aMaterial ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::INIT_SMESH( SMESH& aMesh )
|
||||||
|
{
|
||||||
|
memset( &aMesh, 0, sizeof( aMesh ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::INIT_S3DMODEL( S3DMODEL& aModel )
|
||||||
|
{
|
||||||
|
memset( &aModel, 0, sizeof( aModel ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::FREE_SMESH( SMESH& aMesh)
|
||||||
|
{
|
||||||
|
if( NULL != aMesh.m_Positions )
|
||||||
|
{
|
||||||
|
delete [] aMesh.m_Positions;
|
||||||
|
aMesh.m_Positions = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aMesh.m_Normals )
|
||||||
|
{
|
||||||
|
delete [] aMesh.m_Normals;
|
||||||
|
aMesh.m_Normals = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aMesh.m_Texcoords )
|
||||||
|
{
|
||||||
|
delete [] aMesh.m_Texcoords;
|
||||||
|
aMesh.m_Texcoords = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aMesh.m_Color )
|
||||||
|
{
|
||||||
|
delete [] aMesh.m_Color;
|
||||||
|
aMesh.m_Color = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != aMesh.m_FaceIdx )
|
||||||
|
{
|
||||||
|
delete [] aMesh.m_FaceIdx;
|
||||||
|
aMesh.m_FaceIdx = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
aMesh.m_VertexSize = 0;
|
||||||
|
aMesh.m_FaceIdxSize = 0;
|
||||||
|
aMesh.m_MaterialIdx = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void S3D::FREE_S3DMODEL( S3DMODEL& aModel )
|
||||||
|
{
|
||||||
|
if( NULL != aModel.m_Materials )
|
||||||
|
{
|
||||||
|
delete [] aModel.m_Materials;
|
||||||
|
aModel.m_Materials = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
aModel.m_MaterialsSize = 0;
|
||||||
|
|
||||||
|
if( NULL != aModel.m_Meshes )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < aModel.m_MeshesSize; ++i )
|
||||||
|
FREE_SMESH( aModel.m_Meshes[i] );
|
||||||
|
|
||||||
|
delete [] aModel.m_Meshes;
|
||||||
|
aModel.m_Meshes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
aModel.m_MeshesSize = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_node.h
|
||||||
|
* defines the base class of the intermediate scene graph NODE
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SG_NODE_H
|
||||||
|
#define SG_NODE_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <3d_rendering/c3dmodel.h>
|
||||||
|
#include <3d_cache/sg/sg_base.h>
|
||||||
|
#include <3d_cache/sg/sg_types.h>
|
||||||
|
|
||||||
|
class SGNODE;
|
||||||
|
class SGAPPEARANCE;
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function GetNodeTypeName
|
||||||
|
* returns the name of the given type of node
|
||||||
|
*/
|
||||||
|
char const* GetNodeTypeName( S3D::SGTYPES aType );
|
||||||
|
|
||||||
|
struct MATLIST
|
||||||
|
{
|
||||||
|
std::vector< SGAPPEARANCE const* > matorder; // materials in order of addition
|
||||||
|
std::map< SGAPPEARANCE const*, int > matmap; // mapping from material to index
|
||||||
|
};
|
||||||
|
|
||||||
|
bool GetMatIndex( MATLIST& aList, SGNODE* aNode, int& aIndex );
|
||||||
|
|
||||||
|
void INIT_SMATERIAL( SMATERIAL& aMaterial );
|
||||||
|
void INIT_SMESH( SMESH& aMesh );
|
||||||
|
void INIT_S3DMODEL( S3DMODEL& aModel );
|
||||||
|
|
||||||
|
void FREE_SMESH( SMESH& aMesh);
|
||||||
|
void FREE_S3DMODEL( S3DMODEL& aModel );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SGNODE
|
||||||
|
* represents the base class of all Scene Graph nodes
|
||||||
|
*/
|
||||||
|
class SGNODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::list< SGNODE* > m_BackPointers; // nodes which hold a reference to this
|
||||||
|
SGNODE** m_Association; // handle to the instance held by a wrapper
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SGNODE* m_Parent; // pointer to parent node; may be NULL for top level transform
|
||||||
|
S3D::SGTYPES m_SGtype; // type of SG node
|
||||||
|
std::string m_Name; // name to use for referencing the entity by name
|
||||||
|
bool m_written; // set true when the object has been written after a ReNameNodes()
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* 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 SGNODE* aNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 SGNODE* aNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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( SGNODE* 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( SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGNODE( SGNODE* aParent );
|
||||||
|
virtual ~SGNODE();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetNodeType
|
||||||
|
* returns the type of this node instance
|
||||||
|
*/
|
||||||
|
S3D::SGTYPES 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)
|
||||||
|
*/
|
||||||
|
SGNODE* GetParent( void ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetParent
|
||||||
|
* sets the parent SGNODE of this object.
|
||||||
|
*
|
||||||
|
* @param aParent [in] is the desired parent node
|
||||||
|
* @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( SGNODE* aParent, bool notify = true ) = 0;
|
||||||
|
|
||||||
|
const char* GetName( void );
|
||||||
|
void SetName(const char *aName);
|
||||||
|
|
||||||
|
const char * GetNodeTypeName( S3D::SGTYPES aNodeType ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function FindNode searches the tree of linked nodes and returns a
|
||||||
|
* reference to the first node found 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
|
||||||
|
* @param aCaller is a pointer to the node invoking this function
|
||||||
|
* @return is a valid node pointer on success, otherwise NULL
|
||||||
|
*/
|
||||||
|
virtual SGNODE* FindNode( const char *aNodeName, const SGNODE *aCaller ) = 0;
|
||||||
|
|
||||||
|
virtual bool AddRefNode( SGNODE* aNode ) = 0;
|
||||||
|
|
||||||
|
virtual bool AddChildNode( SGNODE* aNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function AssociateWrapper
|
||||||
|
* associates this object with a handle to itself; this handle
|
||||||
|
* is typically held by an IFSG* wrapper and the pointer which
|
||||||
|
* it refers to is set to NULL upon destruction of this object.
|
||||||
|
* This mechanism provides a scheme by which a wrapper can be
|
||||||
|
* notified of the destruction of the object which it wraps.
|
||||||
|
*/
|
||||||
|
void AssociateWrapper( SGNODE** aWrapperRef );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function DisassociateWrapper
|
||||||
|
* removes the association between an IFSG* wrapper
|
||||||
|
* object and this object.
|
||||||
|
*/
|
||||||
|
void DisassociateWrapper( SGNODE** aWrapperRef );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ResetNodeIndex
|
||||||
|
* resets the global SG* node indices in preparation for
|
||||||
|
* Write() operations
|
||||||
|
*/
|
||||||
|
void ResetNodeIndex( void );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReNameNodes
|
||||||
|
* renames a node and all its child nodes in preparation for
|
||||||
|
* Write() operations
|
||||||
|
*/
|
||||||
|
virtual void ReNameNodes( void ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WriteVRML
|
||||||
|
* writes this node's data to a VRML file; this includes
|
||||||
|
* all data of child and referenced nodes.
|
||||||
|
*/
|
||||||
|
virtual bool WriteVRML( std::ofstream& aFile, bool aReuseFlag ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function WriteCache
|
||||||
|
* write's this node's data to a binary cache file; the data
|
||||||
|
* includes all data of children and references to children.
|
||||||
|
* If this function is invoked by the user, parentNode must be
|
||||||
|
* set to NULL in order to ensure coherent data.
|
||||||
|
*/
|
||||||
|
virtual bool WriteCache( std::ofstream& aFile, SGNODE* parentNode ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function ReadCache
|
||||||
|
* Reads binary format data from a cache file. To read a cache file,
|
||||||
|
* open the file for reading and invoke this function from a new
|
||||||
|
* SCENEGRAPH node.
|
||||||
|
*/
|
||||||
|
virtual bool ReadCache( std::ifstream& aFile, SGNODE* parentNode ) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_NODE_H
|
|
@ -0,0 +1,314 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <3d_cache/sg/sg_normals.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGNORMALS::SGNORMALS( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_NORMALS;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGNORMALS (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_FACESET == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNORMALS::~SGNORMALS()
|
||||||
|
{
|
||||||
|
norms.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGFACESET may be parent to a SGNORMALS
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_FACESET != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGNORMALS::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::unlinkChildNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::unlinkRefNode( const SGNODE* aCaller )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unexpected code branch; node should have no children or refs\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] this node does not accept children or refs\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList )
|
||||||
|
{
|
||||||
|
if( norms.empty() )
|
||||||
|
{
|
||||||
|
aListSize = 0;
|
||||||
|
aNormalList = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aListSize = norms.size();
|
||||||
|
aNormalList = &norms[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::SetNormalList( size_t aListSize, const SGVECTOR* aNormalList )
|
||||||
|
{
|
||||||
|
norms.clear();
|
||||||
|
|
||||||
|
if( 0 == aListSize || NULL == aNormalList )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( int i = 0; i < aListSize; ++i )
|
||||||
|
norms.push_back( aNormalList[i] );
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::AddNormal( double aXValue, double aYValue, double aZValue )
|
||||||
|
{
|
||||||
|
norms.push_back( SGVECTOR( aXValue, aYValue, aZValue ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::AddNormal( const SGVECTOR& aNormal )
|
||||||
|
{
|
||||||
|
norms.push_back( aNormal );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGNORMALS::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( norms.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << " normal DEF " << GetName() << " Normal { vector [\n ";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " normal USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " normal Normal { vector [\n ";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
size_t n = norms.size();
|
||||||
|
bool nline = false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < n; )
|
||||||
|
{
|
||||||
|
S3D::FormatVector( tmp, norms[i] );
|
||||||
|
aFile << tmp ;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if( i < n )
|
||||||
|
{
|
||||||
|
aFile << ",";
|
||||||
|
|
||||||
|
if( nline )
|
||||||
|
{
|
||||||
|
aFile << "\n ";
|
||||||
|
nline = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nline = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "] }\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
size_t npts = norms.size();
|
||||||
|
aFile.write( (char*)&npts, sizeof(size_t) );
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
S3D::WriteVector( aFile, norms[i] );
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGNORMALS::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( !norms.empty() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t npts;
|
||||||
|
aFile.read( (char*)&npts, sizeof(size_t) );
|
||||||
|
SGVECTOR tmp;
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < npts; ++i )
|
||||||
|
{
|
||||||
|
if( !S3D::ReadVector( aFile, tmp ) || aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
norms.push_back( tmp );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_normals.h
|
||||||
|
* defines a set of vertex normals for a scene graph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SG_NORMALS_H
|
||||||
|
#define SG_NORMALS_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGNORMALS : public SGNODE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::vector< SGVECTOR > norms;
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGNORMALS( SGNODE* aParent );
|
||||||
|
virtual ~SGNORMALS();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
bool GetNormalList( size_t& aListSize, SGVECTOR*& aNormalList );
|
||||||
|
void SetNormalList( size_t aListSize, const SGVECTOR* aNormalList );
|
||||||
|
void AddNormal( double aXValue, double aYValue, double aZValue );
|
||||||
|
void AddNormal( const SGVECTOR& aNormal );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_NORMALS_H
|
|
@ -0,0 +1,748 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 <fstream>
|
||||||
|
#include <3d_cache/sg/sg_shape.h>
|
||||||
|
#include <3d_cache/sg/sg_faceset.h>
|
||||||
|
#include <3d_cache/sg/sg_appearance.h>
|
||||||
|
#include <3d_cache/sg/sg_helpers.h>
|
||||||
|
#include <3d_cache/sg/sg_coordindex.h>
|
||||||
|
#include <3d_cache/sg/sg_colorindex.h>
|
||||||
|
#include <3d_cache/sg/sg_coords.h>
|
||||||
|
#include <3d_cache/sg/sg_colors.h>
|
||||||
|
#include <3d_cache/sg/sg_normals.h>
|
||||||
|
|
||||||
|
|
||||||
|
SGSHAPE::SGSHAPE( SGNODE* aParent ) : SGNODE( aParent )
|
||||||
|
{
|
||||||
|
m_SGtype = S3D::SGTYPE_SHAPE;
|
||||||
|
m_Appearance = NULL;
|
||||||
|
m_RAppearance = NULL;
|
||||||
|
m_FaceSet = NULL;
|
||||||
|
m_RFaceSet = NULL;
|
||||||
|
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] inappropriate parent to SGSHAPE (type ";
|
||||||
|
std::cerr << aParent->GetNodeType() << ")\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if( NULL != aParent && S3D::SGTYPE_TRANSFORM == aParent->GetNodeType() )
|
||||||
|
{
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGSHAPE::~SGSHAPE()
|
||||||
|
{
|
||||||
|
// drop references
|
||||||
|
if( m_RAppearance )
|
||||||
|
{
|
||||||
|
m_RAppearance->delNodeRef( this );
|
||||||
|
m_RAppearance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_RFaceSet )
|
||||||
|
{
|
||||||
|
m_RFaceSet->delNodeRef( this );
|
||||||
|
m_RFaceSet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete objects
|
||||||
|
if( m_Appearance )
|
||||||
|
{
|
||||||
|
m_Appearance->SetParent( NULL, false );
|
||||||
|
delete m_Appearance;
|
||||||
|
m_Appearance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_FaceSet )
|
||||||
|
{
|
||||||
|
m_FaceSet->SetParent( NULL, false );
|
||||||
|
delete m_FaceSet;
|
||||||
|
m_FaceSet = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::SetParent( SGNODE* aParent, bool notify )
|
||||||
|
{
|
||||||
|
if( NULL != m_Parent )
|
||||||
|
{
|
||||||
|
if( aParent == m_Parent )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// handle the change in parents
|
||||||
|
if( notify )
|
||||||
|
m_Parent->unlinkChildNode( this );
|
||||||
|
|
||||||
|
m_Parent = NULL;
|
||||||
|
|
||||||
|
if( NULL == aParent )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only a SGTRANSFORM may be parent to a SGSHAPE
|
||||||
|
if( NULL != aParent && S3D::SGTYPE_TRANSFORM != aParent->GetNodeType() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Parent = aParent;
|
||||||
|
|
||||||
|
if( m_Parent )
|
||||||
|
m_Parent->AddChildNode( this );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGNODE* SGSHAPE::FindNode(const char *aNodeName, const SGNODE *aCaller)
|
||||||
|
{
|
||||||
|
if( NULL == aNodeName || 0 == aNodeName[0] )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( !m_Name.compare( aNodeName ) )
|
||||||
|
return this;
|
||||||
|
|
||||||
|
SGNODE* tmp = NULL;
|
||||||
|
|
||||||
|
if( NULL != m_Appearance )
|
||||||
|
{
|
||||||
|
tmp = m_Appearance->FindNode( aNodeName, this );
|
||||||
|
|
||||||
|
if( tmp )
|
||||||
|
{
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != m_FaceSet )
|
||||||
|
{
|
||||||
|
tmp = m_FaceSet->FindNode( aNodeName, this );
|
||||||
|
|
||||||
|
if( tmp )
|
||||||
|
{
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// query the parent if appropriate
|
||||||
|
if( aCaller == m_Parent || NULL == m_Parent )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return m_Parent->FindNode( aNodeName, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGSHAPE::unlinkNode( const SGNODE* aNode, bool isChild )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( isChild )
|
||||||
|
{
|
||||||
|
if( aNode == m_Appearance )
|
||||||
|
{
|
||||||
|
m_Appearance = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aNode == m_FaceSet )
|
||||||
|
{
|
||||||
|
m_FaceSet = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( aNode == m_RAppearance )
|
||||||
|
{
|
||||||
|
m_RAppearance = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aNode == m_RFaceSet )
|
||||||
|
{
|
||||||
|
m_RFaceSet = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] unlinkNode() did not find its target\n";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGSHAPE::unlinkChildNode( const SGNODE* aNode )
|
||||||
|
{
|
||||||
|
unlinkNode( aNode, true );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGSHAPE::unlinkRefNode( const SGNODE* aNode )
|
||||||
|
{
|
||||||
|
unlinkNode( aNode, false );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::addNode( SGNODE* aNode, bool isChild )
|
||||||
|
{
|
||||||
|
if( NULL == aNode )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] NULL pointer passed for aNode\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_APPEARANCE == aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
if( m_Appearance || m_RAppearance )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] assigning multiple Appearance nodes\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isChild )
|
||||||
|
{
|
||||||
|
m_Appearance = (SGAPPEARANCE*)aNode;
|
||||||
|
m_Appearance->SetParent( this );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_RAppearance = (SGAPPEARANCE*)aNode;
|
||||||
|
m_RAppearance->addNodeRef( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_FACESET == aNode->GetNodeType() )
|
||||||
|
{
|
||||||
|
if( m_FaceSet || m_RFaceSet )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] assigning multiple FaceSet nodes\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isChild )
|
||||||
|
{
|
||||||
|
m_FaceSet = (SGFACESET*)aNode;
|
||||||
|
m_FaceSet->SetParent( this );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_RFaceSet = (SGFACESET*)aNode;
|
||||||
|
m_RFaceSet->addNodeRef( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] object '" << aNode->GetName();
|
||||||
|
std::cerr << "' is not a valid type for this object (" << aNode->GetNodeType() << ")\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::AddRefNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
return addNode( aNode, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::AddChildNode( SGNODE* aNode )
|
||||||
|
{
|
||||||
|
return addNode( aNode, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SGSHAPE::ReNameNodes( void )
|
||||||
|
{
|
||||||
|
m_written = false;
|
||||||
|
|
||||||
|
// rename this node
|
||||||
|
m_Name.clear();
|
||||||
|
GetName();
|
||||||
|
|
||||||
|
// rename Appearance
|
||||||
|
if( m_Appearance )
|
||||||
|
m_Appearance->ReNameNodes();
|
||||||
|
|
||||||
|
// rename FaceSet
|
||||||
|
if( m_FaceSet )
|
||||||
|
m_FaceSet->ReNameNodes();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::WriteVRML( std::ofstream& aFile, bool aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_Appearance && !m_RAppearance
|
||||||
|
&& !m_FaceSet && !m_RFaceSet )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tmp;
|
||||||
|
|
||||||
|
if( aReuseFlag )
|
||||||
|
{
|
||||||
|
if( !m_written )
|
||||||
|
{
|
||||||
|
aFile << "DEF " << GetName() << " Shape {\n";
|
||||||
|
m_written = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " USE " << GetName() << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aFile << " Shape {\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_Appearance )
|
||||||
|
m_Appearance->WriteVRML( aFile, aReuseFlag );
|
||||||
|
|
||||||
|
if( m_RAppearance )
|
||||||
|
m_RAppearance->WriteVRML( aFile, aReuseFlag );
|
||||||
|
|
||||||
|
if( m_FaceSet )
|
||||||
|
m_FaceSet->WriteVRML( aFile, aReuseFlag );
|
||||||
|
|
||||||
|
if( m_RFaceSet )
|
||||||
|
m_RFaceSet->WriteVRML( aFile, aReuseFlag );
|
||||||
|
|
||||||
|
aFile << "}\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::WriteCache( std::ofstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == parentNode )
|
||||||
|
{
|
||||||
|
if( NULL == m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; m_aParent is NULL\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = m_Parent;
|
||||||
|
|
||||||
|
while( NULL != np->GetParent() )
|
||||||
|
np = np->GetParent();
|
||||||
|
|
||||||
|
return np->WriteCache( aFile, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( parentNode != m_Parent )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] corrupt data; parentNode != m_aParent\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !aFile.good() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad stream\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile << "[" << GetName() << "]";
|
||||||
|
#define NITEMS 4
|
||||||
|
bool items[NITEMS];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < NITEMS; ++i )
|
||||||
|
items[i] = 0;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if( NULL != m_Appearance )
|
||||||
|
items[i] = true;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
if( NULL != m_RAppearance )
|
||||||
|
items[i] = true;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
if( NULL != m_FaceSet )
|
||||||
|
items[i] = true;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
if( NULL != m_RFaceSet )
|
||||||
|
items[i] = true;
|
||||||
|
|
||||||
|
for( int i = 0; i < NITEMS; ++i )
|
||||||
|
aFile.write( (char*)&items[i], sizeof(bool) );
|
||||||
|
|
||||||
|
if( items[0] )
|
||||||
|
m_Appearance->WriteCache( aFile, this );
|
||||||
|
|
||||||
|
if( items[1] )
|
||||||
|
aFile << "[" << m_RAppearance->GetName() << "]";
|
||||||
|
|
||||||
|
if( items[2] )
|
||||||
|
m_FaceSet->WriteCache( aFile, this );
|
||||||
|
|
||||||
|
if( items[3] )
|
||||||
|
aFile << "[" << m_RFaceSet->GetName() << "]";
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::ReadCache( std::ifstream& aFile, SGNODE* parentNode )
|
||||||
|
{
|
||||||
|
if( m_Appearance || m_RAppearance || m_FaceSet || m_RFaceSet )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [BUG] non-empty node\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NITEMS 4
|
||||||
|
bool items[NITEMS];
|
||||||
|
|
||||||
|
for( int i = 0; i < NITEMS; ++i )
|
||||||
|
aFile.read( (char*)&items[i], sizeof(bool) );
|
||||||
|
|
||||||
|
if( ( items[0] && items[1] ) || ( items[2] && items[3] ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; multiple item definitions at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
if( items[0] )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad child apperance tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Appearance = new SGAPPEARANCE( this );
|
||||||
|
m_Appearance->SetName( name.c_str() );
|
||||||
|
|
||||||
|
if( !m_Appearance->ReadCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data while reading appearance '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( items[1] )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_APPEARANCE != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad ref appearance tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = FindNode( name.c_str(), this );
|
||||||
|
|
||||||
|
if( !np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: cannot find ref appearance '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_APPEARANCE != np->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: type is not SGAPPEARANCE '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_RAppearance = (SGAPPEARANCE*)np;
|
||||||
|
m_RAppearance->addNodeRef( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( items[2] )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad child face set tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_FaceSet = new SGFACESET( this );
|
||||||
|
m_FaceSet->SetName( name.c_str() );
|
||||||
|
|
||||||
|
if( !m_FaceSet->ReadCache( aFile, this ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data while reading face set '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( items[3] )
|
||||||
|
{
|
||||||
|
if( S3D::SGTYPE_FACESET != S3D::ReadTag( aFile, name ) )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data; bad ref face set tag at position ";
|
||||||
|
std::cerr << aFile.tellg() << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SGNODE* np = FindNode( name.c_str(), this );
|
||||||
|
|
||||||
|
if( !np )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: cannot find ref face set '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( S3D::SGTYPE_FACESET != np->GetNodeType() )
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] corrupt data: type is not SGFACESET '";
|
||||||
|
std::cerr << name << "'\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_RFaceSet = (SGFACESET*)np;
|
||||||
|
m_RFaceSet->addNodeRef( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( aFile.fail() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SGSHAPE::Prepare( const glm::dmat4* aTransform,
|
||||||
|
S3D::MATLIST& materials, std::vector< SMESH >& meshes )
|
||||||
|
{
|
||||||
|
SMESH m;
|
||||||
|
S3D::INIT_SMESH( m );
|
||||||
|
|
||||||
|
SGAPPEARANCE* pa = m_Appearance;
|
||||||
|
SGFACESET* pf = m_FaceSet;
|
||||||
|
|
||||||
|
if( NULL == pa )
|
||||||
|
pa = m_RAppearance;
|
||||||
|
|
||||||
|
if( NULL == pf )
|
||||||
|
pf = m_RFaceSet;
|
||||||
|
|
||||||
|
// no face sets = nothing to render, which is valid though pointless
|
||||||
|
if( NULL == pf )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( !pf->validate() )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad model; inconsistent data\n";
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL == m_Appearance )
|
||||||
|
{
|
||||||
|
m.m_MaterialIdx = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
if( !S3D::GetMatIndex( materials, pa, idx ) )
|
||||||
|
{
|
||||||
|
m.m_MaterialIdx = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m.m_MaterialIdx = idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SGCOLORS* pc = pf->m_Colors;
|
||||||
|
SGCOLORINDEX* cidx = pf->m_ColorIndices;
|
||||||
|
SGCOORDS* pv = pf->m_Coords;
|
||||||
|
SGCOORDINDEX* vidx = pf->m_CoordIndices;
|
||||||
|
SGNORMALS* pn = pf->m_Normals;
|
||||||
|
|
||||||
|
if( NULL == pc )
|
||||||
|
pc = pf->m_RColors;
|
||||||
|
|
||||||
|
if( NULL == pv )
|
||||||
|
pv = pf->m_RCoords;
|
||||||
|
|
||||||
|
if( NULL == pn )
|
||||||
|
pn = pf->m_RNormals;
|
||||||
|
|
||||||
|
// set the vertex points and indices
|
||||||
|
size_t nCoords = 0;
|
||||||
|
SGPOINT* pCoords = NULL;
|
||||||
|
pv->GetCoordsList( nCoords, pCoords );
|
||||||
|
|
||||||
|
// set the vertex indices
|
||||||
|
size_t nvidx = 0;
|
||||||
|
int* lv = NULL;
|
||||||
|
vidx->GetIndices( nvidx, lv );
|
||||||
|
|
||||||
|
// note: reduce the vertex set to include only the referenced vertices
|
||||||
|
std::vector< int > vertices; // store the list of temp vertex indices
|
||||||
|
std::map< int, unsigned int > indexmap; // map temp vertex to true vertex
|
||||||
|
std::map< int, unsigned int >::iterator mit;
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < nvidx; ++i )
|
||||||
|
{
|
||||||
|
mit = indexmap.find( lv[i] );
|
||||||
|
|
||||||
|
if( mit == indexmap.end() )
|
||||||
|
{
|
||||||
|
indexmap.insert( std::pair< int, unsigned int >( lv[i], vertices.size() ) );
|
||||||
|
vertices.push_back( lv[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vertices.size() < 3 )
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
|
||||||
|
std::cerr << " * [INFO] bad model; not enough vertices\n";
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct the final vertex list
|
||||||
|
SFVEC3F* lCoords = new SFVEC3F[ vertices.size() ];
|
||||||
|
int ti, ii;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < vertices.size(); ++i )
|
||||||
|
{
|
||||||
|
ti = vertices[i];
|
||||||
|
glm::dvec4 pt( pCoords[ti].x, pCoords[ti].y, pCoords[ti].z, 1.0 );
|
||||||
|
pt = (*aTransform) * pt;
|
||||||
|
|
||||||
|
lCoords[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
m.m_VertexSize = (unsigned int) vertices.size();
|
||||||
|
m.m_Positions = lCoords;
|
||||||
|
unsigned int* lvidx = new unsigned int[ nvidx ];
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < nvidx; ++i )
|
||||||
|
{
|
||||||
|
mit = indexmap.find( lv[i] );
|
||||||
|
lvidx[i] = mit->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.m_FaceIdxSize = (unsigned int )nvidx;
|
||||||
|
m.m_FaceIdx = lvidx;
|
||||||
|
|
||||||
|
// set the per-vertex normals
|
||||||
|
size_t nNorms = 0;
|
||||||
|
SGVECTOR* pNorms = NULL;
|
||||||
|
double x, y, z;
|
||||||
|
|
||||||
|
pn->GetNormalList( nNorms, pNorms );
|
||||||
|
SFVEC3F* lNorms = new SFVEC3F[ vertices.size() ];
|
||||||
|
|
||||||
|
for( size_t i = 0; i < vertices.size(); ++i )
|
||||||
|
{
|
||||||
|
ti = vertices[i];
|
||||||
|
pNorms[ti].GetVector( x, y, z );
|
||||||
|
glm::dvec4 pt( x, y, z, 0.0 );
|
||||||
|
pt = (*aTransform) * pt;
|
||||||
|
|
||||||
|
lNorms[i] = SFVEC3F( pt.x, pt.y, pt.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
m.m_Normals = lNorms;
|
||||||
|
|
||||||
|
// use per-vertex colors if available
|
||||||
|
if( pc )
|
||||||
|
{
|
||||||
|
size_t ncidx = 0;
|
||||||
|
int* lcidx = NULL;
|
||||||
|
cidx->GetIndices( ncidx, lcidx );
|
||||||
|
|
||||||
|
// set the vertex colors
|
||||||
|
size_t nColors = 0;
|
||||||
|
SGCOLOR* pColors = NULL;
|
||||||
|
pc->GetColorList( nColors, pColors );
|
||||||
|
SFVEC3F* lColors = new SFVEC3F[ vertices.size() ];
|
||||||
|
double red, green, blue;
|
||||||
|
|
||||||
|
for( size_t i = 0; i < vertices.size(); ++i )
|
||||||
|
{
|
||||||
|
ti = vertices[i];
|
||||||
|
pColors[ lcidx[ti] ].GetColor( lColors[i].x, lColors[i].y, lColors[i].z );
|
||||||
|
}
|
||||||
|
|
||||||
|
m.m_Color = lColors;
|
||||||
|
}
|
||||||
|
|
||||||
|
meshes.push_back( m );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 sg_shape.h
|
||||||
|
* defines a complex 3D shape for a scenegraph object
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SG_SHAPE_H
|
||||||
|
#define SG_SHAPE_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <3d_cache/sg/sg_node.h>
|
||||||
|
|
||||||
|
class SGAPPEARANCE;
|
||||||
|
class SGFACESET;
|
||||||
|
|
||||||
|
class SGSHAPE : public SGNODE
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void unlinkNode( const SGNODE* aNode, bool isChild );
|
||||||
|
bool addNode( SGNODE* aNode, bool isChild );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// owned node
|
||||||
|
SGAPPEARANCE* m_Appearance;
|
||||||
|
SGFACESET* m_FaceSet;
|
||||||
|
|
||||||
|
// referenced nodes
|
||||||
|
SGAPPEARANCE* m_RAppearance;
|
||||||
|
SGFACESET* m_RFaceSet;
|
||||||
|
|
||||||
|
void unlinkChildNode( const SGNODE* aNode );
|
||||||
|
void unlinkRefNode( const SGNODE* aNode );
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGSHAPE( SGNODE* aParent );
|
||||||
|
virtual ~SGSHAPE();
|
||||||
|
|
||||||
|
virtual bool SetParent( SGNODE* aParent, bool notify = true );
|
||||||
|
|
||||||
|
SGNODE* FindNode(const char *aNodeName, const SGNODE *aCaller);
|
||||||
|
bool AddRefNode( SGNODE* aNode );
|
||||||
|
bool AddChildNode( SGNODE* aNode );
|
||||||
|
|
||||||
|
void ReNameNodes( void );
|
||||||
|
bool WriteVRML( std::ofstream& aFile, bool aReuseFlag );
|
||||||
|
|
||||||
|
bool WriteCache( std::ofstream& aFile, SGNODE* parentNode );
|
||||||
|
bool ReadCache( std::ifstream& aFile, SGNODE* parentNode );
|
||||||
|
|
||||||
|
bool Prepare( const glm::dmat4* aTransform,
|
||||||
|
S3D::MATLIST& materials, std::vector< SMESH >& meshes );
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
p.107
|
||||||
|
Shape {
|
||||||
|
appearance NULL
|
||||||
|
geometry NULL
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif // SG_SHAPE_H
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
#ifndef SG_TYPES_H
|
||||||
|
#define SG_TYPES_H
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
enum SGTYPES
|
||||||
|
{
|
||||||
|
SGTYPE_TRANSFORM = 0,
|
||||||
|
SGTYPE_APPEARANCE,
|
||||||
|
SGTYPE_COLORS,
|
||||||
|
SGTYPE_COLORINDEX,
|
||||||
|
SGTYPE_FACESET,
|
||||||
|
SGTYPE_COORDS,
|
||||||
|
SGTYPE_COORDINDEX,
|
||||||
|
SGTYPE_NORMALS,
|
||||||
|
SGTYPE_SHAPE,
|
||||||
|
SGTYPE_END
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SG_TYPES_H
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 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 str_rsort.h
|
||||||
|
* provides a wxString sorting functino which works from the
|
||||||
|
* end of the string towards the beginning
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STR_RSORT_H
|
||||||
|
#define STR_RSORT_H
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
namespace S3D
|
||||||
|
{
|
||||||
|
|
||||||
|
struct rsort_wxString
|
||||||
|
{
|
||||||
|
bool operator() (const wxString& strA, const wxString& strB ) const
|
||||||
|
{
|
||||||
|
// sort a wxString using the reverse character order; for 3d model
|
||||||
|
// filenames this will typically be a much faster operation than
|
||||||
|
// a normal alphabetic sort
|
||||||
|
wxString::const_reverse_iterator sA = strA.rbegin();
|
||||||
|
wxString::const_reverse_iterator eA = strA.rend();
|
||||||
|
|
||||||
|
wxString::const_reverse_iterator sB = strB.rbegin();
|
||||||
|
wxString::const_reverse_iterator eB = strB.rend();
|
||||||
|
|
||||||
|
if( strA.empty() )
|
||||||
|
{
|
||||||
|
if( strB.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// note: this rule implies that a null string is first in the sort order
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( strB.empty() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while( sA != eA && sB != eB )
|
||||||
|
{
|
||||||
|
if( (*sA) == (*sB) )
|
||||||
|
{
|
||||||
|
++sA;
|
||||||
|
++sB;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (*sA) < (*sB) )
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sB == eB )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end NAMESPACE
|
||||||
|
|
||||||
|
#endif // STR_RSORT_H
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "md5.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main( int argc, char** argv )
|
||||||
|
{
|
||||||
|
if( argc != 2 )
|
||||||
|
{
|
||||||
|
cerr << "No filename given\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* fp = fopen( argv[1], "rb" );
|
||||||
|
|
||||||
|
if( !fp )
|
||||||
|
{
|
||||||
|
cout << "Could not open file '" << argv[1] << "'\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct md5_ctx msum;
|
||||||
|
md5_init_ctx( &msum );
|
||||||
|
unsigned char rb[16];
|
||||||
|
int res = md5_stream( fp, rb );
|
||||||
|
|
||||||
|
cout << "Result: " << res << "\n";
|
||||||
|
cout << "md5sum:\n";
|
||||||
|
for( int i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
cout << setfill( '0' ) << setw(2) << nouppercase << hex << ((int)rb[i] & 0xff);
|
||||||
|
}
|
||||||
|
cout << "\n";
|
||||||
|
|
||||||
|
fclose( fp );
|
||||||
|
|
||||||
|
/*
|
||||||
|
ifstream afile;
|
||||||
|
afile.open( argv[1], ios::in | ios::binary | ios::ate );
|
||||||
|
streampos fsize;
|
||||||
|
|
||||||
|
if( !afile.is_open() )
|
||||||
|
{
|
||||||
|
cout << "Could not open file '" << argv[1] << "'\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsize = afile.tellg();
|
||||||
|
afile.seekg( 0, ios::beg );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
afile.close();
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -45,7 +45,7 @@
|
||||||
#include <3d_struct.h>
|
#include <3d_struct.h>
|
||||||
#include <modelparsers.h>
|
#include <modelparsers.h>
|
||||||
#include <class_module.h>
|
#include <class_module.h>
|
||||||
#include <CBBox.h>
|
#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||||
|
|
||||||
class BOARD_DESIGN_SETTINGS;
|
class BOARD_DESIGN_SETTINGS;
|
||||||
class EDA_3D_FRAME;
|
class EDA_3D_FRAME;
|
||||||
|
|
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 cinfo3d_visu.h
|
||||||
|
* @brief Handles data related with the board to be visualized
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CINFO3D_VISU_H
|
||||||
|
#define CINFO3D_VISU_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
|
||||||
|
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer.h"
|
||||||
|
#include "../3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||||
|
#include "../3d_rendering/ccamera.h"
|
||||||
|
#include "../3d_rendering/ctrack_ball.h"
|
||||||
|
#include <layers_id_colors_and_visibility.h>
|
||||||
|
#include <class_pad.h>
|
||||||
|
#include <class_track.h>
|
||||||
|
#include <wx/gdicmn.h>
|
||||||
|
#include <wxBasePcbFrame.h>
|
||||||
|
#include <clipper.hpp>
|
||||||
|
#include <class_pcb_text.h>
|
||||||
|
#include <class_drawsegment.h>
|
||||||
|
#include <class_zone.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags used in rendering options
|
||||||
|
*/
|
||||||
|
enum DISPLAY3D_FLG {
|
||||||
|
FL_AXIS=0, FL_MODULE, FL_ZONE,
|
||||||
|
FL_ADHESIVE, FL_SILKSCREEN, FL_SOLDERMASK, FL_SOLDERPASTE,
|
||||||
|
FL_COMMENTS, FL_ECO,
|
||||||
|
FL_USE_COPPER_THICKNESS,
|
||||||
|
FL_SHOW_BOARD_BODY,
|
||||||
|
FL_USE_REALISTIC_MODE,
|
||||||
|
FL_RENDER_SHADOWS,
|
||||||
|
FL_RENDER_SHOW_HOLES_IN_ZONES,
|
||||||
|
FL_RENDER_TEXTURES,
|
||||||
|
FL_RENDER_SMOOTH_NORMALS,
|
||||||
|
FL_RENDER_USE_MODEL_NORMALS,
|
||||||
|
FL_RENDER_MATERIAL,
|
||||||
|
FL_RENDER_SHOW_MODEL_BBOX,
|
||||||
|
FL_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Camera types
|
||||||
|
*/
|
||||||
|
enum CAMERA_TYPE
|
||||||
|
{
|
||||||
|
CAMERA_TRACKBALL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grid types
|
||||||
|
*/
|
||||||
|
enum GRID3D_TYPE
|
||||||
|
{
|
||||||
|
GRID3D_NONE,
|
||||||
|
GRID3D_1MM,
|
||||||
|
GRID3D_2P5MM,
|
||||||
|
GRID3D_5MM,
|
||||||
|
GRID3D_10MM
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// A type that stores a container of 2d objects for each layer id
|
||||||
|
typedef std::map< LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
|
||||||
|
|
||||||
|
|
||||||
|
/// This defines the range that all coord will have to be rendered.
|
||||||
|
/// It will use this value to convert to a normalized value between
|
||||||
|
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||||
|
#define RANGE_SCALE_3D 8.0f
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CINFO3D_VISU
|
||||||
|
* Helper class to handle information needed to display 3D board
|
||||||
|
*/
|
||||||
|
class CINFO3D_VISU
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CINFO3D_VISU();
|
||||||
|
|
||||||
|
~CINFO3D_VISU();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetFlag - get a configuration status of a flag
|
||||||
|
* @param aFlag: the flag to get the status
|
||||||
|
* @return true if flag is set, false if not
|
||||||
|
*/
|
||||||
|
bool GetFlag( DISPLAY3D_FLG aFlag ) const ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SetFlag - set the status of a flag
|
||||||
|
* @param aFlag: the flag to get the status
|
||||||
|
* @param aState: status to set
|
||||||
|
*/
|
||||||
|
void SetFlag( DISPLAY3D_FLG aFlag, bool aState );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Is3DLayerEnabled - Check if a layer is enabled
|
||||||
|
* @param aLayer: layer ID to get status
|
||||||
|
* @return true if layer should be displayed, false if not
|
||||||
|
*/
|
||||||
|
bool Is3DLayerEnabled( LAYER_ID aLayer ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SetBoard - Set current board to be rendered
|
||||||
|
* @param aBoard: board to process
|
||||||
|
*/
|
||||||
|
void SetBoard( BOARD *aBoard ) { m_board = aBoard; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBoard - Get current board to be rendered
|
||||||
|
* @return BOARD pointer
|
||||||
|
*/
|
||||||
|
const BOARD *GetBoard() const { return m_board; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief InitSettings - Function to be called by the render when it need to
|
||||||
|
* reload the settings for the board.
|
||||||
|
*/
|
||||||
|
void InitSettings();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function BiuTo3Dunits
|
||||||
|
* @return the conversion factor to transform a position from the board to 3d units
|
||||||
|
*/
|
||||||
|
double BiuTo3Dunits() const { return m_biuTo3Dunits; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBBox3DU - Get the bbox of the pcb board
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const CBBOX &GetBBox3DU() const { return m_boardBoudingBox; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetEpoxyThickness3DU - Get the current epoxy thickness
|
||||||
|
* @return thickness in 3d unities
|
||||||
|
*/
|
||||||
|
float GetEpoxyThickness3DU() const { return m_epoxyThickness; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetNonCopperLayerThickness3DU - Get the current non copper layers thickness
|
||||||
|
* @return thickness in 3d unities of non copperlayers
|
||||||
|
*/
|
||||||
|
float GetNonCopperLayerThickness3DU() const { return m_nonCopperLayerThickness; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetCopperThickness3DU - Get the current copper layer thickness
|
||||||
|
* @return thickness in 3d unities of copperlayers
|
||||||
|
*/
|
||||||
|
float GetCopperThickness3DU() const { return m_copperThickness; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetCopperThicknessBIU - Get the current copper layer thickness
|
||||||
|
* @return thickness in board unities
|
||||||
|
*/
|
||||||
|
int GetCopperThicknessBIU() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBoardSize3DU - Get the board size
|
||||||
|
* @return size in 3D unities
|
||||||
|
*/
|
||||||
|
wxSize GetBoardSize3DU() const { return m_boardSize; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetBoardCenter
|
||||||
|
* @return board center in 3d units
|
||||||
|
*/
|
||||||
|
SFVEC3F &GetBoardCenter3DU() { return m_boardCenter; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param aIsFlipped: true for use in modules on Front (top) layer, false
|
||||||
|
* if module is on back (bottom) layer
|
||||||
|
* @return the Z position of 3D shapes, in 3D Units
|
||||||
|
*/
|
||||||
|
float GetModulesZcoord3DIU( bool aIsFlipped ) const ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param aCameraType: camera type to use in this canvas
|
||||||
|
*/
|
||||||
|
void CameraSetType( CAMERA_TYPE aCameraType );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief CameraGet - get current camera in use
|
||||||
|
* @return a camera
|
||||||
|
*/
|
||||||
|
CCAMERA &CameraGet() const { return m_currentCamera; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GridGet
|
||||||
|
* @return space type of the grid
|
||||||
|
*/
|
||||||
|
GRID3D_TYPE GridGet() const { return m_3D_Grid_type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GridSet
|
||||||
|
* @param aGridType = the type space of the grid
|
||||||
|
*/
|
||||||
|
void GridSet( GRID3D_TYPE aGridType ) { m_3D_Grid_type = aGridType; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBoardPoly - Get the current polygon of the epoxy board
|
||||||
|
* @return the shape polygon
|
||||||
|
*/
|
||||||
|
const SHAPE_POLY_SET &GetBoardPoly() const { return m_boardPoly; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetLayerColor - get the technical color of a layer
|
||||||
|
* @param aLayerId: the layer to get the color information
|
||||||
|
* @return the color in SFVEC3F format
|
||||||
|
*/
|
||||||
|
SFVEC3F GetLayerColor( LAYER_ID aLayerId ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetItemColor - get the technical color of a layer
|
||||||
|
* @param aItemId: the item id to get the color information
|
||||||
|
* @return the color in SFVEC3F format
|
||||||
|
*/
|
||||||
|
SFVEC3F GetItemColor( int aItemId ) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetLayerTopZpos3DU - Get the top z position
|
||||||
|
* @param aLayerId: layer id
|
||||||
|
* @return position in 3D unities
|
||||||
|
*/
|
||||||
|
float GetLayerTopZpos3DU( LAYER_ID aLayerId ) const { return m_layerZcoordTop[aLayerId]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetLayerBottomZpos3DU - Get the bottom z position
|
||||||
|
* @param aLayerId: layer id
|
||||||
|
* @return position in 3D unities
|
||||||
|
*/
|
||||||
|
float GetLayerBottomZpos3DU( LAYER_ID aLayerId ) const { return m_layerZcoordBottom[aLayerId]; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetMapLayers - Get the map of container that have the objects per layer
|
||||||
|
* @return the map containers of this board
|
||||||
|
*/
|
||||||
|
const MAP_CONTAINER_2D &GetMapLayers() const { return m_layers_container2D; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetMapLayersHoles -Get the map of container that have the holes per layer
|
||||||
|
* @return the map containers of holes from this board
|
||||||
|
*/
|
||||||
|
const MAP_CONTAINER_2D &GetMapLayersHoles() const { return m_layers_holes2D; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetThroughHole_Inflated - Get the inflated ThroughHole container
|
||||||
|
* @return a container with holes
|
||||||
|
*/
|
||||||
|
const CBVHCONTAINER2D &GetThroughHole_Inflated() const { return m_throughHoles_inflated; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetThroughHole - Get the ThroughHole container
|
||||||
|
* @return a container with holes
|
||||||
|
*/
|
||||||
|
const CBVHCONTAINER2D &GetThroughHole() const { return m_throughHoles; }
|
||||||
|
|
||||||
|
unsigned int GetStats_Nr_Vias() const { return m_stats_nr_vias; }
|
||||||
|
unsigned int GetStats_Nr_Holes() const { return m_stats_nr_holes; }
|
||||||
|
|
||||||
|
float GetStats_Med_Via_Hole_Diameter3DU() const { return m_stats_via_med_hole_diameter; }
|
||||||
|
float GetStats_Med_Hole_Diameter3DU() const { return m_stats_hole_med_diameter; }
|
||||||
|
float GetStats_Med_Track_Width() const { return m_stats_track_med_width; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createBoardPolygon();
|
||||||
|
void createLayers();
|
||||||
|
void destroyLayers();
|
||||||
|
|
||||||
|
// Helper functions to create the board
|
||||||
|
COBJECT2D *createNewTrack( const TRACK* aTrack , int aClearanceValue ) const;
|
||||||
|
void createNewPad(const D_PAD* aPad, CGENERICCONTAINER2D *aDstContainer, const wxSize &aInflateValue ) const;
|
||||||
|
void createNewPadWithClearance( const D_PAD* aPad, CGENERICCONTAINER2D *aDstContainer, int aClearanceValue ) const;
|
||||||
|
COBJECT2D *createNewPadDrill(const D_PAD* aPad, int aInflateValue);
|
||||||
|
void AddPadsShapesWithClearanceToContainer( const MODULE* aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue, bool aSkipNPTHPadsWihNoCopper );
|
||||||
|
void AddGraphicsShapesWithClearanceToContainer( const MODULE* aModule, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aInflateValue );
|
||||||
|
void AddShapeWithClearanceToContainer( const TEXTE_PCB* aTextPCB, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aClearanceValue );
|
||||||
|
void AddShapeWithClearanceToContainer(const DRAWSEGMENT* aDrawSegment, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId, int aClearanceValue );
|
||||||
|
void AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneContainer, CGENERICCONTAINER2D *aDstContainer, LAYER_ID aLayerId );
|
||||||
|
void TransformArcToSegments(const wxPoint &aCentre, const wxPoint &aStart, double aArcAngle, int aCircleToSegmentsCount, int aWidth, CGENERICCONTAINER2D *aDstContainer , const BOARD_ITEM &aBoardItem);
|
||||||
|
void buildPadShapeThickOutlineAsSegments( const D_PAD* aPad, CGENERICCONTAINER2D *aDstContainer, int aWidth);
|
||||||
|
|
||||||
|
public:
|
||||||
|
wxColour m_BgColor;
|
||||||
|
wxColour m_BgColor_Top;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BOARD *m_board;
|
||||||
|
|
||||||
|
// Render options
|
||||||
|
std::vector< bool > m_drawFlags; ///< options flags to render the board
|
||||||
|
GRID3D_TYPE m_3D_Grid_type; ///< Stores the current grid type
|
||||||
|
|
||||||
|
// Pcb board position
|
||||||
|
wxPoint m_boardPos; ///< center board actual position in board units
|
||||||
|
wxSize m_boardSize; ///< board actual size in board units
|
||||||
|
SFVEC3F m_boardCenter; ///< 3d center position of the pcb board in 3d units
|
||||||
|
|
||||||
|
// Pcb board bounding boxes
|
||||||
|
CBBOX m_boardBoudingBox; ///< 3d bouding box of the pcb board in 3d units
|
||||||
|
CBBOX2D m_board2dBBox3DU; ///< 2d bouding box of the pcb board in 3d units
|
||||||
|
|
||||||
|
SHAPE_POLY_SET m_boardPoly; ///< PCB board outline polygon
|
||||||
|
|
||||||
|
// 2D element containers
|
||||||
|
MAP_CONTAINER_2D m_layers_container2D; ///< It contains the 2d elements of each layer
|
||||||
|
MAP_CONTAINER_2D m_layers_holes2D; ///< It contains the holes per each layer
|
||||||
|
CBVHCONTAINER2D m_throughHoles_inflated; ///< It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper tickness
|
||||||
|
CBVHCONTAINER2D m_throughHoles; ///< It contains the list of throughHoles of the board, the radius of the hole is inflated with the copper tickness
|
||||||
|
|
||||||
|
// Layers information
|
||||||
|
unsigned int m_copperLayersCount; ///< Number of copper layers actually used by the board
|
||||||
|
double m_biuTo3Dunits; ///< Normalization scale to convert board internal units to 3D units to normalize 3D units between -1.0 and +1.0
|
||||||
|
float m_layerZcoordTop[LAYER_ID_COUNT]; ///< Top (End) Z position of each layer (normalized)
|
||||||
|
float m_layerZcoordBottom[LAYER_ID_COUNT]; ///< Bottom (Start) Z position of each layer (normalized)
|
||||||
|
float m_copperThickness; ///< Copper thickness (normalized)
|
||||||
|
float m_epoxyThickness; ///< Epoxy thickness (normalized)
|
||||||
|
float m_nonCopperLayerThickness; ///< Non copper layers thickness
|
||||||
|
|
||||||
|
// Cameras
|
||||||
|
CCAMERA &m_currentCamera; ///< Holds a pointer to current camera in use.
|
||||||
|
CTRACK_BALL m_trackBallCamera;
|
||||||
|
|
||||||
|
// Statistics
|
||||||
|
unsigned int m_stats_nr_tracks;
|
||||||
|
float m_stats_track_med_width;
|
||||||
|
unsigned int m_stats_nr_vias; ///< Nr of vias
|
||||||
|
float m_stats_via_med_hole_diameter; ///< Computed medium diameter of the via holes in 3dunits
|
||||||
|
unsigned int m_stats_nr_holes;
|
||||||
|
float m_stats_hole_med_diameter; ///< Computed medium diameter of the holes in 3dunits
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace mask used to enable or disable the trace output of this class.
|
||||||
|
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||||
|
* "KI_TRACE_EDA_CINFO3D_VISU". See the wxWidgets documentation on wxLogTrace for
|
||||||
|
* more information.
|
||||||
|
*/
|
||||||
|
static const wxChar *m_logTrace;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CINFO3D_VISU G_null_CINFO3D_VISU;
|
||||||
|
|
||||||
|
#endif // CINFO3D_VISU_H
|
|
@ -45,7 +45,7 @@
|
||||||
#include <colors_selection.h>
|
#include <colors_selection.h>
|
||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gal/opengl/opengl_compositor.h>
|
#include <gal/opengl/opengl_compositor.h>
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include <GL/glew.h> // must be included before gl.h
|
#include <GL/glew.h> // must be included before gl.h
|
||||||
|
@ -1128,16 +1128,24 @@ void EDA_3D_CANVAS::render3DComponentShape( MODULE* module,
|
||||||
shape3D->Render( aIsRenderingJustNonTransparentObjects,
|
shape3D->Render( aIsRenderingJustNonTransparentObjects,
|
||||||
aIsRenderingJustTransparentObjects );
|
aIsRenderingJustTransparentObjects );
|
||||||
|
|
||||||
if( isEnabled( FL_RENDER_SHOW_MODEL_BBOX ) )
|
/*
|
||||||
|
* XXX - CB - DEPRECATE THIS - the old renderer will eventually
|
||||||
|
* be replaced anyway so all debugging of 3D Plugins should be
|
||||||
|
* done via the new rendering system
|
||||||
|
*/
|
||||||
|
if( 0 )
|
||||||
{
|
{
|
||||||
// Set the alpha current color to opaque
|
if( isEnabled( FL_RENDER_SHOW_MODEL_BBOX ) )
|
||||||
float currentColor[4];
|
{
|
||||||
glGetFloatv( GL_CURRENT_COLOR,currentColor );
|
// Set the alpha current color to opaque
|
||||||
currentColor[3] = 1.0f;
|
float currentColor[4];
|
||||||
glColor4fv( currentColor );
|
glGetFloatv( GL_CURRENT_COLOR,currentColor );
|
||||||
|
currentColor[3] = 1.0f;
|
||||||
|
glColor4fv( currentColor );
|
||||||
|
|
||||||
CBBOX thisBBox = shape3D->getBBox();
|
CBBOX thisBBox = shape3D->getBBox();
|
||||||
thisBBox.GLdebug();
|
thisBBox.GLdebug();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
#include <colors_selection.h>
|
#include <colors_selection.h>
|
||||||
#include <convert_basic_shapes_to_polygon.h>
|
#include <convert_basic_shapes_to_polygon.h>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gal/opengl/opengl_compositor.h>
|
#include <gal/opengl/opengl_compositor.h>
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
#include <GL/glew.h> // must be included before gl.h
|
#include <GL/glew.h> // must be included before gl.h
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <base_struct.h>
|
#include <base_struct.h>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class S3D_MASTER;
|
class S3D_MASTER;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 3d_fastmath.h
|
||||||
|
* @brief Defines math related functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _3D_FASTMATH_H
|
||||||
|
#define _3D_FASTMATH_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
|
// Define this flag to use fast math optimizations
|
||||||
|
#define FASTMATH_USE
|
||||||
|
|
||||||
|
#define L1_CACHE_LINE_SIZE 64
|
||||||
|
|
||||||
|
#ifdef FASTMATH_USE
|
||||||
|
#define INTFLOORF(s) (lrintf( (s) - (0.5f - FLT_EPSILON) ))
|
||||||
|
#else
|
||||||
|
#define INTFLOORF(s) ((int)( floor(s) ))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This part contains some functions from the PBRT 3 source code.
|
||||||
|
* https://github.com/mmp/pbrt-v3/blob/master/src/core/pbrt.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
pbrt source code is Copyright(c) 1998-2015
|
||||||
|
Matt Pharr, Greg Humphreys, and Wenzel Jakob.
|
||||||
|
|
||||||
|
This file is part of pbrt.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
- Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
- Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Global Inline Functions
|
||||||
|
inline uint32_t FloatToBits(float f) {
|
||||||
|
uint32_t ui;
|
||||||
|
memcpy(&ui, &f, sizeof(float));
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BitsToFloat(uint32_t ui) {
|
||||||
|
float f;
|
||||||
|
memcpy(&f, &ui, sizeof(uint32_t));
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t FloatToBits(double f) {
|
||||||
|
uint64_t ui;
|
||||||
|
memcpy(&ui, &f, sizeof(double));
|
||||||
|
return ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double BitsToFloat(uint64_t ui) {
|
||||||
|
double f;
|
||||||
|
memcpy(&f, &ui, sizeof(uint64_t));
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float NextFloatUp(float v) {
|
||||||
|
// Handle infinity and negative zero for _NextFloatUp()_
|
||||||
|
if (std::isinf(v) && v > 0.) return v;
|
||||||
|
if (v == -0.f) v = 0.f;
|
||||||
|
|
||||||
|
// Advance _v_ to next higher float
|
||||||
|
uint32_t ui = FloatToBits(v);
|
||||||
|
if (v >= 0.)
|
||||||
|
++ui;
|
||||||
|
else
|
||||||
|
--ui;
|
||||||
|
return BitsToFloat(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float NextFloatDown(float v) {
|
||||||
|
// Handle infinity and positive zero for _NextFloatDown()_
|
||||||
|
if (std::isinf(v) && v < 0.) return v;
|
||||||
|
if (v == 0.f) v = -0.f;
|
||||||
|
uint32_t ui = FloatToBits(v);
|
||||||
|
if (v > 0.)
|
||||||
|
--ui;
|
||||||
|
else
|
||||||
|
++ui;
|
||||||
|
return BitsToFloat(ui);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // 3D_FASTMATH_H
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 3d_math.h
|
||||||
|
* @brief Defines math related functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _3D_MATH_H
|
||||||
|
#define _3D_MATH_H
|
||||||
|
|
||||||
|
#include "3d_xv3d/xv3d_types.h"
|
||||||
|
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
|
||||||
|
/**
|
||||||
|
* @brief SphericalToCartesian
|
||||||
|
* @param aInclination θ ∈ [0, π]
|
||||||
|
* @param aAzimuth φ ∈ [0, 2π]
|
||||||
|
* @return Cartesian cordinates
|
||||||
|
*/
|
||||||
|
inline SFVEC3F SphericalToCartesian( float aInclination, float aAzimuth )
|
||||||
|
{
|
||||||
|
float sinInc = glm::sin( aInclination );
|
||||||
|
return SFVEC3F( sinInc * glm::cos( aAzimuth ),
|
||||||
|
sinInc * glm::sin( aAzimuth ),
|
||||||
|
glm::cos( aInclination ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||||
|
// !TODO: this is not correct because it is not a gaussian random
|
||||||
|
inline SFVEC3F UniformRandomHemisphereDirection( )
|
||||||
|
{
|
||||||
|
SFVEC3F b( (rand()/(float)RAND_MAX) - 0.5f, (rand()/(float)RAND_MAX) - 0.5f, (rand()/(float)RAND_MAX) - 0.5f);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://pathtracing.wordpress.com/2011/03/03/cosine-weighted-hemisphere/
|
||||||
|
inline SFVEC3F CosWeightedRandomHemisphereDirection( SFVEC3F n )
|
||||||
|
{
|
||||||
|
const float Xi1 = (float)rand() / (float)RAND_MAX;
|
||||||
|
const float Xi2 = (float)rand() / (float)RAND_MAX;
|
||||||
|
|
||||||
|
const float theta = acos( sqrt( 1.0f - Xi1 ) );
|
||||||
|
const float phi = 2.0f * glm::pi<float>() * Xi2;
|
||||||
|
|
||||||
|
const float xs = sinf( theta ) * cosf( phi );
|
||||||
|
const float ys = cosf( theta );
|
||||||
|
const float zs = sinf( theta ) * sinf( phi );
|
||||||
|
|
||||||
|
const SFVEC3F y( n.x, n.y, n.z );
|
||||||
|
SFVEC3F h = y;
|
||||||
|
|
||||||
|
if (fabs( h.x ) <= fabs( h.y ) && fabs( h.x ) <= fabs( h.z ) )
|
||||||
|
h.x= 1.0f;
|
||||||
|
else if (fabs(h.y)<=fabs(h.x) && fabs(h.y)<=fabs(h.z))
|
||||||
|
h.y= 1.0f;
|
||||||
|
else
|
||||||
|
h.z= 1.0f;
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC3F x = glm::normalize( glm::cross( h, y ) );
|
||||||
|
const SFVEC3F z = glm::normalize( glm::cross( x, y ) );
|
||||||
|
|
||||||
|
SFVEC3F direction = xs * x + ys * y + zs * z;
|
||||||
|
return glm::normalize( direction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refract
|
||||||
|
* Based on: https://github.com/mmp/pbrt-v3/blob/master/src/core/reflection.h
|
||||||
|
* See also: http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_3_Refractions_and_Beers_Law.shtml
|
||||||
|
* @param aInVector incoming vector
|
||||||
|
* @param aNormal normal in the intersection point
|
||||||
|
* @param aRin_over_Rout incoming refraction index / out refraction index
|
||||||
|
* @param aOutVector the refracted vector
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
|
inline bool Refract( const SFVEC3F &aInVector, const SFVEC3F &aNormal, float aRin_over_Rout, SFVEC3F &aOutVector )
|
||||||
|
{
|
||||||
|
float cosThetaI = -glm::dot( aNormal, aInVector );
|
||||||
|
float sin2ThetaI = glm::max( 0.0f, 1.0f - cosThetaI * cosThetaI );
|
||||||
|
float sin2ThetaT = aRin_over_Rout * aRin_over_Rout * sin2ThetaI;
|
||||||
|
|
||||||
|
// Handle total internal reflection for transmission
|
||||||
|
if( sin2ThetaT >= 1.0f )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
float cosThetaT = sqrtf( 1.0f - sin2ThetaT );
|
||||||
|
aOutVector = glm::normalize( aRin_over_Rout * aInVector + ( aRin_over_Rout * cosThetaI - cosThetaT ) * aNormal );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float mapf( float x, float in_min, float in_max, float out_min, float out_max)
|
||||||
|
{
|
||||||
|
x = glm::clamp( x, in_min, in_max );
|
||||||
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // 3D_MATH_H
|
|
@ -31,8 +31,8 @@
|
||||||
#include <3d_mesh_model.h>
|
#include <3d_mesh_model.h>
|
||||||
#include <boost/geometry/algorithms/area.hpp>
|
#include <boost/geometry/algorithms/area.hpp>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <gal/opengl/glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#ifdef __WXMAC__
|
#ifdef __WXMAC__
|
||||||
# ifdef __DARWIN__
|
# ifdef __DARWIN__
|
||||||
|
|
|
@ -34,10 +34,10 @@
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include "3d_struct.h"
|
#include "3d_struct.h"
|
||||||
#include "3d_material.h"
|
#include "3d_material.h"
|
||||||
#include "CBBox.h"
|
#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||||
|
|
||||||
class S3D_MESH;
|
class S3D_MESH;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c3d_model_viewer.cpp
|
||||||
|
* @brief Implements a model viewer canvas
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "c3d_model_viewer.h"
|
||||||
|
#include "3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h"
|
||||||
|
#include "common_ogl/ogl_utils.h"
|
||||||
|
#include <wx/dcclient.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace mask used to enable or disable the trace output of this class.
|
||||||
|
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||||
|
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||||
|
* more information.
|
||||||
|
*/
|
||||||
|
const wxChar * C3D_MODEL_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_MODEL_VIEWER" );
|
||||||
|
|
||||||
|
|
||||||
|
BEGIN_EVENT_TABLE( C3D_MODEL_VIEWER, wxGLCanvas )
|
||||||
|
EVT_PAINT( C3D_MODEL_VIEWER::OnPaint )
|
||||||
|
|
||||||
|
// mouse events
|
||||||
|
EVT_LEFT_DOWN( C3D_MODEL_VIEWER::OnLeftDown )
|
||||||
|
EVT_LEFT_UP( C3D_MODEL_VIEWER::OnLeftUp )
|
||||||
|
EVT_MIDDLE_UP( C3D_MODEL_VIEWER::OnMiddleUp )
|
||||||
|
EVT_MIDDLE_DOWN(C3D_MODEL_VIEWER::OnMiddleDown)
|
||||||
|
EVT_RIGHT_DOWN( C3D_MODEL_VIEWER::OnRightClick )
|
||||||
|
EVT_MOUSEWHEEL( C3D_MODEL_VIEWER::OnMouseWheel )
|
||||||
|
EVT_MOTION( C3D_MODEL_VIEWER::OnMouseMove )
|
||||||
|
|
||||||
|
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||||
|
EVT_MAGNIFY( C3D_MODEL_VIEWER::OnMagnify )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// other events
|
||||||
|
EVT_ERASE_BACKGROUND( C3D_MODEL_VIEWER::OnEraseBackground )
|
||||||
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
/// This defines the range that all coord will have to be rendered.
|
||||||
|
/// It will use this value to convert to a normalized value between
|
||||||
|
/// -(RANGE_SCALE_3D/2) .. +(RANGE_SCALE_3D/2)
|
||||||
|
#define RANGE_SCALE_3D 8.0f
|
||||||
|
|
||||||
|
|
||||||
|
C3D_MODEL_VIEWER::C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||||
|
const int *aAttribList ) :
|
||||||
|
|
||||||
|
wxGLCanvas( aParent,
|
||||||
|
wxID_ANY,
|
||||||
|
aAttribList,
|
||||||
|
wxDefaultPosition,
|
||||||
|
wxDefaultSize,
|
||||||
|
wxFULL_REPAINT_ON_RESIZE ),
|
||||||
|
m_trackBallCamera( RANGE_SCALE_3D * 2.0f )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::C3D_MODEL_VIEWER" ) );
|
||||||
|
|
||||||
|
m_ogl_initialized = false;
|
||||||
|
m_reload_is_needed = false;
|
||||||
|
m_ogl_3dmodel = NULL;
|
||||||
|
m_3d_model = NULL;
|
||||||
|
|
||||||
|
// Explicitly create a new rendering context instance for this canvas.
|
||||||
|
m_glRC = new wxGLContext( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER()
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::~C3D_MODEL_VIEWER" ) );
|
||||||
|
|
||||||
|
delete m_ogl_3dmodel;
|
||||||
|
m_ogl_3dmodel = NULL;
|
||||||
|
|
||||||
|
delete m_glRC;
|
||||||
|
m_glRC = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::Set3DModel( const S3DMODEL &a3DModel )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::Set3DModel" ) );
|
||||||
|
|
||||||
|
// Validate a3DModel pointers
|
||||||
|
wxASSERT( a3DModel.m_Materials != NULL );
|
||||||
|
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||||
|
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||||
|
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||||
|
|
||||||
|
// Delete the old model
|
||||||
|
delete m_ogl_3dmodel;
|
||||||
|
m_ogl_3dmodel = NULL;
|
||||||
|
|
||||||
|
m_3d_model = NULL;
|
||||||
|
|
||||||
|
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||||
|
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||||
|
{
|
||||||
|
m_3d_model = &a3DModel;
|
||||||
|
m_reload_is_needed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::Clear3DModel()
|
||||||
|
{
|
||||||
|
// Delete the old model
|
||||||
|
m_reload_is_needed = false;
|
||||||
|
delete m_ogl_3dmodel;
|
||||||
|
m_ogl_3dmodel = NULL;
|
||||||
|
|
||||||
|
m_3d_model = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::ogl_initialize()
|
||||||
|
{
|
||||||
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
|
||||||
|
glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
|
||||||
|
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
|
||||||
|
|
||||||
|
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
//glDepthFunc( GL_LEQUAL );
|
||||||
|
glEnable( GL_CULL_FACE );
|
||||||
|
glShadeModel( GL_SMOOTH );
|
||||||
|
glEnable( GL_LINE_SMOOTH );
|
||||||
|
glEnable( GL_NORMALIZE );
|
||||||
|
|
||||||
|
// Setup light
|
||||||
|
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
const GLfloat ambient[] = { 0.1f, 0.1f, 0.1f, 1.0f };
|
||||||
|
const GLfloat diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
const GLfloat position[] = { 0.0f, 0.0f, 1.0f, 0.0f }; // defines a directional light that points along the negative z-axis
|
||||||
|
const GLfloat lmodel_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||||
|
|
||||||
|
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||||
|
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||||
|
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, position );
|
||||||
|
glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::ogl_set_arrow_material()
|
||||||
|
{
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||||
|
|
||||||
|
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||||
|
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnPaint( wxPaintEvent &event )
|
||||||
|
{
|
||||||
|
wxPaintDC( this );
|
||||||
|
|
||||||
|
// SwapBuffer requires the window to be shown before calling
|
||||||
|
if( !IsShownOnScreen() )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint !IsShown" ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Makes the OpenGL state that is represented by the OpenGL rendering
|
||||||
|
// context context current, i.e. it will be used by all subsequent OpenGL calls.
|
||||||
|
// This function may only be called when the window is shown on screen"
|
||||||
|
SetCurrent( *m_glRC );
|
||||||
|
|
||||||
|
// Set the OpenGL viewport according to the client size of this canvas.
|
||||||
|
// This is done here rather than in a wxSizeEvent handler because our
|
||||||
|
// OpenGL rendering context (and thus viewport setting) is used with
|
||||||
|
// multiple canvases: If we updated the viewport in the wxSizeEvent
|
||||||
|
// handler, changing the size of one canvas causes a viewport setting that
|
||||||
|
// is wrong when next another canvas is repainted.
|
||||||
|
wxSize clientSize = GetClientSize();
|
||||||
|
|
||||||
|
if( !m_ogl_initialized )
|
||||||
|
{
|
||||||
|
m_ogl_initialized = true;
|
||||||
|
ogl_initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_reload_is_needed )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnPaint m_reload_is_needed" ) );
|
||||||
|
|
||||||
|
m_reload_is_needed = false;
|
||||||
|
m_ogl_3dmodel = new C_OGL_3DMODEL( *m_3d_model );
|
||||||
|
|
||||||
|
// It convert a model as it was a board, so get the max size dimension of the board
|
||||||
|
// and compute the conversion scale
|
||||||
|
m_BiuTo3Dunits = (double)RANGE_SCALE_3D / ((double)m_ogl_3dmodel->GetBBox().GetMaxDimension() * UNITS3D_TO_UNITSPCB);
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport( 0, 0, clientSize.x, clientSize.y );
|
||||||
|
|
||||||
|
m_trackBallCamera.SetCurWindowSize( clientSize );
|
||||||
|
|
||||||
|
// clear color and depth buffers
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
glEnable( GL_DEPTH_TEST );
|
||||||
|
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||||
|
glClearDepth( 1.0f );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
// Set projection and modelview matrixes
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetProjectionMatrix() ) );
|
||||||
|
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadMatrixf( glm::value_ptr( m_trackBallCamera.GetViewMatrix() ) );
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glEnable(GL_LIGHT0);
|
||||||
|
|
||||||
|
ogl_set_arrow_material();
|
||||||
|
|
||||||
|
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( RANGE_SCALE_3D / 1.0f, 0.0f, 0.0f ),
|
||||||
|
0.2f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, RANGE_SCALE_3D / 1.0f, 0.0f ),
|
||||||
|
0.2f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 1.0f ),
|
||||||
|
0.2f );
|
||||||
|
|
||||||
|
// Render Model
|
||||||
|
if( m_ogl_3dmodel )
|
||||||
|
{
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
double modelunit_to_3d_units_factor = m_BiuTo3Dunits * UNITS3D_TO_UNITSPCB;
|
||||||
|
|
||||||
|
const SFVEC3F model_center = m_ogl_3dmodel->GetBBox().GetCenter();
|
||||||
|
glTranslatef( model_center.x, model_center.y, model_center.z );
|
||||||
|
|
||||||
|
glScaled( modelunit_to_3d_units_factor, modelunit_to_3d_units_factor, modelunit_to_3d_units_factor);
|
||||||
|
|
||||||
|
m_ogl_3dmodel->Draw_opaque();
|
||||||
|
//m_ogl_3dmodel->Draw_transparent();
|
||||||
|
//m_ogl_3dmodel->Draw_bboxes();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
glViewport( 0, 0, clientSize.y / 8 , clientSize.y / 8 ); // YxY squared view port
|
||||||
|
glClear( GL_DEPTH_BUFFER_BIT );
|
||||||
|
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective( 45.0f, 1.0f, 0.01f, RANGE_SCALE_3D * 2.0f );
|
||||||
|
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glm::mat4 TranslationMatrix = glm::translate( glm::mat4(1.0f), SFVEC3F( 0.0f, 0.0f, -RANGE_SCALE_3D ) );
|
||||||
|
glm::mat4 ViewMatrix = TranslationMatrix * m_trackBallCamera.GetRotationMatrix();
|
||||||
|
|
||||||
|
glLoadMatrixf( glm::value_ptr( ViewMatrix ) );
|
||||||
|
|
||||||
|
ogl_set_arrow_material();
|
||||||
|
|
||||||
|
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( RANGE_SCALE_3D / 2.65f, 0.0f, 0.0f ),
|
||||||
|
0.275f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, RANGE_SCALE_3D / 2.65f, 0.0f ),
|
||||||
|
0.275f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 2.65f ),
|
||||||
|
0.275f );
|
||||||
|
|
||||||
|
// "Swaps the double-buffer of this window, making the back-buffer the
|
||||||
|
// front-buffer and vice versa, so that the output of the previous OpenGL
|
||||||
|
// commands is displayed on the window."
|
||||||
|
SwapBuffers();
|
||||||
|
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnEraseBackground( wxEraseEvent &event )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnEraseBackground" ) );
|
||||||
|
// Do nothing, to avoid flashing.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnMouseWheel( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_MODEL_VIEWER::OnMouseWheel" ) );
|
||||||
|
|
||||||
|
if( event.ShiftDown() )
|
||||||
|
{
|
||||||
|
//if( event.GetWheelRotation() < 0 )
|
||||||
|
//SetView3D( WXK_UP ); // move up
|
||||||
|
//else
|
||||||
|
//SetView3D( WXK_DOWN ); // move down
|
||||||
|
}
|
||||||
|
else if( event.ControlDown() )
|
||||||
|
{
|
||||||
|
//if( event.GetWheelRotation() > 0 )
|
||||||
|
//SetView3D( WXK_RIGHT ); // move right
|
||||||
|
//else
|
||||||
|
//SetView3D( WXK_LEFT ); // move left
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( event.GetWheelRotation() > 0 )
|
||||||
|
{
|
||||||
|
m_trackBallCamera.ZoomIn( 1.1f );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_trackBallCamera.ZoomOut( 1.1f );
|
||||||
|
}
|
||||||
|
|
||||||
|
//DisplayStatus();
|
||||||
|
Refresh( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||||
|
void C3D_MODEL_VIEWER::OnMagnify( wxMouseEvent& event )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
double magnification = ( event.GetMagnification() + 1.0f );
|
||||||
|
GetPrm3DVisu().m_Zoom /= magnification;
|
||||||
|
if( GetPrm3DVisu().m_Zoom <= 0.01 )
|
||||||
|
GetPrm3DVisu().m_Zoom = 0.01;
|
||||||
|
DisplayStatus();
|
||||||
|
Refresh( false );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnMouseMove( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
m_trackBallCamera.SetCurWindowSize( GetClientSize() );
|
||||||
|
|
||||||
|
if( event.Dragging() )
|
||||||
|
{
|
||||||
|
if( event.LeftIsDown() ) // Drag
|
||||||
|
m_trackBallCamera.Drag( event.GetPosition() );
|
||||||
|
//else if( event.MiddleIsDown() ) // Pan
|
||||||
|
// m_trackBallCamera.Pan( event.GetPosition() );
|
||||||
|
|
||||||
|
// orientation has changed, redraw mesh
|
||||||
|
Refresh( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_trackBallCamera.SetCurMousePosition( event.GetPosition() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnLeftDown( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
//m_is_moving_mouse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnLeftUp( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
//m_is_moving_mouse = false;
|
||||||
|
//Refresh( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnMiddleDown( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
//m_is_moving_mouse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnMiddleUp( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
//m_is_moving_mouse = false;
|
||||||
|
//Refresh( false );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_MODEL_VIEWER::OnRightClick( wxMouseEvent &event )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c3d_model_viewer.h
|
||||||
|
* @brief Implements a model viewer canvas
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _C3D_MODEL_VIEWER_H_
|
||||||
|
#define _C3D_MODEL_VIEWER_H_
|
||||||
|
|
||||||
|
#include "3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h"
|
||||||
|
#include "3d_rendering/ctrack_ball.h"
|
||||||
|
#include <wx/glcanvas.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class C3D_MODEL_VIEWER
|
||||||
|
* Implement a canvas based on a wxGLCanvas
|
||||||
|
*/
|
||||||
|
class C3D_MODEL_VIEWER : public wxGLCanvas
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new 3D Canvas with a attribute list
|
||||||
|
* @param aParent = the parent creator of this canvas
|
||||||
|
* @param aAttribList = a list of openGL options created by COGL_ATT_LIST::GetAttributesList
|
||||||
|
*/
|
||||||
|
C3D_MODEL_VIEWER( wxWindow *aParent,
|
||||||
|
const int *aAttribList = 0 );
|
||||||
|
|
||||||
|
~C3D_MODEL_VIEWER();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set3DModel - Set this model to be displayed
|
||||||
|
* @param a3DModel - 3d model data
|
||||||
|
*/
|
||||||
|
void Set3DModel( const S3DMODEL &a3DModel );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear3DModel - Unloads the displayed 3d model
|
||||||
|
*/
|
||||||
|
void Clear3DModel();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ogl_initialize();
|
||||||
|
void ogl_set_arrow_material();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void OnPaint( wxPaintEvent &event );
|
||||||
|
|
||||||
|
void OnEraseBackground( wxEraseEvent &event );
|
||||||
|
|
||||||
|
void OnMouseWheel( wxMouseEvent &event );
|
||||||
|
|
||||||
|
#ifdef USE_OSX_MAGNIFY_EVENT
|
||||||
|
void OnMagnify( wxMouseEvent& event );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void OnMouseMove( wxMouseEvent &event );
|
||||||
|
|
||||||
|
void OnLeftDown( wxMouseEvent &event );
|
||||||
|
|
||||||
|
void OnLeftUp( wxMouseEvent &event );
|
||||||
|
|
||||||
|
void OnMiddleUp( wxMouseEvent &event );
|
||||||
|
void OnMiddleDown( wxMouseEvent &event );
|
||||||
|
|
||||||
|
void OnRightClick( wxMouseEvent &event );
|
||||||
|
|
||||||
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// openGL context
|
||||||
|
wxGLContext *m_glRC;
|
||||||
|
|
||||||
|
/// Camera used in this canvas
|
||||||
|
CTRACK_BALL m_trackBallCamera;
|
||||||
|
|
||||||
|
/// Original 3d model data
|
||||||
|
const S3DMODEL *m_3d_model;
|
||||||
|
|
||||||
|
/// Class holder for 3d model to display on openGL
|
||||||
|
C_OGL_3DMODEL *m_ogl_3dmodel;
|
||||||
|
|
||||||
|
/// Flag that we have a new model and it need to be reloaded when the paint is called
|
||||||
|
bool m_reload_is_needed;
|
||||||
|
|
||||||
|
/// Flag if open gl was initialized
|
||||||
|
bool m_ogl_initialized;
|
||||||
|
|
||||||
|
/// factor to convert the model or any other items to keep it in relation to the +/-RANGE_SCALE_3D
|
||||||
|
/// (it is named same as the board render for better understanding proposes)
|
||||||
|
double m_BiuTo3Dunits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace mask used to enable or disable the trace output of this class.
|
||||||
|
* The debug output can be turned on by setting the WXTRACE environment variable to
|
||||||
|
* "KI_TRACE_EDA_3D_MODEL_VIEWER". See the wxWidgets documentation on wxLogTrace for
|
||||||
|
* more information.
|
||||||
|
*/
|
||||||
|
static const wxChar *m_logTrace;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _C3D_MODEL_VIEWER_H_
|
|
@ -34,7 +34,7 @@
|
||||||
#include <kicad_string.h>
|
#include <kicad_string.h>
|
||||||
#include <pgm_base.h>
|
#include <pgm_base.h>
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#include <gal/opengl/glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <3d_viewer.h>
|
#include <3d_viewer.h>
|
||||||
#include <info3d_visu.h>
|
#include <info3d_visu.h>
|
||||||
#include "3d_struct.h"
|
#include "3d_struct.h"
|
||||||
|
|
|
@ -0,0 +1,816 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c3d_render_createscene_ogl_legacy.cpp
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "c3d_render_ogl_legacy.h"
|
||||||
|
|
||||||
|
#include "ogl_legacy_utils.h"
|
||||||
|
|
||||||
|
#include "../3d_render_raytracing/shapes2D/cpolygon2d.h"
|
||||||
|
#include "../3d_render_raytracing/shapes2D/ctriangle2d.h"
|
||||||
|
#include "../3d_render_raytracing/shapes2D/cpolygon4pts2d.h"
|
||||||
|
#include "../3d_render_raytracing/shapes2D/cfilledcircle2d.h"
|
||||||
|
#include "../3d_render_raytracing/shapes2D/cring2d.h"
|
||||||
|
#include "3d_math/3d_math.h"
|
||||||
|
#include "3d_math/3d_fastmath.h"
|
||||||
|
#include <trigo.h>
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::reload()
|
||||||
|
{
|
||||||
|
m_reloadRequested = false;
|
||||||
|
|
||||||
|
ogl_free_all_display_lists();
|
||||||
|
|
||||||
|
COBJECT2D_STATS::Instance().ResetStats();
|
||||||
|
|
||||||
|
printf("InitSettings...\n");
|
||||||
|
unsigned stats_startReloadTime = GetRunningMicroSecs();
|
||||||
|
m_settings.InitSettings();
|
||||||
|
unsigned stats_endReloadTime = GetRunningMicroSecs();
|
||||||
|
|
||||||
|
SFVEC3F camera_pos = m_settings.GetBoardCenter3DU();
|
||||||
|
m_settings.CameraGet().SetBoardLookAtPos( camera_pos );
|
||||||
|
|
||||||
|
unsigned stats_start_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||||
|
|
||||||
|
// Create Board
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
printf("Create board...\n");
|
||||||
|
CCONTAINER2D boardContainer;
|
||||||
|
Convert_shape_line_polygon_to_triangles( m_settings.GetBoardPoly(),
|
||||||
|
boardContainer,
|
||||||
|
m_settings.BiuTo3Dunits(),
|
||||||
|
(const BOARD_ITEM &)*m_settings.GetBoard() );
|
||||||
|
|
||||||
|
const LIST_OBJECT2D listBoardObject2d = boardContainer.GetList();
|
||||||
|
|
||||||
|
if( listBoardObject2d.size() > 0 )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
float layer_z_top = m_settings.GetLayerBottomZpos3DU( F_Cu );
|
||||||
|
float layer_z_bot = m_settings.GetLayerBottomZpos3DU( B_Cu );
|
||||||
|
*/
|
||||||
|
float layer_z_top = m_settings.GetLayerBottomZpos3DU( B_Mask );
|
||||||
|
float layer_z_bot = m_settings.GetLayerTopZpos3DU( B_Mask );
|
||||||
|
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( listBoardObject2d.size() );
|
||||||
|
|
||||||
|
for( LIST_OBJECT2D::const_iterator itemOnLayer = listBoardObject2d.begin();
|
||||||
|
itemOnLayer != listBoardObject2d.end();
|
||||||
|
itemOnLayer++ )
|
||||||
|
{
|
||||||
|
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||||
|
|
||||||
|
wxASSERT( object2d_A->GetObjectType() == OBJ2D_TRIANGLE );
|
||||||
|
|
||||||
|
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||||
|
const SFVEC2F &v1 = tri->GetP1();
|
||||||
|
const SFVEC2F &v2 = tri->GetP2();
|
||||||
|
const SFVEC2F &v3 = tri->GetP3();
|
||||||
|
|
||||||
|
add_triangle_top_bot( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot );
|
||||||
|
}
|
||||||
|
|
||||||
|
const SHAPE_POLY_SET boardPoly = m_settings.GetBoardPoly();
|
||||||
|
SHAPE_POLY_SET boardPolyCopy = boardPoly;
|
||||||
|
|
||||||
|
boardPolyCopy.Simplify( true );
|
||||||
|
|
||||||
|
if( boardPolyCopy.OutlineCount() == 1 )
|
||||||
|
{
|
||||||
|
const SHAPE_LINE_CHAIN& outlinePath = boardPolyCopy.COutline( 0 );
|
||||||
|
|
||||||
|
std::vector< SFVEC2F > contournPoints;
|
||||||
|
contournPoints.clear();
|
||||||
|
contournPoints.reserve( outlinePath.PointCount() + 2 );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < (unsigned int)outlinePath.PointCount(); ++i )
|
||||||
|
{
|
||||||
|
const VECTOR2I& v = outlinePath.CPoint( i );
|
||||||
|
contournPoints.push_back( SFVEC2F( v.x * m_settings.BiuTo3Dunits(),
|
||||||
|
-v.y * m_settings.BiuTo3Dunits() ) );
|
||||||
|
}
|
||||||
|
contournPoints.push_back( contournPoints[0] );
|
||||||
|
|
||||||
|
if( contournPoints.size() > 4 )
|
||||||
|
{
|
||||||
|
// Calculate normals of each segment of the contourn
|
||||||
|
std::vector< SFVEC2F > contournNormals;
|
||||||
|
contournNormals.clear();
|
||||||
|
contournNormals.reserve( contournPoints.size() );
|
||||||
|
for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = contournPoints[i + 0];
|
||||||
|
const SFVEC2F &v1 = contournPoints[i + 1];
|
||||||
|
|
||||||
|
SFVEC2F n = glm::normalize( v1 - v0 );
|
||||||
|
contournNormals.push_back( SFVEC2F( -n.y, n.x ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
SFVEC2F lastNormal = contournNormals[contournPoints.size() - 2];
|
||||||
|
for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = contournPoints[i + 0];
|
||||||
|
const SFVEC2F &v1 = contournPoints[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_top ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_top ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_bot ) ) );
|
||||||
|
|
||||||
|
SFVEC2F n0 = contournNormals[i];
|
||||||
|
|
||||||
|
if( glm::dot( n0, lastNormal ) > 0.5f )
|
||||||
|
n0 += lastNormal;
|
||||||
|
else
|
||||||
|
n0 += contournNormals[i];
|
||||||
|
|
||||||
|
const SFVEC2F &nextNormal = contournNormals[ (i + 1) % (contournPoints.size() - 1) ];
|
||||||
|
SFVEC2F n1 = contournNormals[i];
|
||||||
|
|
||||||
|
if( glm::dot( n1, nextNormal ) > 0.5f )
|
||||||
|
n1 += nextNormal;
|
||||||
|
else
|
||||||
|
n1 += contournNormals[i];
|
||||||
|
|
||||||
|
n0 = glm::normalize( n0 );
|
||||||
|
n1 = glm::normalize( n1 );
|
||||||
|
|
||||||
|
const SFVEC3F n3d0 = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n3d1 = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d0, n3d1, n3d1, n3d0 );
|
||||||
|
|
||||||
|
lastNormal = contournNormals[i];
|
||||||
|
/*
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - center );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - center );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contournPoints.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ogl_disp_list_board = new CLAYERS_OGL_DISP_LISTS( *layerTriangles, m_ogl_circle_texture, SFVEC3F(0.65f,0.55f,0.05f) );
|
||||||
|
|
||||||
|
delete layerTriangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float calc_sides_min_factor = (float)( 10.0 * IU_PER_MILS * m_settings.BiuTo3Dunits() );
|
||||||
|
float calc_sides_max_factor = (float)( 1000.0 * IU_PER_MILS * m_settings.BiuTo3Dunits() );
|
||||||
|
|
||||||
|
|
||||||
|
// Add layers maps (except B_Mask and F_Mask)
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
printf("Add layers maps...\n");
|
||||||
|
for( MAP_CONTAINER_2D::const_iterator ii = m_settings.GetMapLayers().begin();
|
||||||
|
ii != m_settings.GetMapLayers().end();
|
||||||
|
ii++ )
|
||||||
|
{
|
||||||
|
LAYER_ID layer_id = static_cast<LAYER_ID>(ii->first);
|
||||||
|
|
||||||
|
if( !m_settings.Is3DLayerEnabled( layer_id ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const CBVHCONTAINER2D *container2d = static_cast<const CBVHCONTAINER2D *>(ii->second);
|
||||||
|
const LIST_OBJECT2D listObject2d = container2d->GetList();
|
||||||
|
|
||||||
|
if( listObject2d.size() == 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//CMATERIAL *materialLayer = &m_materials.m_SilkS;
|
||||||
|
SFVEC3F layerColor = SFVEC3F( 0.3f, 0.4f, 0.5f );
|
||||||
|
|
||||||
|
float layer_z_bot = m_settings.GetLayerBottomZpos3DU( layer_id );
|
||||||
|
float layer_z_top = m_settings.GetLayerTopZpos3DU( layer_id );
|
||||||
|
|
||||||
|
if( layer_z_top < layer_z_bot )
|
||||||
|
{
|
||||||
|
float tmpFloat = layer_z_bot;
|
||||||
|
layer_z_bot = layer_z_top;
|
||||||
|
layer_z_top = tmpFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_z_bot -= m_settings.GetNonCopperLayerThickness3DU();
|
||||||
|
layer_z_top += m_settings.GetNonCopperLayerThickness3DU();
|
||||||
|
|
||||||
|
if( m_settings.GetFlag( FL_USE_REALISTIC_MODE ) )
|
||||||
|
{
|
||||||
|
switch( layer_id )
|
||||||
|
{
|
||||||
|
case B_Adhes:
|
||||||
|
case F_Adhes:
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_Paste:
|
||||||
|
case F_Paste:
|
||||||
|
// materialLayer = &m_materials.m_Paste;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_SilkS:
|
||||||
|
case F_SilkS:
|
||||||
|
|
||||||
|
// materialLayer = &m_materials.m_SilkS;
|
||||||
|
// layerColor = g_silkscreenColor;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Dwgs_User:
|
||||||
|
case Cmts_User:
|
||||||
|
case Eco1_User:
|
||||||
|
case Eco2_User:
|
||||||
|
case Edge_Cuts:
|
||||||
|
case Margin:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_CrtYd:
|
||||||
|
case F_CrtYd:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_Fab:
|
||||||
|
case F_Fab:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//materialLayer = &m_materials.m_Copper;
|
||||||
|
|
||||||
|
//layerColor = g_copperColor;
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
layerColor = m_settings.GetLayerColor( layer_id );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate an estiation for then nr of triangles based on the nr of objects
|
||||||
|
unsigned int nrTrianglesEstimation = listObject2d.size() * 8;
|
||||||
|
|
||||||
|
CLAYER_TRIANGLES *layerTriangles = new CLAYER_TRIANGLES( nrTrianglesEstimation );
|
||||||
|
|
||||||
|
m_triangles[layer_id] = layerTriangles;
|
||||||
|
|
||||||
|
for( LIST_OBJECT2D::const_iterator itemOnLayer = listObject2d.begin();
|
||||||
|
itemOnLayer != listObject2d.end();
|
||||||
|
itemOnLayer++ )
|
||||||
|
{
|
||||||
|
const COBJECT2D *object2d_A = static_cast<const COBJECT2D *>(*itemOnLayer);
|
||||||
|
|
||||||
|
switch( object2d_A->GetObjectType() )
|
||||||
|
{
|
||||||
|
|
||||||
|
case OBJ2D_FILLED_CIRCLE:
|
||||||
|
{
|
||||||
|
const CFILLEDCIRCLE2D *filledCircle = (const CFILLEDCIRCLE2D *)object2d_A;
|
||||||
|
const SFVEC2F ¢er = filledCircle->GetCenter();
|
||||||
|
float radius = filledCircle->GetRadius() * 2.0f; // Double because the render triangle
|
||||||
|
float radiusSquared = radius * radius;
|
||||||
|
|
||||||
|
const float texture_factor = (0.9f/(float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||||
|
const float f = (sqrtf(2.0f) / 2.0f) * radius * 0.9;// * texture_factor;
|
||||||
|
|
||||||
|
layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, layer_z_top ),
|
||||||
|
SFVEC3F( center.x - f, center.y, layer_z_top ),
|
||||||
|
SFVEC3F( center.x,
|
||||||
|
center.y - f, layer_z_top ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, layer_z_top ),
|
||||||
|
SFVEC3F( center.x + f, center.y, layer_z_top ),
|
||||||
|
SFVEC3F( center.x,
|
||||||
|
center.y + f, layer_z_top ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x - f, center.y, layer_z_bot ),
|
||||||
|
SFVEC3F( center.x + f, center.y, layer_z_bot ),
|
||||||
|
SFVEC3F( center.x,
|
||||||
|
center.y - f, layer_z_bot ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( center.x + f, center.y, layer_z_bot ),
|
||||||
|
SFVEC3F( center.x - f, center.y, layer_z_bot ),
|
||||||
|
SFVEC3F( center.x,
|
||||||
|
center.y + f, layer_z_bot ) );
|
||||||
|
|
||||||
|
unsigned int nr_sides_per_circle = (unsigned int)mapf( radiusSquared,
|
||||||
|
calc_sides_min_factor, calc_sides_max_factor,
|
||||||
|
24.0f, 256.0f );
|
||||||
|
|
||||||
|
wxASSERT( nr_sides_per_circle >= 24 );
|
||||||
|
|
||||||
|
// Normal radius for the circle
|
||||||
|
radius = filledCircle->GetRadius();
|
||||||
|
|
||||||
|
std::vector< SFVEC2F > contournPoints;
|
||||||
|
|
||||||
|
contournPoints.clear();
|
||||||
|
contournPoints.reserve( nr_sides_per_circle + 2 );
|
||||||
|
int delta = 3600 / nr_sides_per_circle;
|
||||||
|
int ii;
|
||||||
|
for( ii = 0; ii < 3600; ii += delta )
|
||||||
|
{
|
||||||
|
const SFVEC2F rotatedDir = glm::rotate( SFVEC2F( 0.0f, 1.0f ), (float)ii * 2.0f * 3.14f / 3600.0f );
|
||||||
|
contournPoints.push_back( SFVEC2F( center.x - rotatedDir.y * radius, center.y + rotatedDir.x * radius ) );
|
||||||
|
}
|
||||||
|
contournPoints.push_back( contournPoints[0] );
|
||||||
|
|
||||||
|
if( contournPoints.size() > 1 )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < ( contournPoints.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = contournPoints[i + 0];
|
||||||
|
const SFVEC2F &v1 = contournPoints[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ),
|
||||||
|
SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ) );
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - center );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - center );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contournPoints.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OBJ2D_DUMMYBLOCK:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OBJ2D_POLYGON4PT:
|
||||||
|
{
|
||||||
|
const CPOLYGON4PTS2D *poly = (const CPOLYGON4PTS2D *)object2d_A;
|
||||||
|
const SFVEC2F &v0 = poly->GetV0();
|
||||||
|
const SFVEC2F &v1 = poly->GetV1();
|
||||||
|
const SFVEC2F &v2 = poly->GetV2();
|
||||||
|
const SFVEC2F &v3 = poly->GetV3();
|
||||||
|
|
||||||
|
add_triangle_top_bot( layerTriangles, v0, v2, v1, layer_z_top, layer_z_bot );
|
||||||
|
add_triangle_top_bot( layerTriangles, v2, v0, v3, layer_z_top, layer_z_bot );
|
||||||
|
|
||||||
|
const SFVEC2F &n0 = poly->GetN0();
|
||||||
|
const SFVEC2F &n1 = poly->GetN1();
|
||||||
|
const SFVEC2F &n2 = poly->GetN2();
|
||||||
|
const SFVEC2F &n3 = poly->GetN3();
|
||||||
|
|
||||||
|
const SFVEC3F n3d0 = SFVEC3F(-n0.y, n0.x, 0.0f );
|
||||||
|
const SFVEC3F n3d1 = SFVEC3F(-n1.y, n1.x, 0.0f );
|
||||||
|
const SFVEC3F n3d2 = SFVEC3F(-n2.y, n2.x, 0.0f );
|
||||||
|
const SFVEC3F n3d3 = SFVEC3F(-n3.y, n3.x, 0.0f );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_top ),
|
||||||
|
SFVEC3F( v0.x, v0.y, layer_z_top ) );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d0, n3d0, n3d0, n3d0 );
|
||||||
|
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v2.x, v2.y, layer_z_top ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_top ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v2.x, v2.y, layer_z_bot ) );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d1, n3d1, n3d1, n3d1 );
|
||||||
|
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v3.x, v3.y, layer_z_top ),
|
||||||
|
SFVEC3F( v2.x, v2.y, layer_z_top ),
|
||||||
|
SFVEC3F( v2.x, v2.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v3.x, v3.y, layer_z_bot ) );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d2, n3d2, n3d2, n3d2 );
|
||||||
|
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_top ),
|
||||||
|
SFVEC3F( v3.x, v3.y, layer_z_top ),
|
||||||
|
SFVEC3F( v3.x, v3.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v0.x, v0.y, layer_z_bot ) );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n3d3, n3d3, n3d3, n3d3 );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case OBJ2D_RING:
|
||||||
|
{
|
||||||
|
const CRING2D *ring = (const CRING2D *)object2d_A;
|
||||||
|
const SFVEC2F ¢er = ring->GetCenter();
|
||||||
|
float inner = ring->GetInnerRadius();
|
||||||
|
float outer = ring->GetOuterRadius();
|
||||||
|
|
||||||
|
unsigned int nr_sides_per_circle = (unsigned int)mapf( outer,
|
||||||
|
calc_sides_min_factor, calc_sides_max_factor,
|
||||||
|
24.0f, 256.0f );
|
||||||
|
|
||||||
|
wxASSERT( nr_sides_per_circle >= 24 );
|
||||||
|
|
||||||
|
|
||||||
|
std::vector< SFVEC2F > innerContour;
|
||||||
|
std::vector< SFVEC2F > outerContour;
|
||||||
|
innerContour.clear();
|
||||||
|
innerContour.reserve( nr_sides_per_circle + 2 );
|
||||||
|
|
||||||
|
outerContour.clear();
|
||||||
|
outerContour.reserve( nr_sides_per_circle + 2 );
|
||||||
|
|
||||||
|
int delta = 3600 / nr_sides_per_circle;
|
||||||
|
for( int ii = 0; ii < 3600; ii += delta )
|
||||||
|
{
|
||||||
|
const SFVEC2F rotatedDir = glm::rotate( SFVEC2F( 0.0f, 1.0f), (float) ii * 2.0f * 3.14f / 3600.0f );
|
||||||
|
|
||||||
|
innerContour.push_back( SFVEC2F( center.x - rotatedDir.y * inner, center.y + rotatedDir.x * inner ) );
|
||||||
|
outerContour.push_back( SFVEC2F( center.x - rotatedDir.y * outer, center.y + rotatedDir.x * outer ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
innerContour.push_back( innerContour[0] );
|
||||||
|
outerContour.push_back( outerContour[0] );
|
||||||
|
|
||||||
|
wxASSERT( innerContour.size() == outerContour.size() );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &vi0 = innerContour[i + 0];
|
||||||
|
const SFVEC2F &vi1 = innerContour[i + 1];
|
||||||
|
const SFVEC2F &vo0 = outerContour[i + 0];
|
||||||
|
const SFVEC2F &vo1 = outerContour[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_top_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, layer_z_top ),
|
||||||
|
SFVEC3F( vi0.x, vi0.y, layer_z_top ),
|
||||||
|
SFVEC3F( vo0.x, vo0.y, layer_z_top ),
|
||||||
|
SFVEC3F( vo1.x, vo1.y, layer_z_top ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_bot_triangles->AddQuad( SFVEC3F( vi1.x, vi1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( vo1.x, vo1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( vo0.x, vo0.y, layer_z_bot ),
|
||||||
|
SFVEC3F( vi0.x, vi0.y, layer_z_bot ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ( innerContour.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = innerContour[i + 0];
|
||||||
|
const SFVEC2F &v1 = innerContour[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ) );
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - center );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - center );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < ( outerContour.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = outerContour[i + 0];
|
||||||
|
const SFVEC2F &v1 = outerContour[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatUp( layer_z_bot ) ),
|
||||||
|
SFVEC3F( v1.x, v1.y, NextFloatDown( layer_z_top ) ),
|
||||||
|
SFVEC3F( v0.x, v0.y, NextFloatDown( layer_z_top ) ) );
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - center );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - center );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case OBJ2D_TRIANGLE:
|
||||||
|
{
|
||||||
|
const CTRIANGLE2D *tri = (const CTRIANGLE2D *)object2d_A;
|
||||||
|
const SFVEC2F &v1 = tri->GetP1();
|
||||||
|
const SFVEC2F &v2 = tri->GetP2();
|
||||||
|
const SFVEC2F &v3 = tri->GetP3();
|
||||||
|
|
||||||
|
add_triangle_top_bot( layerTriangles, v1, v2, v3, layer_z_top, layer_z_bot );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OBJ2D_ROUNDSEG:
|
||||||
|
{
|
||||||
|
const CROUNDSEGMENT2D &roundSeg = (const CROUNDSEGMENT2D &) *object2d_A;
|
||||||
|
unsigned int nr_sides_per_circle = (unsigned int)mapf( roundSeg.GetWidth(),
|
||||||
|
calc_sides_min_factor, calc_sides_max_factor,
|
||||||
|
24.0f, 256.0f );
|
||||||
|
|
||||||
|
wxASSERT( nr_sides_per_circle >= 24 );
|
||||||
|
|
||||||
|
SFVEC2F leftStart = roundSeg.GetLeftStar();
|
||||||
|
SFVEC2F leftEnd = roundSeg.GetLeftEnd();
|
||||||
|
SFVEC2F leftDir = roundSeg.GetLeftDir();
|
||||||
|
|
||||||
|
SFVEC2F rightStart = roundSeg.GetRightStar();
|
||||||
|
SFVEC2F rightEnd = roundSeg.GetRightEnd();
|
||||||
|
SFVEC2F rightDir = roundSeg.GetRightDir();
|
||||||
|
float radius = roundSeg.GetRadius();
|
||||||
|
|
||||||
|
SFVEC2F start = roundSeg.GetStart();
|
||||||
|
SFVEC2F end = roundSeg.GetEnd();
|
||||||
|
|
||||||
|
float texture_factor = (12.0f/(float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||||
|
float texture_factorF= ( 4.0f/(float)SIZE_OF_CIRCLE_TEXTURE) + 1.0f;
|
||||||
|
|
||||||
|
const float radius_of_the_square = sqrtf( roundSeg.GetRadiusSquared() * 2.0f );
|
||||||
|
const float radius_triangle_factor = (radius_of_the_square - radius) / radius;
|
||||||
|
|
||||||
|
const SFVEC2F factorS = SFVEC2F( -rightDir.y * radius * radius_triangle_factor, rightDir.x * radius * radius_triangle_factor );
|
||||||
|
const SFVEC2F factorE = SFVEC2F( -leftDir.y * radius * radius_triangle_factor, leftDir.x * radius * radius_triangle_factor );
|
||||||
|
|
||||||
|
// Top end segment triangles
|
||||||
|
layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, layer_z_top ),
|
||||||
|
SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, layer_z_top ),
|
||||||
|
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf(2.0f),
|
||||||
|
start.y - texture_factorF * leftDir.y * radius * sqrtf(2.0f), layer_z_top ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_top_segment_ends->AddTriangle( SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, layer_z_top ),
|
||||||
|
SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, layer_z_top ),
|
||||||
|
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf(2.0f),
|
||||||
|
end.y - texture_factorF * rightDir.y * radius * sqrtf(2.0f), layer_z_top ) );
|
||||||
|
|
||||||
|
// Bot end segment triangles
|
||||||
|
layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( leftStart.x + texture_factor * factorE.x, leftStart.y + texture_factor * factorE.y, layer_z_bot ),
|
||||||
|
SFVEC3F( rightEnd.x + texture_factor * factorS.x, rightEnd.y + texture_factor * factorS.y, layer_z_bot ),
|
||||||
|
SFVEC3F( start.x - texture_factorF * leftDir.x * radius * sqrtf(2.0f),
|
||||||
|
start.y - texture_factorF * leftDir.y * radius * sqrtf(2.0f), layer_z_bot ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_bot_segment_ends->AddTriangle( SFVEC3F( rightStart.x + texture_factor * factorS.x, rightStart.y + texture_factor * factorS.y, layer_z_bot ),
|
||||||
|
SFVEC3F( leftEnd.x + texture_factor * factorE.x, leftEnd.y + texture_factor * factorE.y, layer_z_bot ),
|
||||||
|
SFVEC3F( end.x - texture_factorF * rightDir.x * radius * sqrtf(2.0f),
|
||||||
|
end.y - texture_factorF * rightDir.y * radius * sqrtf(2.0f), layer_z_bot ) );
|
||||||
|
|
||||||
|
// Segment top and bot planes
|
||||||
|
layerTriangles->m_layer_top_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, layer_z_top ),
|
||||||
|
SFVEC3F( rightStart.x, rightStart.y, layer_z_top ),
|
||||||
|
SFVEC3F( leftEnd.x, leftEnd.y, layer_z_top ),
|
||||||
|
SFVEC3F( leftStart.x, leftStart.y, layer_z_top ) );
|
||||||
|
|
||||||
|
layerTriangles->m_layer_bot_triangles->AddQuad( SFVEC3F( rightEnd.x, rightEnd.y, layer_z_bot ),
|
||||||
|
SFVEC3F( leftStart.x, leftStart.y, layer_z_bot ),
|
||||||
|
SFVEC3F( leftEnd.x, leftEnd.y, layer_z_bot ),
|
||||||
|
SFVEC3F( rightStart.x, rightStart.y, layer_z_bot ) );
|
||||||
|
|
||||||
|
// Middle contourns (two sides of the segment)
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( leftStart.x, leftStart.y, layer_z_top ),
|
||||||
|
SFVEC3F( leftEnd.x, leftEnd.y, layer_z_top ),
|
||||||
|
SFVEC3F( leftEnd.x, leftEnd.y, layer_z_bot ),
|
||||||
|
SFVEC3F( leftStart.x, leftStart.y, layer_z_bot ) );
|
||||||
|
const SFVEC3F leftNormal = SFVEC3F( -leftDir.y, leftDir.x, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( leftNormal, leftNormal, leftNormal, leftNormal );
|
||||||
|
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( rightStart.x, rightStart.y, layer_z_top ),
|
||||||
|
SFVEC3F( rightEnd.x, rightEnd.y, layer_z_top ),
|
||||||
|
SFVEC3F( rightEnd.x, rightEnd.y, layer_z_bot ),
|
||||||
|
SFVEC3F( rightStart.x, rightStart.y, layer_z_bot ) );
|
||||||
|
const SFVEC3F rightNormal = SFVEC3F( -rightDir.y, rightDir.x, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( rightNormal, rightNormal, rightNormal, rightNormal );
|
||||||
|
|
||||||
|
|
||||||
|
// Compute the outlines of the segment, and creates a polygon
|
||||||
|
// add right rounded end:
|
||||||
|
|
||||||
|
std::vector< SFVEC2F > roundedEndPointsStart;
|
||||||
|
std::vector< SFVEC2F > roundedEndPointsEnd;
|
||||||
|
roundedEndPointsStart.clear();
|
||||||
|
roundedEndPointsStart.reserve( nr_sides_per_circle + 2 );
|
||||||
|
|
||||||
|
roundedEndPointsEnd.clear();
|
||||||
|
roundedEndPointsEnd.reserve( nr_sides_per_circle + 2 );
|
||||||
|
|
||||||
|
roundedEndPointsStart.push_back( SFVEC2F( leftStart.x, leftStart.y ) );
|
||||||
|
roundedEndPointsEnd.push_back( SFVEC2F( leftEnd.x, leftEnd.y ) );
|
||||||
|
|
||||||
|
int delta = 3600 / nr_sides_per_circle;
|
||||||
|
for( int ii = delta; ii < 1800; ii += delta )
|
||||||
|
{
|
||||||
|
const SFVEC2F rotatedDirL = glm::rotate( leftDir, (float) ii * 2.0f * 3.14f / 3600.0f );
|
||||||
|
const SFVEC2F rotatedDirR = glm::rotate( rightDir, (float)(1800 - ii) * 2.0f * 3.14f / 3600.0f );
|
||||||
|
roundedEndPointsStart.push_back( SFVEC2F( start.x - rotatedDirL.y * radius, start.y + rotatedDirL.x * radius ) );
|
||||||
|
roundedEndPointsEnd.push_back( SFVEC2F( end.x - rotatedDirR.y * radius, end.y + rotatedDirR.x * radius ) );
|
||||||
|
}
|
||||||
|
roundedEndPointsStart.push_back( SFVEC2F( rightEnd.x, rightEnd.y ) );
|
||||||
|
roundedEndPointsEnd.push_back( SFVEC2F( rightStart.x, rightStart.y ) );
|
||||||
|
|
||||||
|
if( roundedEndPointsStart.size() > 1 )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < ( roundedEndPointsStart.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = roundedEndPointsStart[i + 0];
|
||||||
|
const SFVEC2F &v1 = roundedEndPointsStart[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_top ),
|
||||||
|
SFVEC3F( v0.x, v0.y, layer_z_top ) );
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - start );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - start );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roundedEndPointsStart.clear();
|
||||||
|
|
||||||
|
if( roundedEndPointsEnd.size() > 1 )
|
||||||
|
{
|
||||||
|
for( unsigned int i = 0; i < ( roundedEndPointsEnd.size() - 1 ); ++i )
|
||||||
|
{
|
||||||
|
const SFVEC2F &v0 = roundedEndPointsEnd[i + 0];
|
||||||
|
const SFVEC2F &v1 = roundedEndPointsEnd[i + 1];
|
||||||
|
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, layer_z_top ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_top ),
|
||||||
|
SFVEC3F( v1.x, v1.y, layer_z_bot ),
|
||||||
|
SFVEC3F( v0.x, v0.y, layer_z_bot ) );
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC2F n0 = glm::normalize( v0 - end );
|
||||||
|
const SFVEC2F n1 = glm::normalize( v1 - end );
|
||||||
|
const SFVEC3F n0z = SFVEC3F( n0.x, n0.y, 0.0f );
|
||||||
|
const SFVEC3F n1z = SFVEC3F( n1.x, n1.y, 0.0f );
|
||||||
|
layerTriangles->m_layer_middle_contourns_quads->AddNormal( n0z, n1z, n1z, n0z );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roundedEndPointsEnd.clear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
// not yet used / implemented (can be used in future to clip the objects in the board borders
|
||||||
|
COBJECT2D *object2d_C = CSGITEM_FULL;
|
||||||
|
|
||||||
|
std::vector<const COBJECT2D *> *object2d_B = CSGITEM_EMPTY;
|
||||||
|
|
||||||
|
if( m_settings.GetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES ) )
|
||||||
|
{
|
||||||
|
object2d_B = new std::vector<const COBJECT2D *>();
|
||||||
|
|
||||||
|
// Check if there are any layerhole that intersects this object
|
||||||
|
// Eg: a segment is cutted by a via hole or THT hole.
|
||||||
|
// /////////////////////////////////////////////////////////////
|
||||||
|
const MAP_CONTAINER_2D &layerHolesMap = m_settings.GetMapLayersHoles();
|
||||||
|
if( layerHolesMap.find(layer_id) != layerHolesMap.end() )
|
||||||
|
{
|
||||||
|
MAP_CONTAINER_2D::const_iterator ii_hole = layerHolesMap.find(layer_id);
|
||||||
|
const CBVHCONTAINER2D *containerLayerHoles2d = static_cast<const CBVHCONTAINER2D *>(ii_hole->second);
|
||||||
|
|
||||||
|
|
||||||
|
CONST_LIST_OBJECT2D intersectionList;
|
||||||
|
containerLayerHoles2d->GetListObjectsIntersects( object2d_A->GetBBox(), intersectionList );
|
||||||
|
|
||||||
|
if( !intersectionList.empty() )
|
||||||
|
{
|
||||||
|
for( CONST_LIST_OBJECT2D::const_iterator holeOnLayer = intersectionList.begin();
|
||||||
|
holeOnLayer != intersectionList.end();
|
||||||
|
holeOnLayer++ )
|
||||||
|
{
|
||||||
|
const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*holeOnLayer);
|
||||||
|
|
||||||
|
//if( object2d_A->Intersects( hole2d->GetBBox() ) )
|
||||||
|
//if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
|
||||||
|
object2d_B->push_back( hole2d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any THT that intersects this object
|
||||||
|
// /////////////////////////////////////////////////////////////
|
||||||
|
if( !m_settings.GetThroughHole_Inflated().GetList().empty() )
|
||||||
|
{
|
||||||
|
CONST_LIST_OBJECT2D intersectionList;
|
||||||
|
m_settings.GetThroughHole_Inflated().GetListObjectsIntersects( object2d_A->GetBBox(), intersectionList );
|
||||||
|
|
||||||
|
if( !intersectionList.empty() )
|
||||||
|
{
|
||||||
|
for( CONST_LIST_OBJECT2D::const_iterator hole = intersectionList.begin();
|
||||||
|
hole != intersectionList.end();
|
||||||
|
hole++ )
|
||||||
|
{
|
||||||
|
const COBJECT2D *hole2d = static_cast<const COBJECT2D *>(*hole);
|
||||||
|
|
||||||
|
//if( object2d_A->Intersects( hole2d->GetBBox() ) )
|
||||||
|
//if( object2d_A->GetBBox().Intersects( hole2d->GetBBox() ) )
|
||||||
|
object2d_B->push_back( hole2d );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( object2d_B->empty() )
|
||||||
|
{
|
||||||
|
delete object2d_B;
|
||||||
|
object2d_B = CSGITEM_EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (object2d_B == CSGITEM_EMPTY) &&
|
||||||
|
(object2d_C == CSGITEM_FULL) )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
create_3d_object_from( m_object_container, object2d_A, m_settings.GetLayerBottomZpos3DU( layer_id ),
|
||||||
|
m_settings.GetLayerTopZpos3DU( layer_id ),
|
||||||
|
materialLayer,
|
||||||
|
layerColor );
|
||||||
|
#else
|
||||||
|
CLAYERITEM *objPtr = new CLAYERITEM( object2d_A, m_settings.GetLayerBottomZpos3DU( layer_id ),
|
||||||
|
m_settings.GetLayerTopZpos3DU( layer_id ) );
|
||||||
|
objPtr->SetMaterial( materialLayer );
|
||||||
|
objPtr->SetColor( layerColor );
|
||||||
|
m_object_container.Add( objPtr );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
CITEMLAYERCSG2D *itemCSG2d = new CITEMLAYERCSG2D( object2d_A, object2d_B, object2d_C,
|
||||||
|
object2d_A->GetBoardItem() );
|
||||||
|
m_containerWithObjectsToDelete.Add( itemCSG2d );
|
||||||
|
|
||||||
|
CLAYERITEM *objPtr = new CLAYERITEM( itemCSG2d, m_settings.GetLayerBottomZpos3DU( layer_id ),
|
||||||
|
m_settings.GetLayerTopZpos3DU( layer_id ) );
|
||||||
|
|
||||||
|
objPtr->SetMaterial( materialLayer );
|
||||||
|
objPtr->SetColor( layerColor );
|
||||||
|
m_object_container.Add( objPtr );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create display list
|
||||||
|
// /////////////////////////////////////////////////////////////////////
|
||||||
|
m_ogl_disp_lists_layers[layer_id] = new CLAYERS_OGL_DISP_LISTS( *layerTriangles,
|
||||||
|
m_ogl_circle_texture,
|
||||||
|
layerColor );
|
||||||
|
}// for each layer on map
|
||||||
|
|
||||||
|
unsigned stats_end_OpenGL_Load_Time = GetRunningMicroSecs();
|
||||||
|
|
||||||
|
#ifdef RAYTRACING_PRINT_STATISTICS
|
||||||
|
printf( "C3D_RENDER_OGL_LEGACY::reload times:\n" );
|
||||||
|
printf( " Reload board: %.3f ms\n", (float)( stats_endReloadTime - stats_startReloadTime ) / 1000.0f );
|
||||||
|
printf( " Loading to openGL: %.3f ms\n", (float)( stats_end_OpenGL_Load_Time - stats_start_OpenGL_Load_Time ) / 1000.0f );
|
||||||
|
COBJECT2D_STATS::Instance().PrintStats();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::add_triangle_top_bot( CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot )
|
||||||
|
{
|
||||||
|
aDst->m_layer_bot_triangles->AddTriangle( SFVEC3F( v0.x, v0.y, bot ),
|
||||||
|
SFVEC3F( v1.x, v1.y, bot ),
|
||||||
|
SFVEC3F( v2.x, v2.y, bot ) );
|
||||||
|
|
||||||
|
aDst->m_layer_top_triangles->AddTriangle( SFVEC3F( v2.x, v2.y, top ),
|
||||||
|
SFVEC3F( v1.x, v1.y, top ),
|
||||||
|
SFVEC3F( v0.x, v0.y, top ) );
|
||||||
|
}
|
|
@ -0,0 +1,723 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c3d_render_ogl_legacy.cpp
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "c3d_render_ogl_legacy.h"
|
||||||
|
#include "ogl_legacy_utils.h"
|
||||||
|
#include "common_ogl/ogl_utils.h"
|
||||||
|
#include "../cimage.h"
|
||||||
|
|
||||||
|
C3D_RENDER_OGL_LEGACY::C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings,
|
||||||
|
S3D_CACHE *a3DModelManager ) :
|
||||||
|
C3D_RENDER_BASE( aSettings, a3DModelManager )
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_RENDER_OGL_LEGACY::C3D_RENDER_OGL_LEGACY" ) );
|
||||||
|
|
||||||
|
m_ogl_disp_lists_layers.clear();
|
||||||
|
m_triangles.clear();
|
||||||
|
m_ogl_disp_list_board = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
C3D_RENDER_OGL_LEGACY::~C3D_RENDER_OGL_LEGACY()
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace, wxT( "C3D_RENDER_OGL_LEGACY::~C3D_RENDER_OGL_LEGACY" ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::SetCurWindowSize( const wxSize &aSize )
|
||||||
|
{
|
||||||
|
if( m_windowSize != aSize )
|
||||||
|
{
|
||||||
|
m_windowSize = aSize;
|
||||||
|
glViewport( 0, 0, m_windowSize.x, m_windowSize.y );
|
||||||
|
|
||||||
|
// Initialize here any screen dependent data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* defines */
|
||||||
|
#define SPHERE 1
|
||||||
|
#define CONE 2
|
||||||
|
#define CUBE 3
|
||||||
|
|
||||||
|
|
||||||
|
/* csgOperation
|
||||||
|
* types of CSG operations
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CSG_A,
|
||||||
|
CSG_B,
|
||||||
|
CSG_A_OR_B,
|
||||||
|
CSG_A_AND_B,
|
||||||
|
CSG_A_SUB_B,
|
||||||
|
CSG_B_SUB_A
|
||||||
|
} csgOperation;
|
||||||
|
|
||||||
|
GLfloat cone_x = 0.0;
|
||||||
|
GLfloat cone_y = 0.0;
|
||||||
|
GLfloat cone_z = 0.0;
|
||||||
|
|
||||||
|
GLfloat cube_x = 0.0;
|
||||||
|
GLfloat cube_y = 0.0;
|
||||||
|
GLfloat cube_z = 0.0;
|
||||||
|
|
||||||
|
GLfloat sphere_x = 0.0;
|
||||||
|
GLfloat sphere_y = 0.0;
|
||||||
|
GLfloat sphere_z = 0.0;
|
||||||
|
|
||||||
|
GLint mouse_state = -1;
|
||||||
|
GLint mouse_button = -1;
|
||||||
|
|
||||||
|
csgOperation Op = CSG_A_OR_B;
|
||||||
|
|
||||||
|
void (*A)(void);
|
||||||
|
void (*B)(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
|
||||||
|
/* one()
|
||||||
|
* draw a single object
|
||||||
|
*/
|
||||||
|
void op_one(void(*a)(void))
|
||||||
|
{
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
a();
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* or()
|
||||||
|
* boolean A or B (draw wherever A or B)
|
||||||
|
* algorithm: simple, just draw both with depth test enabled
|
||||||
|
*/
|
||||||
|
void op_or(void(*a)(void), void(*b)())
|
||||||
|
{
|
||||||
|
glPushAttrib(GL_ALL_ATTRIB_BITS); /* TODO - should just push depth */
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
//glDisable(GL_CULL_FACE);
|
||||||
|
a(); b();
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inside()
|
||||||
|
* sets stencil buffer to show the part of A
|
||||||
|
* (front or back face according to 'face')
|
||||||
|
* that is inside of B.
|
||||||
|
*/
|
||||||
|
void op_inside(void(*a)(void), void(*b)(void), GLenum face, GLenum test)
|
||||||
|
{
|
||||||
|
/* draw A into depth buffer, but not into color buffer */
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glCullFace(face);
|
||||||
|
a();
|
||||||
|
|
||||||
|
/* use stencil buffer to find the parts of A that are inside of B
|
||||||
|
* by first incrementing the stencil buffer wherever B's front faces
|
||||||
|
* are...
|
||||||
|
*/
|
||||||
|
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
//glStencilFunc(GL_LESS, 1, 0);
|
||||||
|
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT ); //GL_INCR);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
b();
|
||||||
|
|
||||||
|
/* ...then decrement the stencil buffer wherever B's back faces are */
|
||||||
|
//glStencilFunc(GL_EQUAL, 0, 0);
|
||||||
|
//glStencilFunc(GL_ALWAYS, 0, 0);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO );
|
||||||
|
glCullFace(GL_FRONT);
|
||||||
|
b();
|
||||||
|
|
||||||
|
|
||||||
|
/* now draw the part of A that is inside of B */
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
glStencilFunc(test, 0, 1);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glCullFace(face);
|
||||||
|
a();
|
||||||
|
|
||||||
|
/* reset stencil test */
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fixup()
|
||||||
|
* fixes up the depth buffer with A's depth values
|
||||||
|
*/
|
||||||
|
void fixup(void(*a)(void))
|
||||||
|
{
|
||||||
|
/* fix up the depth buffer */
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
a();
|
||||||
|
|
||||||
|
/* reset depth func */
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* and()
|
||||||
|
* boolean A and B (draw wherever A intersects B)
|
||||||
|
* algorithm: find where A is inside B, then find where
|
||||||
|
* B is inside A
|
||||||
|
*/
|
||||||
|
void op_and(void(*a)(void), void(*b)(void))
|
||||||
|
{
|
||||||
|
op_inside(a, b, GL_BACK, GL_NOTEQUAL);
|
||||||
|
#if 1 /* set to 0 for faster, but incorrect results */
|
||||||
|
fixup(b);
|
||||||
|
#endif
|
||||||
|
op_inside(b, a, GL_BACK, GL_NOTEQUAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sub()
|
||||||
|
* boolean A subtract B (draw wherever A is and B is NOT)
|
||||||
|
* algorithm: find where a is inside B, then find where
|
||||||
|
* the BACK faces of B are NOT in A
|
||||||
|
*/
|
||||||
|
void op_sub(void(*a)(void), void(*b)(void))
|
||||||
|
{
|
||||||
|
op_inside(a, b, GL_FRONT, GL_NOTEQUAL);
|
||||||
|
|
||||||
|
#if 1 /* set to 0 for faster, but incorrect results */
|
||||||
|
fixup(b);
|
||||||
|
#endif
|
||||||
|
op_inside(b, a, GL_BACK, GL_EQUAL);
|
||||||
|
//op_inside(a, b, GL_FRONT, GL_NOTEQUAL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sphere()
|
||||||
|
* draw a yellow sphere
|
||||||
|
*/
|
||||||
|
void sphere(void)
|
||||||
|
{/*
|
||||||
|
glLoadName(2);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(sphere_x, sphere_y, sphere_z);
|
||||||
|
glColor3f(1.0, 1.0, 0.0);
|
||||||
|
glutSolidSphere(5.0, 16, 16);
|
||||||
|
glPopMatrix();*/
|
||||||
|
glBegin(GL_QUADS); // Begin drawing the color cube with 6 quads
|
||||||
|
// Top face (y = 1.0f)
|
||||||
|
// Define vertices in counter-clockwise (CCW) order with normal pointing out
|
||||||
|
glColor3f(0.0f, 1.0f, 0.0f); // Green
|
||||||
|
glVertex3f( 1.0f, 1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
// Bottom face (y = -1.0f)
|
||||||
|
glColor3f(1.0f, 0.5f, 0.0f); // Orange
|
||||||
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glVertex3f( 1.0f, -1.0f, -1.0f);
|
||||||
|
|
||||||
|
// Front face (z = 1.0f)
|
||||||
|
glColor3f(1.0f, 0.0f, 0.0f); // Red
|
||||||
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
// Back face (z = -1.0f)
|
||||||
|
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
|
||||||
|
glVertex3f( 1.0f, -1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glVertex3f( 1.0f, 1.0f, -1.0f);
|
||||||
|
|
||||||
|
// Left face (x = -1.0f)
|
||||||
|
glColor3f(0.0f, 0.0f, 1.0f); // Blue
|
||||||
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
||||||
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||||
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
// Right face (x = 1.0f)
|
||||||
|
glColor3f(1.0f, 0.0f, 1.0f); // Magenta
|
||||||
|
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||||
|
glVertex3f(1.0f, 1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, 1.0f);
|
||||||
|
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||||
|
glEnd(); // End of drawing color-cube
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cube()
|
||||||
|
* draw a red cube
|
||||||
|
*/
|
||||||
|
void cube(void)
|
||||||
|
{
|
||||||
|
glPushMatrix();
|
||||||
|
glColor3f(0.3, 0.8, 0.1);
|
||||||
|
OGL_draw_arrow( SFVEC3F( 1.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
0.2f );
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cone()
|
||||||
|
* draw a green cone
|
||||||
|
*/
|
||||||
|
void cone(void)
|
||||||
|
{
|
||||||
|
/* glLoadName(3);
|
||||||
|
glPushMatrix();
|
||||||
|
glTranslatef(cone_x, cone_y, cone_z);
|
||||||
|
glColor3f(0.0, 1.0, 0.0);
|
||||||
|
glTranslatef(0.0, 0.0, -6.5);
|
||||||
|
glutSolidCone(4.0, 15.0, 16, 16);
|
||||||
|
glRotatef(180.0, 1.0, 0.0, 0.0);
|
||||||
|
glutSolidCone(4.0, 0.0, 16, 1);
|
||||||
|
glPopMatrix();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(void)
|
||||||
|
{
|
||||||
|
//tbInit(GLUT_MIDDLE_BUTTON);
|
||||||
|
|
||||||
|
//glSelectBuffer(SELECT_BUFFER, select_buffer);
|
||||||
|
|
||||||
|
// glEnable( GL_DITHER );
|
||||||
|
|
||||||
|
glDepthFunc(GL_LESS);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
//glEnable(GL_LIGHT0);
|
||||||
|
//glEnable(GL_LIGHT1);
|
||||||
|
//glEnable(GL_LIGHT2);
|
||||||
|
//glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
// Setup light
|
||||||
|
// https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
{
|
||||||
|
const GLfloat ambient[] = { 0.1f, 0.0f, 0.1f, 1.0f };
|
||||||
|
const GLfloat diffuse[] = { 0.3f, 0.3f, 0.3f, 1.0f };
|
||||||
|
const GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
//const GLfloat lmodel_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||||
|
|
||||||
|
glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
|
||||||
|
glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
|
||||||
|
glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
|
||||||
|
|
||||||
|
const GLfloat position1[]= { 0.0f, 0.0f, 1.0f, 0.0f }; // defines a directional light that points along the negative z-axis
|
||||||
|
glLightfv( GL_LIGHT2, GL_AMBIENT, ambient );
|
||||||
|
glLightfv( GL_LIGHT2, GL_DIFFUSE, diffuse );
|
||||||
|
glLightfv( GL_LIGHT2, GL_SPECULAR, specular );
|
||||||
|
glLightfv( GL_LIGHT2, GL_POSITION, position1 );
|
||||||
|
|
||||||
|
const GLfloat position2[]= { 0.0f, 0.0f, -1.0f, 0.0f }; // defines a directional light that points along the positive z-axis
|
||||||
|
glLightfv( GL_LIGHT2, GL_AMBIENT, ambient );
|
||||||
|
glLightfv( GL_LIGHT2, GL_DIFFUSE, diffuse );
|
||||||
|
glLightfv( GL_LIGHT2, GL_SPECULAR, specular );
|
||||||
|
glLightfv( GL_LIGHT2, GL_POSITION, position2 );
|
||||||
|
//glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
|
||||||
|
}
|
||||||
|
|
||||||
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
|
||||||
|
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
|
glClearColor(0.0, 0.0, 1.0, 0.0);
|
||||||
|
{
|
||||||
|
const SFVEC4F ambient = SFVEC4F( 0.2,0.2,0.2, 1.0f );
|
||||||
|
const SFVEC4F diffuse = SFVEC4F( 0.5,0.1,0.1, 1.0f );
|
||||||
|
const SFVEC4F specular = SFVEC4F( 0.1,0.1,0.8, 1.0f );
|
||||||
|
//const SFVEC4F emissive = SFVEC4F( material.m_Emissive, 1.0f );
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r );
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r );
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||||
|
//glMaterialfv( GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r );
|
||||||
|
}
|
||||||
|
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 128 );
|
||||||
|
glDisable( GL_COLOR_MATERIAL );
|
||||||
|
|
||||||
|
glFrontFace( GL_CCW ); // This is the openGL default
|
||||||
|
glEnable( GL_NORMALIZE ); // This allow openGL to normalize the normals after transformations
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void display(void)
|
||||||
|
{
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||||
|
//glClearDepth( 1.0f );
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
//tbMatrix();
|
||||||
|
|
||||||
|
switch(Op) {
|
||||||
|
case CSG_A:
|
||||||
|
op_one(A);
|
||||||
|
break;
|
||||||
|
case CSG_B:
|
||||||
|
op_one(B);
|
||||||
|
break;
|
||||||
|
case CSG_A_OR_B:
|
||||||
|
op_or(A, B);
|
||||||
|
break;
|
||||||
|
case CSG_A_AND_B:
|
||||||
|
op_and(A, B);
|
||||||
|
break;
|
||||||
|
case CSG_A_SUB_B:
|
||||||
|
op_sub(A, B);
|
||||||
|
break;
|
||||||
|
case CSG_B_SUB_A:
|
||||||
|
op_sub(B, A);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const C3D_RENDER_OGL_LEGACY *renderclass = NULL;
|
||||||
|
|
||||||
|
void draw_board(void)
|
||||||
|
{
|
||||||
|
if( renderclass )
|
||||||
|
{
|
||||||
|
renderclass->GetBoardDispList()->DrawTop();
|
||||||
|
renderclass->GetBoardDispList()->DrawBot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_b_mask(void)
|
||||||
|
{
|
||||||
|
if( renderclass )
|
||||||
|
{
|
||||||
|
const CLAYERS_OGL_DISP_LISTS *layer = renderclass->GetLayerDispList( B_Mask );
|
||||||
|
layer->DrawTop();
|
||||||
|
layer->DrawBot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static SFVEC3F light = SFVEC3F();
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::Redraw( bool aIsMoving )
|
||||||
|
{
|
||||||
|
// Initialize openGL
|
||||||
|
if( !m_is_opengl_initialized )
|
||||||
|
{
|
||||||
|
if( !initializeOpenGL() )
|
||||||
|
return;
|
||||||
|
aIsMoving = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A = sphere;
|
||||||
|
B = cube;
|
||||||
|
|
||||||
|
//Op = CSG_A;
|
||||||
|
//Op = CSG_B;
|
||||||
|
//Op = CSG_A_OR_B;
|
||||||
|
//Op = CSG_A_AND_B;
|
||||||
|
//Op = CSG_A_SUB_B;
|
||||||
|
Op = CSG_B_SUB_A;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
const GLfloat position0[]= { 0.0f, 0.0f, 1.0f, 0.0f }; // defines a directional light that points along the negative z-axis
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, position0 );
|
||||||
|
*/
|
||||||
|
if( m_reloadRequested )
|
||||||
|
reload();
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
glEnable( GL_LIGHT0 );
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
|
||||||
|
|
||||||
|
// clear color and depth buffers
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
|
||||||
|
glClearDepth( 1.0f );
|
||||||
|
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
|
||||||
|
|
||||||
|
// Set projection and modelview matrixes
|
||||||
|
// /////////////////////////////////////////////////////////////////////////
|
||||||
|
glMatrixMode( GL_PROJECTION );
|
||||||
|
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetProjectionMatrix() ) );
|
||||||
|
|
||||||
|
glMatrixMode( GL_MODELVIEW );
|
||||||
|
|
||||||
|
// Position the headlight
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
//glTranslatef( -m_settings.GetBBox3DU().GetCenter().x, -m_settings.GetBBox3DU().GetCenter().y, -m_settings.GetBBox3DU().GetCenter().z );
|
||||||
|
// glTranslatef( m_settings.GetBBox3DU().GetCenter().x, m_settings.GetBBox3DU().GetCenter().y, m_settings.GetBBox3DU().GetCenter().z );
|
||||||
|
|
||||||
|
glLoadMatrixf( glm::value_ptr( m_settings.CameraGet().GetViewMatrix() ) );
|
||||||
|
|
||||||
|
{
|
||||||
|
const SFVEC3F &cameraPos = m_settings.CameraGet().GetPos();//m_settings.CameraGet().GetPos();
|
||||||
|
const GLfloat headlight_pos[] = { cameraPos.x, cameraPos.y, cameraPos.z, 1.0f };
|
||||||
|
glLightfv( GL_LIGHT0, GL_POSITION, headlight_pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SFVEC4F specular = SFVEC4F( 0.5f, 1.0f, 0.5f, 1.0f );
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT, GL_SPECULAR, &specular.r );
|
||||||
|
glMaterialf( GL_FRONT, GL_SHININESS, 10.0f );
|
||||||
|
|
||||||
|
SFVEC4F layerColor4 = SFVEC4F( specular.x, specular.y, specular.z, 1.0f );
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, &layerColor4.x );
|
||||||
|
glDisable( GL_COLOR_MATERIAL );
|
||||||
|
|
||||||
|
/*
|
||||||
|
glPushMatrix();
|
||||||
|
|
||||||
|
glTranslatef( m_settings.GetBBox3DU().GetCenter().x, m_settings.GetBBox3DU().GetCenter().y, m_settings.GetBBox3DU().GetCenter().z );
|
||||||
|
|
||||||
|
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
||||||
|
|
||||||
|
//const SFVEC4F specular = SFVEC4F( 0.5f, 0.5f, 0.5f, 1.0f );
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT, GL_SPECULAR, &specular.r );
|
||||||
|
glMaterialf( GL_FRONT, GL_SHININESS, 10.0f );
|
||||||
|
|
||||||
|
glColor3f( 0.9f, 0.0f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( RANGE_SCALE_3D / 1.0f, 0.0f, 0.0f ),
|
||||||
|
0.2f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.9f, 0.0f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, RANGE_SCALE_3D / 1.0f, 0.0f ),
|
||||||
|
0.2f );
|
||||||
|
|
||||||
|
glColor3f( 0.0f, 0.0f, 0.9f );
|
||||||
|
OGL_draw_arrow( SFVEC3F( 0.0f, 0.0f, 0.0f ),
|
||||||
|
SFVEC3F( 0.0f, 0.0f, RANGE_SCALE_3D / 1.0f ),
|
||||||
|
0.2f );
|
||||||
|
glPopMatrix();
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers.begin();
|
||||||
|
ii != m_ogl_disp_lists_layers.end();
|
||||||
|
ii++ )
|
||||||
|
{
|
||||||
|
|
||||||
|
LAYER_ID layer_id = (LAYER_ID)(ii->first);
|
||||||
|
|
||||||
|
// Mask kayers are not processed here because they are a special case
|
||||||
|
if( (layer_id == B_Mask) || (layer_id == F_Mask) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
|
||||||
|
pLayerDispList->DrawAll();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
renderclass = this;
|
||||||
|
//op_sub( draw_b_mask, draw_board );
|
||||||
|
//op_sub( draw_board, draw_b_mask );
|
||||||
|
|
||||||
|
|
||||||
|
const CLAYERS_OGL_DISP_LISTS *layer = renderclass->GetLayerDispList( B_Mask );
|
||||||
|
|
||||||
|
//glEnable(GL_LIGHTING);
|
||||||
|
//glEnable(GL_LIGHT0);
|
||||||
|
/*
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
m_ogl_disp_list_board->DrawBot();
|
||||||
|
*/
|
||||||
|
|
||||||
|
glCullFace(GL_BACK);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilFunc(GL_ALWAYS, 1, 0);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||||
|
layer->DrawBot();
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
glStencilFunc(GL_EQUAL, 0, 1);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP );
|
||||||
|
//glDisable(GL_DEPTH_TEST);
|
||||||
|
//glCullFace(face);
|
||||||
|
m_ogl_disp_list_board->DrawBot();
|
||||||
|
|
||||||
|
//glClear( GL_STENCIL_BUFFER_BIT );
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilFunc(GL_ALWAYS, 2, 0);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE );
|
||||||
|
layer->DrawTop();
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
glStencilFunc(GL_NOTEQUAL, 2, 0xFF);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR );
|
||||||
|
//glDisable(GL_DEPTH_TEST);
|
||||||
|
//glCullFace(face);
|
||||||
|
m_ogl_disp_list_board->DrawTop();
|
||||||
|
|
||||||
|
//glClear( GL_STENCIL_BUFFER_BIT );
|
||||||
|
|
||||||
|
//glCullFace(GL_FRONT);
|
||||||
|
/*
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_STENCIL_TEST);
|
||||||
|
glStencilFunc(GL_GEQUAL, 3, 0xFF);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR );
|
||||||
|
layer->DrawBot();
|
||||||
|
layer->DrawTop();
|
||||||
|
|
||||||
|
*/
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glCullFace(GL_FRONT);
|
||||||
|
glStencilFunc(GL_GEQUAL, 3, 0x03);
|
||||||
|
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP );
|
||||||
|
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
layer->DrawMiddle();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool C3D_RENDER_OGL_LEGACY::initializeOpenGL()
|
||||||
|
{
|
||||||
|
GLenum err = glewInit();
|
||||||
|
|
||||||
|
if( GLEW_OK != err )
|
||||||
|
{
|
||||||
|
std::string msgError = (const char*) glewGetErrorString( err );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wxLogTrace( m_logTrace,
|
||||||
|
wxString( wxT( "C3D_RENDER_OGL_LEGACY::initializeOpenGL Using GLEW " ) ) +
|
||||||
|
FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4-byte pixel alignment
|
||||||
|
glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
|
||||||
|
|
||||||
|
// Initialize the open GL texture to draw the filled semi-circle of the segments
|
||||||
|
CIMAGE *circleImage = new CIMAGE( SIZE_OF_CIRCLE_TEXTURE, SIZE_OF_CIRCLE_TEXTURE );
|
||||||
|
if( !circleImage )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 2) - 0, (SIZE_OF_CIRCLE_TEXTURE / 2) - 0, (SIZE_OF_CIRCLE_TEXTURE / 2) - 4, 0xFF );
|
||||||
|
//circleImage->CircleFilled( (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1, (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 1, (SIZE_OF_CIRCLE_TEXTURE / 4)*1.5f - 2, 0xFF );
|
||||||
|
|
||||||
|
CIMAGE *bluredCircle = new CIMAGE( *circleImage );
|
||||||
|
circleImage->EfxFilter( bluredCircle, FILTER_GAUSSIAN_BLUR2 );
|
||||||
|
|
||||||
|
m_ogl_circle_texture = OGL_LoadTexture( *circleImage );
|
||||||
|
|
||||||
|
circleImage->SaveAsPNG("circleImage.png");
|
||||||
|
delete circleImage;
|
||||||
|
circleImage = 0;
|
||||||
|
|
||||||
|
if( bluredCircle )
|
||||||
|
{
|
||||||
|
bluredCircle->SaveAsPNG("circleImage_blured.png");
|
||||||
|
delete bluredCircle;
|
||||||
|
bluredCircle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_is_opengl_initialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::ogl_set_arrow_material()
|
||||||
|
{
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||||
|
|
||||||
|
const SFVEC4F specular = SFVEC4F( 0.1f, 0.1f, 0.1f, 1.0f );
|
||||||
|
|
||||||
|
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r );
|
||||||
|
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 96.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C3D_RENDER_OGL_LEGACY::ogl_free_all_display_lists()
|
||||||
|
{
|
||||||
|
for( MAP_OGL_DISP_LISTS::const_iterator ii = m_ogl_disp_lists_layers.begin();
|
||||||
|
ii != m_ogl_disp_lists_layers.end();
|
||||||
|
ii++ )
|
||||||
|
{
|
||||||
|
CLAYERS_OGL_DISP_LISTS *pLayerDispList = static_cast<CLAYERS_OGL_DISP_LISTS*>(ii->second);
|
||||||
|
delete pLayerDispList;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ogl_disp_lists_layers.clear();
|
||||||
|
|
||||||
|
for( MAP_TRIANGLES::const_iterator ii = m_triangles.begin();
|
||||||
|
ii != m_triangles.end();
|
||||||
|
ii++ )
|
||||||
|
{
|
||||||
|
CLAYER_TRIANGLES *pointer = static_cast<CLAYER_TRIANGLES*>(ii->second);
|
||||||
|
delete pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_triangles.clear();
|
||||||
|
|
||||||
|
delete m_ogl_disp_list_board;
|
||||||
|
m_ogl_disp_list_board = 0;
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c3d_render_ogl_legacy.h
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef C3D_RENDER_OGL_LEGACY_H_
|
||||||
|
#define C3D_RENDER_OGL_LEGACY_H_
|
||||||
|
|
||||||
|
#include "../c3d_render_base.h"
|
||||||
|
#include "clayer_triangles.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::map< LAYER_ID, CLAYERS_OGL_DISP_LISTS* > MAP_OGL_DISP_LISTS;
|
||||||
|
typedef std::map< LAYER_ID, CLAYER_TRIANGLES * > MAP_TRIANGLES;
|
||||||
|
|
||||||
|
#define SIZE_OF_CIRCLE_TEXTURE 512
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The C3D_RENDER_OGL_LEGACY class render the board using openGL legacy mode
|
||||||
|
*/
|
||||||
|
class C3D_RENDER_OGL_LEGACY : public C3D_RENDER_BASE
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
C3D_RENDER_OGL_LEGACY( CINFO3D_VISU &aSettings,
|
||||||
|
S3D_CACHE *a3DModelManager );
|
||||||
|
|
||||||
|
~C3D_RENDER_OGL_LEGACY();
|
||||||
|
|
||||||
|
// Imported from C3D_RENDER_BASE
|
||||||
|
void SetCurWindowSize( const wxSize &aSize );
|
||||||
|
void Redraw( bool aIsMoving );
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool initializeOpenGL();
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
void ogl_set_arrow_material();
|
||||||
|
|
||||||
|
void ogl_free_all_display_lists();
|
||||||
|
MAP_OGL_DISP_LISTS m_ogl_disp_lists_layers;
|
||||||
|
CLAYERS_OGL_DISP_LISTS* m_ogl_disp_list_board;
|
||||||
|
MAP_TRIANGLES m_triangles;
|
||||||
|
|
||||||
|
GLuint m_ogl_circle_texture;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void add_triangle_top_bot( CLAYER_TRIANGLES *aDst, const SFVEC2F &v0, const SFVEC2F &v1, const SFVEC2F &v2, float top, float bot );
|
||||||
|
|
||||||
|
public:
|
||||||
|
const MAP_OGL_DISP_LISTS &GetLayerDispListMap() const { return m_ogl_disp_lists_layers; }
|
||||||
|
const CLAYERS_OGL_DISP_LISTS *GetLayerDispList( LAYER_ID aLayerId ) const { return m_ogl_disp_lists_layers.at( aLayerId ); }
|
||||||
|
const CLAYERS_OGL_DISP_LISTS *GetBoardDispList() const { return m_ogl_disp_list_board; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // C3D_RENDER_OGL_LEGACY_H_
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c_ogl_3dmodel.cpp
|
||||||
|
* @brief
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "c_ogl_3dmodel.h"
|
||||||
|
#include "ogl_legacy_utils.h"
|
||||||
|
#include "common_ogl/ogl_utils.h"
|
||||||
|
#include <wx/debug.h>
|
||||||
|
|
||||||
|
|
||||||
|
C_OGL_3DMODEL::C_OGL_3DMODEL( const S3DMODEL &a3DModel )
|
||||||
|
{
|
||||||
|
m_ogl_idx_list_opaque = 0;
|
||||||
|
m_ogl_idx_list_transparent = 0;
|
||||||
|
m_nr_meshes = 0;
|
||||||
|
m_meshs_bbox = NULL;
|
||||||
|
|
||||||
|
// Validate a3DModel pointers
|
||||||
|
wxASSERT( a3DModel.m_Materials != NULL );
|
||||||
|
wxASSERT( a3DModel.m_Meshes != NULL );
|
||||||
|
wxASSERT( a3DModel.m_MaterialsSize > 0 );
|
||||||
|
wxASSERT( a3DModel.m_MeshesSize > 0 );
|
||||||
|
|
||||||
|
if( (a3DModel.m_Materials != NULL) && (a3DModel.m_Meshes != NULL) &&
|
||||||
|
(a3DModel.m_MaterialsSize > 0) && (a3DModel.m_MeshesSize > 0) )
|
||||||
|
{
|
||||||
|
m_nr_meshes = a3DModel.m_MeshesSize;
|
||||||
|
|
||||||
|
m_meshs_bbox = new CBBOX[a3DModel.m_MeshesSize];
|
||||||
|
|
||||||
|
// Generate m_MeshesSize auxiliar lists to render the meshes
|
||||||
|
GLuint m_ogl_idx_list_meshes = glGenLists( a3DModel.m_MeshesSize );
|
||||||
|
|
||||||
|
// Render each mesh of the model
|
||||||
|
// /////////////////////////////////////////////////////////////////////
|
||||||
|
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||||
|
{
|
||||||
|
if( glIsList( m_ogl_idx_list_meshes + mesh_i ) )
|
||||||
|
{
|
||||||
|
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||||
|
|
||||||
|
// Validate the mesh pointers
|
||||||
|
wxASSERT( mesh.m_Positions != NULL );
|
||||||
|
wxASSERT( mesh.m_FaceIdx != NULL );
|
||||||
|
wxASSERT( mesh.m_Normals != NULL );
|
||||||
|
|
||||||
|
if( (mesh.m_Positions != NULL) &&
|
||||||
|
(mesh.m_Normals != NULL) &&
|
||||||
|
(mesh.m_FaceIdx != NULL) &&
|
||||||
|
(mesh.m_FaceIdxSize > 0) && (mesh.m_VertexSize > 0) )
|
||||||
|
{
|
||||||
|
// Create the bbox for this mesh
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
m_meshs_bbox[mesh_i].Reset();
|
||||||
|
|
||||||
|
for( unsigned int vertex_i = 0; vertex_i < mesh.m_VertexSize; ++vertex_i )
|
||||||
|
m_meshs_bbox[mesh_i].Union( mesh.m_Positions[vertex_i] );
|
||||||
|
|
||||||
|
// Make sure we start with client state disabled
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
|
glDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
|
||||||
|
|
||||||
|
// Enable arrays client states
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
glEnableClientState( GL_VERTEX_ARRAY );
|
||||||
|
glEnableClientState( GL_NORMAL_ARRAY );
|
||||||
|
|
||||||
|
glVertexPointer( 3, GL_FLOAT, 0, mesh.m_Positions );
|
||||||
|
glNormalPointer( GL_FLOAT, 0, mesh.m_Normals );
|
||||||
|
|
||||||
|
if( mesh.m_Color != NULL )
|
||||||
|
{
|
||||||
|
glEnableClientState( GL_COLOR_ARRAY );
|
||||||
|
glColorPointer( 3, GL_FLOAT, 0, mesh.m_Color );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( mesh.m_Texcoords != NULL )
|
||||||
|
{
|
||||||
|
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
|
glTexCoordPointer( 2, GL_FLOAT, 0, mesh.m_Texcoords );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compile the display list to store triangles
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
glNewList( m_ogl_idx_list_meshes + mesh_i, GL_COMPILE );
|
||||||
|
|
||||||
|
// Set material properties
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
if( mesh.m_Color != NULL )
|
||||||
|
{
|
||||||
|
glEnable( GL_COLOR_MATERIAL );
|
||||||
|
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDisable( GL_COLOR_MATERIAL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||||
|
{
|
||||||
|
OGL_SetMaterial( a3DModel.m_Materials[mesh.m_MaterialIdx] );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw mesh
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
glDrawElements( GL_TRIANGLES, mesh.m_FaceIdxSize, GL_UNSIGNED_INT, mesh.m_FaceIdx );
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
// Disable arrays client states
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||||
|
glDisableClientState( GL_COLOR_ARRAY );
|
||||||
|
glDisableClientState( GL_NORMAL_ARRAY );
|
||||||
|
glDisableClientState( GL_VERTEX_ARRAY );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}// for each mesh
|
||||||
|
|
||||||
|
bool have_opaque_meshes = false;
|
||||||
|
bool have_transparent_meshes = false;
|
||||||
|
|
||||||
|
m_ogl_idx_list_opaque = glGenLists( 1 );
|
||||||
|
|
||||||
|
// Check if the generated list is valid
|
||||||
|
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||||
|
{
|
||||||
|
// Compile the model display list
|
||||||
|
glNewList( m_ogl_idx_list_opaque, GL_COMPILE );
|
||||||
|
|
||||||
|
// Render each mesh display list (opaque first)
|
||||||
|
// /////////////////////////////////////////////////////////////////
|
||||||
|
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||||
|
{
|
||||||
|
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||||
|
|
||||||
|
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||||
|
{
|
||||||
|
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||||
|
|
||||||
|
if( material.m_Transparency == 0.0f )
|
||||||
|
{
|
||||||
|
have_opaque_meshes = true; // Flag that we have at least one opaque mesh
|
||||||
|
glCallList( m_ogl_idx_list_meshes + mesh_i );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
have_transparent_meshes = true; // Flag that we found a transparent mesh
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
|
||||||
|
if( !have_opaque_meshes )
|
||||||
|
{
|
||||||
|
glDeleteLists( m_ogl_idx_list_opaque, 1 ); // If we dont have opaque meshes, we can free the list
|
||||||
|
m_ogl_idx_list_opaque = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( have_transparent_meshes )
|
||||||
|
{
|
||||||
|
m_ogl_idx_list_transparent = glGenLists( 1 );
|
||||||
|
|
||||||
|
// Check if the generated list is valid
|
||||||
|
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||||
|
{
|
||||||
|
// Compile the model display list
|
||||||
|
glNewList( m_ogl_idx_list_transparent, GL_COMPILE );
|
||||||
|
|
||||||
|
// Render each mesh display list (opaque first)
|
||||||
|
// /////////////////////////////////////////////////////////
|
||||||
|
for( unsigned mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||||
|
{
|
||||||
|
const SMESH &mesh = a3DModel.m_Meshes[mesh_i];
|
||||||
|
|
||||||
|
if( mesh.m_MaterialIdx < a3DModel.m_MaterialsSize )
|
||||||
|
{
|
||||||
|
const SMATERIAL &material = a3DModel.m_Materials[mesh.m_MaterialIdx];
|
||||||
|
|
||||||
|
if( material.m_Transparency != 0.0f )
|
||||||
|
glCallList( m_ogl_idx_list_meshes + mesh_i ); // Render the transparent mesh
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glEndList();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ogl_idx_list_transparent = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ogl_idx_list_opaque = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the main bbox
|
||||||
|
// /////////////////////////////////////////////////////////////////////
|
||||||
|
m_model_bbox.Reset();
|
||||||
|
|
||||||
|
for( unsigned int mesh_i = 0; mesh_i < a3DModel.m_MeshesSize; ++mesh_i )
|
||||||
|
m_model_bbox.Union( m_meshs_bbox[mesh_i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C_OGL_3DMODEL::Draw_opaque() const
|
||||||
|
{
|
||||||
|
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||||
|
glCallList( m_ogl_idx_list_opaque );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C_OGL_3DMODEL::Draw_transparent() const
|
||||||
|
{
|
||||||
|
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||||
|
glCallList( m_ogl_idx_list_transparent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
C_OGL_3DMODEL::~C_OGL_3DMODEL()
|
||||||
|
{
|
||||||
|
if( glIsList( m_ogl_idx_list_opaque ) )
|
||||||
|
glDeleteLists( m_ogl_idx_list_opaque, 1 );
|
||||||
|
|
||||||
|
if( glIsList( m_ogl_idx_list_transparent ) )
|
||||||
|
glDeleteLists( m_ogl_idx_list_transparent, 1 );
|
||||||
|
|
||||||
|
if( glIsList( m_ogl_idx_list_meshes ) )
|
||||||
|
glDeleteLists( m_ogl_idx_list_meshes, m_nr_meshes );
|
||||||
|
|
||||||
|
m_ogl_idx_list_meshes = 0;
|
||||||
|
m_ogl_idx_list_opaque = 0;
|
||||||
|
m_ogl_idx_list_transparent = 0;
|
||||||
|
|
||||||
|
delete[] m_meshs_bbox;
|
||||||
|
m_meshs_bbox = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C_OGL_3DMODEL::Draw_bbox() const
|
||||||
|
{
|
||||||
|
OGL_draw_bbox( m_model_bbox );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void C_OGL_3DMODEL::Draw_bboxes() const
|
||||||
|
{
|
||||||
|
for( unsigned int mesh_i = 0; mesh_i < m_nr_meshes; ++mesh_i )
|
||||||
|
OGL_draw_bbox( m_meshs_bbox[mesh_i] );
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Mario Luzeiro <mrluzeiro@ua.pt>
|
||||||
|
* Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors.
|
||||||
|
*
|
||||||
|
* 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 c_ogl_3dmodel.h
|
||||||
|
* @brief implement a legacy 3dmodel render
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _C_OGL_3DMODEL_H_
|
||||||
|
#define _C_OGL_3DMODEL_H_
|
||||||
|
|
||||||
|
#include "3d_rendering/c3dmodel.h"
|
||||||
|
#include "common_ogl/openGL_includes.h"
|
||||||
|
#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h"
|
||||||
|
|
||||||
|
///
|
||||||
|
class GLM_ALIGN(CLASS_ALIGNMENT) C_OGL_3DMODEL
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief C_OGL_3DMODEL - Load a 3d model. This must be called inside a gl context
|
||||||
|
* @param a3DModel: a 3d model data to load.
|
||||||
|
*/
|
||||||
|
C_OGL_3DMODEL( const S3DMODEL &a3DModel );
|
||||||
|
|
||||||
|
~C_OGL_3DMODEL();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw_opaque - render the model into the current context
|
||||||
|
*/
|
||||||
|
void Draw_opaque() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw_transparent - render the model into the current context
|
||||||
|
*/
|
||||||
|
void Draw_transparent() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw_bbox - draw main bounding box of the model
|
||||||
|
*/
|
||||||
|
void Draw_bbox() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw_bboxes - draw individual bounding boxes of each mesh
|
||||||
|
*/
|
||||||
|
void Draw_bboxes() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief GetBBox - Get main bbox
|
||||||
|
* @return the main model bbox
|
||||||
|
*/
|
||||||
|
const CBBOX &GetBBox() const { return m_model_bbox; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint m_ogl_idx_list_opaque; ///< display list for rendering opaque meshes
|
||||||
|
GLuint m_ogl_idx_list_transparent; ///< display list for rendering transparent meshes
|
||||||
|
GLuint m_ogl_idx_list_meshes; ///< display lists for all meshes.
|
||||||
|
unsigned int m_nr_meshes; ///< number of meshes of this model
|
||||||
|
|
||||||
|
CBBOX m_model_bbox; ///< global bounding box for this model
|
||||||
|
CBBOX *m_meshs_bbox; ///< individual bbox for each mesh
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _C_OGL_3DMODEL_H_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue