diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp new file mode 100644 index 0000000000..96cd8c39d2 --- /dev/null +++ b/3d-viewer/3d_cache/3d_cache.cpp @@ -0,0 +1,622 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#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 ); +} diff --git a/3d-viewer/3d_cache/3d_cache.h b/3d-viewer/3d_cache/3d_cache.h new file mode 100644 index 0000000000..1961a4e16c --- /dev/null +++ b/3d-viewer/3d_cache/3d_cache.h @@ -0,0 +1,214 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#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 diff --git a/3d-viewer/3d_cache/3d_cache_wrapper.cpp b/3d-viewer/3d_cache/3d_cache_wrapper.cpp new file mode 100644 index 0000000000..80769d9a5f --- /dev/null +++ b/3d-viewer/3d_cache/3d_cache_wrapper.cpp @@ -0,0 +1,66 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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( cw ); + + // check that we get the expected type of object or NULL + wxASSERT( !cw || cache ); + + if( !cw ) + { + cw = new CACHE_WRAPPER; + cache = dynamic_cast( 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; +} diff --git a/3d-viewer/3d_cache/3d_cache_wrapper.h b/3d-viewer/3d_cache/3d_cache_wrapper.h new file mode 100644 index 0000000000..60051d21af --- /dev/null +++ b/3d-viewer/3d_cache/3d_cache_wrapper.h @@ -0,0 +1,37 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include "3d_cache.h" + +class CACHE_WRAPPER : public S3D_CACHE, public PROJECT::_ELEM +{ +public: + CACHE_WRAPPER(); + virtual ~CACHE_WRAPPER(); +}; + +#endif // CACHE_WRAPPER_3D_H diff --git a/3d-viewer/3d_cache/3d_filename_resolver.cpp b/3d-viewer/3d_cache/3d_filename_resolver.cpp new file mode 100644 index 0000000000..c8ca971e45 --- /dev/null +++ b/3d-viewer/3d_cache/3d_filename_resolver.cpp @@ -0,0 +1,457 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#include + +#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; +} diff --git a/3d-viewer/3d_cache/3d_filename_resolver.h b/3d-viewer/3d_cache/3d_filename_resolver.h new file mode 100644 index 0000000000..d88bc7c760 --- /dev/null +++ b/3d-viewer/3d_cache/3d_filename_resolver.h @@ -0,0 +1,165 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#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 diff --git a/3d-viewer/3d_cache/3d_info.h b/3d-viewer/3d_cache/3d_info.h new file mode 100644 index 0000000000..ad901be95b --- /dev/null +++ b/3d-viewer/3d_cache/3d_info.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * Copyright (C) 2015 Mario Luzeiro + * Copyright (C) 2011 Wayne Stambaugh + * 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 +#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 diff --git a/3d-viewer/3d_cache/3d_plugin_manager.cpp b/3d-viewer/3d_cache/3d_plugin_manager.cpp new file mode 100644 index 0000000000..b90f9e1258 --- /dev/null +++ b/3d-viewer/3d_cache/3d_plugin_manager.cpp @@ -0,0 +1,602 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef _WIN32 + #include +#else + #include + #include +#endif + +#include <3d_plugin_manager.h> +#include +#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; +} diff --git a/3d-viewer/3d_cache/3d_plugin_manager.h b/3d-viewer/3d_cache/3d_plugin_manager.h new file mode 100644 index 0000000000..af03e18375 --- /dev/null +++ b/3d-viewer/3d_cache/3d_plugin_manager.h @@ -0,0 +1,96 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include + +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 diff --git a/3d-viewer/3d_cache/CMakeLists.txt b/3d-viewer/3d_cache/CMakeLists.txt new file mode 100644 index 0000000000..82ed6dec69 --- /dev/null +++ b/3d-viewer/3d_cache/CMakeLists.txt @@ -0,0 +1,3 @@ +# unset CMAKE_CXX_FLAGS because it's contaminated with too many options +set( CMAKE_CXX_FLAGS "" ) +add_subdirectory( sg ) diff --git a/3d-viewer/3d_cache/README b/3d-viewer/3d_cache/README new file mode 100644 index 0000000000..3b2602aaf3 --- /dev/null +++ b/3d-viewer/3d_cache/README @@ -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 *.* diff --git a/3d-viewer/3d_cache/ansidecl.h b/3d-viewer/3d_cache/ansidecl.h new file mode 100644 index 0000000000..f64990fbbf --- /dev/null +++ b/3d-viewer/3d_cache/ansidecl.h @@ -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 and C89 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 */ diff --git a/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.cpp b/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.cpp new file mode 100644 index 0000000000..13e78bc0f6 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.cpp @@ -0,0 +1,72 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include <3d_info.h> +#include <3d_cache.h> +#include + +#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; +} diff --git a/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.h b/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.h new file mode 100644 index 0000000000..4fb3015ed7 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/3d_cache_dialogs.h @@ -0,0 +1,41 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + +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 diff --git a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp new file mode 100644 index 0000000000..0f4f39271c --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.cpp @@ -0,0 +1,257 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#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; +} diff --git a/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h new file mode 100644 index 0000000000..b8efb6b7dc --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/dialog_config_3dpath.h @@ -0,0 +1,62 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include + +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 diff --git a/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.cpp b/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.cpp new file mode 100644 index 0000000000..b9999bc1a0 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.cpp @@ -0,0 +1,119 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.h b/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.h new file mode 100644 index 0000000000..156e8235f1 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/dialog_select_3dmodel.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include + +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 diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp new file mode 100644 index 0000000000..9b2e3e0407 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp @@ -0,0 +1,634 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.h b/3d-viewer/3d_cache/dialogs/panel_prev_model.h new file mode 100644 index 0000000000..72e1c648c4 --- /dev/null +++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.h @@ -0,0 +1,97 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include + +#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 diff --git a/3d-viewer/3d_cache/md5.cpp b/3d-viewer/3d_cache/md5.cpp new file mode 100644 index 0000000000..d42ea0b3e7 --- /dev/null +++ b/3d-viewer/3d_cache/md5.cpp @@ -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 , 1995. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +# include +# include + +#include "ansidecl.h" +#include "md5.h" + +#ifdef __APPLE__ + # include +#elif !defined( _WIN32 ) + # include +#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; +} diff --git a/3d-viewer/3d_cache/md5.h b/3d-viewer/3d_cache/md5.h new file mode 100644 index 0000000000..9e67521b72 --- /dev/null +++ b/3d-viewer/3d_cache/md5.h @@ -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 + +#if defined HAVE_LIMITS_H || _LIBC +# include +#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 +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 ) 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 diff --git a/3d-viewer/3d_cache/sg/CMakeLists.txt b/3d-viewer/3d_cache/sg/CMakeLists.txt new file mode 100644 index 0000000000..d7926c2e86 --- /dev/null +++ b/3d-viewer/3d_cache/sg/CMakeLists.txt @@ -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() diff --git a/3d-viewer/3d_cache/sg/api_sg_node.cpp b/3d-viewer/3d_cache/sg/api_sg_node.cpp new file mode 100644 index 0000000000..6af4099ee5 --- /dev/null +++ b/3d-viewer/3d_cache/sg/api_sg_node.cpp @@ -0,0 +1,149 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/api_sg_transform.cpp b/3d-viewer/3d_cache/sg/api_sg_transform.cpp new file mode 100644 index 0000000000..13dd09e666 --- /dev/null +++ b/3d-viewer/3d_cache/sg/api_sg_transform.cpp @@ -0,0 +1,26 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_all.h b/3d-viewer/3d_cache/sg/ifsg_all.h new file mode 100644 index 0000000000..43471aa229 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_all.h @@ -0,0 +1,38 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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> diff --git a/3d-viewer/3d_cache/sg/ifsg_api.cpp b/3d-viewer/3d_cache/sg/ifsg_api.cpp new file mode 100644 index 0000000000..00e4161748 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_api.cpp @@ -0,0 +1,413 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_api.h b/3d-viewer/3d_cache/sg/ifsg_api.h new file mode 100644 index 0000000000..e7609dc332 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_api.h @@ -0,0 +1,182 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#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 diff --git a/3d-viewer/3d_cache/sg/ifsg_appearance.cpp b/3d-viewer/3d_cache/sg/ifsg_appearance.cpp new file mode 100644 index 0000000000..01f3c9cd21 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_appearance.cpp @@ -0,0 +1,344 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_appearance.h b/3d-viewer/3d_cache/sg/ifsg_appearance.h new file mode 100644 index 0000000000..bdc982e3e0 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_appearance.h @@ -0,0 +1,63 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_colorindex.cpp b/3d-viewer/3d_cache/sg/ifsg_colorindex.cpp new file mode 100644 index 0000000000..51a7181e41 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_colorindex.cpp @@ -0,0 +1,158 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_colorindex.h b/3d-viewer/3d_cache/sg/ifsg_colorindex.h new file mode 100644 index 0000000000..e16023e645 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_colorindex.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_colors.cpp b/3d-viewer/3d_cache/sg/ifsg_colors.cpp new file mode 100644 index 0000000000..520aa937f1 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_colors.cpp @@ -0,0 +1,218 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_colors.h b/3d-viewer/3d_cache/sg/ifsg_colors.h new file mode 100644 index 0000000000..456e34d491 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_colors.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_coordindex.cpp b/3d-viewer/3d_cache/sg/ifsg_coordindex.cpp new file mode 100644 index 0000000000..19aaa7dbe0 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_coordindex.cpp @@ -0,0 +1,158 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_coordindex.h b/3d-viewer/3d_cache/sg/ifsg_coordindex.h new file mode 100644 index 0000000000..604c071a1d --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_coordindex.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_coords.cpp b/3d-viewer/3d_cache/sg/ifsg_coords.cpp new file mode 100644 index 0000000000..6375fdbe1d --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_coords.cpp @@ -0,0 +1,218 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_coords.h b/3d-viewer/3d_cache/sg/ifsg_coords.h new file mode 100644 index 0000000000..14ac6a68bc --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_coords.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_defs.h b/3d-viewer/3d_cache/sg/ifsg_defs.h new file mode 100644 index 0000000000..da06d4b131 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_defs.h @@ -0,0 +1,39 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_faceset.cpp b/3d-viewer/3d_cache/sg/ifsg_faceset.cpp new file mode 100644 index 0000000000..130f412a3f --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_faceset.cpp @@ -0,0 +1,161 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_faceset.h b/3d-viewer/3d_cache/sg/ifsg_faceset.h new file mode 100644 index 0000000000..a94d567212 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_faceset.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_index.cpp b/3d-viewer/3d_cache/sg/ifsg_index.cpp new file mode 100644 index 0000000000..45b777d420 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_index.cpp @@ -0,0 +1,83 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_index.h b/3d-viewer/3d_cache/sg/ifsg_index.h new file mode 100644 index 0000000000..175d2f0009 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_index.h @@ -0,0 +1,71 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_node.cpp b/3d-viewer/3d_cache/sg/ifsg_node.cpp new file mode 100644 index 0000000000..485b3c4e2d --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_node.cpp @@ -0,0 +1,216 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_node.h b/3d-viewer/3d_cache/sg/ifsg_node.h new file mode 100644 index 0000000000..5d5f6203cf --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_node.h @@ -0,0 +1,174 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_normalindex.cpp b/3d-viewer/3d_cache/sg/ifsg_normalindex.cpp new file mode 100644 index 0000000000..9e72e62f1e --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_normalindex.cpp @@ -0,0 +1,158 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_normalindex.h b/3d-viewer/3d_cache/sg/ifsg_normalindex.h new file mode 100644 index 0000000000..35428ef41d --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_normalindex.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_normals.cpp b/3d-viewer/3d_cache/sg/ifsg_normals.cpp new file mode 100644 index 0000000000..5715518bdb --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_normals.cpp @@ -0,0 +1,217 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_normals.h b/3d-viewer/3d_cache/sg/ifsg_normals.h new file mode 100644 index 0000000000..8c92dc75bd --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_normals.h @@ -0,0 +1,57 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_shape.cpp b/3d-viewer/3d_cache/sg/ifsg_shape.cpp new file mode 100644 index 0000000000..106d92ded9 --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_shape.cpp @@ -0,0 +1,162 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 ); +} diff --git a/3d-viewer/3d_cache/sg/ifsg_shape.h b/3d-viewer/3d_cache/sg/ifsg_shape.h new file mode 100644 index 0000000000..57400a31cd --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_shape.h @@ -0,0 +1,52 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/ifsg_transform.cpp b/3d-viewer/3d_cache/sg/ifsg_transform.cpp new file mode 100644 index 0000000000..68fa1223ef --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_transform.cpp @@ -0,0 +1,230 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/ifsg_transform.h b/3d-viewer/3d_cache/sg/ifsg_transform.h new file mode 100644 index 0000000000..8a426d461a --- /dev/null +++ b/3d-viewer/3d_cache/sg/ifsg_transform.h @@ -0,0 +1,61 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/scenegraph.cpp b/3d-viewer/3d_cache/sg/scenegraph.cpp new file mode 100644 index 0000000000..1b7275f9e7 --- /dev/null +++ b/3d-viewer/3d_cache/sg/scenegraph.cpp @@ -0,0 +1,636 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include + +#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; +} diff --git a/3d-viewer/3d_cache/sg/scenegraph.h b/3d-viewer/3d_cache/sg/scenegraph.h new file mode 100644 index 0000000000..ac48188a3f --- /dev/null +++ b/3d-viewer/3d_cache/sg/scenegraph.h @@ -0,0 +1,105 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_api.h b/3d-viewer/3d_cache/sg/sg_api.h new file mode 100644 index 0000000000..be9cd29c71 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_api.h @@ -0,0 +1,172 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/sg_appearance.cpp b/3d-viewer/3d_cache/sg/sg_appearance.cpp new file mode 100644 index 0000000000..1dd95c6ee6 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_appearance.cpp @@ -0,0 +1,347 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include + +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_appearance.h b/3d-viewer/3d_cache/sg/sg_appearance.h new file mode 100644 index 0000000000..43994ff544 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_appearance.h @@ -0,0 +1,76 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/sg_base.cpp b/3d-viewer/3d_cache/sg/sg_base.cpp new file mode 100644 index 0000000000..3122f1284d --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_base.cpp @@ -0,0 +1,325 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_base.h b/3d-viewer/3d_cache/sg/sg_base.h new file mode 100644 index 0000000000..8e9c6fa248 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_base.h @@ -0,0 +1,100 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/sg_colorindex.cpp b/3d-viewer/3d_cache/sg/sg_colorindex.cpp new file mode 100644 index 0000000000..6610bebd2e --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_colorindex.cpp @@ -0,0 +1,42 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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; +} diff --git a/3d-viewer/3d_cache/sg/sg_colorindex.h b/3d-viewer/3d_cache/sg/sg_colorindex.h new file mode 100644 index 0000000000..937b957f9e --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_colorindex.h @@ -0,0 +1,41 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/sg_colors.cpp b/3d-viewer/3d_cache/sg/sg_colors.cpp new file mode 100644 index 0000000000..d58b2206b8 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_colors.cpp @@ -0,0 +1,313 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_colors.h b/3d-viewer/3d_cache/sg/sg_colors.h new file mode 100644 index 0000000000..b23332399e --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_colors.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_coordindex.cpp b/3d-viewer/3d_cache/sg/sg_coordindex.cpp new file mode 100644 index 0000000000..0888cbff4d --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_coordindex.cpp @@ -0,0 +1,43 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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; +} diff --git a/3d-viewer/3d_cache/sg/sg_coordindex.h b/3d-viewer/3d_cache/sg/sg_coordindex.h new file mode 100644 index 0000000000..5813d7caec --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_coordindex.h @@ -0,0 +1,51 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 diff --git a/3d-viewer/3d_cache/sg/sg_coords.cpp b/3d-viewer/3d_cache/sg/sg_coords.cpp new file mode 100644 index 0000000000..9236ca0e1f --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_coords.cpp @@ -0,0 +1,314 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_coords.h b/3d-viewer/3d_cache/sg/sg_coords.h new file mode 100644 index 0000000000..1b263489f1 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_coords.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_faceset.cpp b/3d-viewer/3d_cache/sg/sg_faceset.cpp new file mode 100644 index 0000000000..afae6494f5 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_faceset.cpp @@ -0,0 +1,1032 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include <3d_cache/sg/sg_faceset.h> +#include <3d_cache/sg/sg_colors.h> +#include <3d_cache/sg/sg_coords.h> +#include <3d_cache/sg/sg_normals.h> +#include <3d_cache/sg/sg_colorindex.h> +#include <3d_cache/sg/sg_coordindex.h> +#include <3d_cache/sg/sg_helpers.h> + +SGFACESET::SGFACESET( SGNODE* aParent ) : SGNODE( aParent ) +{ + m_SGtype = S3D::SGTYPE_FACESET; + m_Colors = NULL; + m_ColorIndices = NULL; + m_Coords = NULL; + m_CoordIndices = NULL; + m_Normals = NULL; + m_RColors = NULL; + m_RCoords = NULL; + m_RNormals = NULL; + valid = false; + validated = false; + + 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 SGFACESET (type "; + std::cerr << aParent->GetNodeType() << ")\n"; +#endif + } + else if( NULL != aParent && S3D::SGTYPE_SHAPE == aParent->GetNodeType() ) + { + m_Parent->AddChildNode( this ); + } + + return; +} + + +SGFACESET::~SGFACESET() +{ + // drop references + if( m_RColors ) + { + m_RColors->delNodeRef( this ); + m_RColors = NULL; + } + + if( m_RCoords ) + { + m_RCoords->delNodeRef( this ); + m_RCoords = NULL; + } + + if( m_RNormals ) + { + m_RNormals->delNodeRef( this ); + m_RNormals = NULL; + } + + // delete owned objects + if( m_Colors ) + { + m_Colors->SetParent( NULL, false ); + delete m_Colors; + m_Colors = NULL; + } + + if( m_Coords ) + { + m_Coords->SetParent( NULL, false ); + delete m_Coords; + m_Coords = NULL; + } + + if( m_Normals ) + { + m_Normals->SetParent( NULL, false ); + delete m_Normals; + m_Normals = NULL; + } + + if( m_ColorIndices ) + { + m_ColorIndices->SetParent( NULL, false ); + delete m_ColorIndices; + m_ColorIndices = NULL; + } + + if( m_CoordIndices ) + { + m_CoordIndices->SetParent( NULL, false ); + delete m_CoordIndices; + m_CoordIndices = NULL; + } + + return; +} + + +bool SGFACESET::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 SGFACESET + if( NULL != aParent && S3D::SGTYPE_SHAPE != aParent->GetNodeType() ) + return false; + + m_Parent = aParent; + + if( m_Parent ) + m_Parent->AddChildNode( this ); + + return true; +} + + +SGNODE* SGFACESET::FindNode(const char *aNodeName, const SGNODE *aCaller) +{ + if( NULL == aNodeName || 0 == aNodeName[0] ) + return NULL; + + if( !m_Name.compare( aNodeName ) ) + return this; + + SGNODE* np = NULL; + + if( m_Colors ) + { + np = m_Colors->FindNode( aNodeName, this ); + + if( np ) + return np; + } + + if( m_ColorIndices ) + { + np = m_ColorIndices->FindNode( aNodeName, this ); + + if( np ) + return np; + } + + if( m_Coords ) + { + np = m_Coords->FindNode( aNodeName, this ); + + if( np ) + return np; + } + + if( m_CoordIndices ) + { + np = m_CoordIndices->FindNode( aNodeName, this ); + + if( np ) + return np; + } + + if( m_Normals ) + { + np = m_Normals->FindNode( aNodeName, this ); + + if( np ) + return np; + } + + // query the parent if appropriate + if( aCaller == m_Parent || NULL == m_Parent ) + return NULL; + + return m_Parent->FindNode( aNodeName, this ); +} + + +void SGFACESET::unlinkNode( const SGNODE* aNode, bool isChild ) +{ + if( NULL == aNode ) + return; + + valid = false; + validated = false; + + if( isChild ) + { + if( aNode == m_Colors ) + { + m_Colors = NULL; + return; + } + + if( aNode == m_Coords ) + { + m_Coords = NULL; + return; + } + + if( aNode == m_Normals ) + { + m_Normals = NULL; + return; + } + + if( aNode == m_ColorIndices ) + { + m_ColorIndices = NULL; + return; + } + + if( aNode == m_CoordIndices ) + { + m_CoordIndices = NULL; + return; + } + } + else + { + if( aNode == m_RColors ) + { + m_RColors = NULL; + return; + } + + if( aNode == m_RCoords ) + { + m_RCoords = NULL; + return; + } + + if( aNode == m_RNormals ) + { + m_RNormals = NULL; + return; + } + } + + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] unlinkNode() did not find its target\n"; + + return; +} + + +void SGFACESET::unlinkChildNode( const SGNODE* aNode ) +{ + unlinkNode( aNode, true ); + return; +} + + +void SGFACESET::unlinkRefNode( const SGNODE* aNode ) +{ + unlinkNode( aNode, false ); + return; +} + + + +bool SGFACESET::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; + } + + valid = false; + validated = false; + + if( S3D::SGTYPE_COLORS == aNode->GetNodeType() ) + { + if( m_Colors || m_RColors ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] assigning multiple Colors nodes\n"; + return false; + } + + if( isChild ) + { + m_Colors = (SGCOLORS*)aNode; + m_Colors->SetParent( this ); + } + else + { + m_RColors = (SGCOLORS*)aNode; + m_RColors->addNodeRef( this ); + } + + return true; + } + + if( S3D::SGTYPE_COORDS == aNode->GetNodeType() ) + { + if( m_Coords || m_RCoords ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] assigning multiple Coords nodes\n"; + return false; + } + + if( isChild ) + { + m_Coords = (SGCOORDS*)aNode; + m_Coords->SetParent( this ); + } + else + { + m_RCoords = (SGCOORDS*)aNode; + m_RCoords->addNodeRef( this ); + } + + return true; + } + + if( S3D::SGTYPE_NORMALS == aNode->GetNodeType() ) + { + if( m_Normals || m_RNormals ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] assigning multiple Normals nodes\n"; + return false; + } + + if( isChild ) + { + m_Normals = (SGNORMALS*)aNode; + m_Normals->SetParent( this ); + } + else + { + m_RNormals = (SGNORMALS*)aNode; + m_RNormals->addNodeRef( this ); + } + + return true; + } + + if( S3D::SGTYPE_COLORINDEX == aNode->GetNodeType() ) + { + if( m_ColorIndices ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] assigning multiple ColorIndex nodes\n"; + return false; + } + + m_ColorIndices = (SGCOLORINDEX*)aNode; + m_ColorIndices->SetParent( this ); + + return true; + } + + if( S3D::SGTYPE_COORDINDEX == aNode->GetNodeType() ) + { + if( m_CoordIndices ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] assigning multiple CoordIndex nodes\n"; + return false; + } + + m_CoordIndices = (SGCOORDINDEX*)aNode; + m_CoordIndices->SetParent( this ); + + return true; + } + + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] object '" << aNode->GetName(); + std::cerr << "' (type " << aNode->GetNodeType(); + std::cerr << ") is not a valid type for this object (" << aNode->GetNodeType() << ")\n"; + + return false; +} + + +bool SGFACESET::AddRefNode( SGNODE* aNode ) +{ + return addNode( aNode, false ); +} + + +bool SGFACESET::AddChildNode( SGNODE* aNode ) +{ + return addNode( aNode, true ); +} + + +void SGFACESET::ReNameNodes( void ) +{ + m_written = false; + + // rename this node + m_Name.clear(); + GetName(); + + // rename all Colors and Indices + if( m_Colors ) + m_Colors->ReNameNodes(); + + if( m_ColorIndices ) + m_ColorIndices->ReNameNodes(); + + // rename all Coordinates and Indices + if( m_Coords ) + m_Coords->ReNameNodes(); + + if( m_CoordIndices ) + m_CoordIndices->ReNameNodes(); + + // rename all Normals and Indices + if( m_Normals ) + m_Normals->ReNameNodes(); + + return; +} + + +bool SGFACESET::WriteVRML( std::ofstream& aFile, bool aReuseFlag ) +{ + if( ( NULL == m_Coords && NULL == m_RCoords ) + || ( NULL == m_CoordIndices ) ) + { + return false; + } + + std::string tmp; + + if( aReuseFlag ) + { + if( !m_written ) + { + aFile << " geometry DEF " << GetName() << " IndexedFaceSet {\n"; + m_written = true; + } + else + { + aFile << "USE " << GetName() << "\n"; + return true; + } + } + else + { + aFile << " geometry IndexedFaceSet {\n"; + } + + if( m_Coords ) + m_Coords->WriteVRML( aFile, aReuseFlag ); + + if( m_RCoords ) + m_RCoords->WriteVRML( aFile, aReuseFlag ); + + if( m_CoordIndices ) + m_CoordIndices->WriteVRML( aFile, aReuseFlag ); + + if( m_Normals || m_RNormals ) + aFile << " normalPerVertex TRUE\n"; + + if( m_Normals ) + m_Normals->WriteVRML( aFile, aReuseFlag ); + + if( m_RNormals ) + m_RNormals->WriteVRML( aFile, aReuseFlag ); + + if( m_Colors ) + m_Colors->WriteVRML( aFile, aReuseFlag ); + + if( m_RColors ) + m_RColors->WriteVRML( aFile, aReuseFlag ); + + if( m_ColorIndices ) + m_ColorIndices->WriteVRML( aFile, aReuseFlag ); + + aFile << "}\n"; + + return true; +} + + +bool SGFACESET::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 8 + bool items[NITEMS]; + int i; + + for( i = 0; i < NITEMS; ++i ) + items[i] = 0; + + i = 0; + if( NULL != m_Coords ) + items[i] = true; + + ++i; + if( NULL != m_RCoords ) + items[i] = true; + + ++i; + if( NULL != m_CoordIndices ) + items[i] = true; + + ++i; + if( NULL != m_Normals ) + items[i] = true; + + ++i; + if( NULL != m_RNormals ) + items[i] = true; + + ++i; + if( NULL != m_Colors ) + items[i] = true; + + ++i; + if( NULL != m_RColors ) + items[i] = true; + + ++i; + if( NULL != m_ColorIndices ) + items[i] = true; + + for( int i = 0; i < NITEMS; ++i ) + aFile.write( (char*)&items[i], sizeof(bool) ); + + if( items[0] ) + m_Coords->WriteCache( aFile, this ); + + if( items[1] ) + aFile << "[" << m_RCoords->GetName() << "]"; + + if( items[2] ) + m_CoordIndices->WriteCache( aFile, this ); + + if( items[3] ) + m_Normals->WriteCache( aFile, this ); + + if( items[4] ) + aFile << "[" << m_RNormals->GetName() << "]"; + + if( items[5] ) + m_Colors->WriteCache( aFile, this ); + + if( items[6] ) + aFile << "[" << m_RColors->GetName() << "]"; + + if( items[7] ) + m_ColorIndices->WriteCache( aFile, this ); + + if( aFile.fail() ) + return false; + + return true; +} + + +bool SGFACESET::ReadCache( std::ifstream& aFile, SGNODE* parentNode ) +{ + if( m_Coords || m_RCoords || m_CoordIndices + || m_Colors || m_RColors || m_ColorIndices + || m_Normals || m_RNormals ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [BUG] non-empty node\n"; + return false; + } + + #define NITEMS 8 + bool items[NITEMS]; + + for( int i = 0; i < NITEMS; ++i ) + aFile.read( (char*)&items[i], sizeof(bool) ); + + if( ( items[0] && items[1] ) || ( items[3] && items[4] ) + || ( items[5] && items[6] ) ) + { + 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_COORDS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad child coords tag at position "; + std::cerr << aFile.tellg() << "\n"; + return false; + } + + m_Coords = new SGCOORDS( this ); + m_Coords->SetName( name.c_str() ); + + if( !m_Coords->ReadCache( aFile, this ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data while reading coords '"; + std::cerr << name << "'\n"; + return false; + } + } + + if( items[1] ) + { + if( S3D::SGTYPE_COORDS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad ref coords 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 coords '"; + std::cerr << name << "'\n"; + return false; + } + + if( S3D::SGTYPE_COORDS != np->GetNodeType() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data: type is not SGCOORDS '"; + std::cerr << name << "'\n"; + return false; + } + + m_RCoords = (SGCOORDS*)np; + m_RCoords->addNodeRef( this ); + } + + if( items[2] ) + { + if( S3D::SGTYPE_COORDINDEX != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad coord index tag at position "; + std::cerr << aFile.tellg() << "\n"; + return false; + } + + m_CoordIndices = new SGCOORDINDEX( this ); + m_CoordIndices->SetName( name.c_str() ); + + if( !m_CoordIndices->ReadCache( aFile, this ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data while reading coord index '"; + std::cerr << name << "'\n"; + return false; + } + } + + if( items[3] ) + { + if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad child normals tag at position "; + std::cerr << aFile.tellg() << "\n"; + return false; + } + + m_Normals = new SGNORMALS( this ); + m_Normals->SetName( name.c_str() ); + + if( !m_Normals->ReadCache( aFile, this ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data while reading normals '"; + std::cerr << name << "'\n"; + return false; + } + } + + if( items[4] ) + { + if( S3D::SGTYPE_NORMALS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad ref normals 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 normals '"; + std::cerr << name << "'\n"; + return false; + } + + if( S3D::SGTYPE_NORMALS != np->GetNodeType() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data: type is not SGNORMALS '"; + std::cerr << name << "'\n"; + return false; + } + + m_RNormals = (SGNORMALS*)np; + m_RNormals->addNodeRef( this ); + } + + if( items[5] ) + { + if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad child colors tag at position "; + std::cerr << aFile.tellg() << "\n"; + return false; + } + + m_Colors = new SGCOLORS( this ); + m_Colors->SetName( name.c_str() ); + + if( !m_Colors->ReadCache( aFile, this ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data while reading colors '"; + std::cerr << name << "'\n"; + return false; + } + } + + if( items[6] ) + { + if( S3D::SGTYPE_COLORS != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad ref colors 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 colors '"; + std::cerr << name << "'\n"; + return false; + } + + if( S3D::SGTYPE_COLORS != np->GetNodeType() ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data: type is not SGCOLORS '"; + std::cerr << name << "'\n"; + return false; + } + + m_RColors = (SGCOLORS*)np; + m_RColors->addNodeRef( this ); + } + + if( items[7] ) + { + if( S3D::SGTYPE_COLORINDEX != S3D::ReadTag( aFile, name ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data; bad color index tag at position "; + std::cerr << aFile.tellg() << "\n"; + return false; + } + + m_ColorIndices = new SGCOLORINDEX( this ); + m_ColorIndices->SetName( name.c_str() ); + + if( !m_ColorIndices->ReadCache( aFile, this ) ) + { + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] corrupt data while reading color index '"; + std::cerr << name << "'\n"; + return false; + } + } + + if( aFile.fail() ) + return false; + + return true; +} + + +bool SGFACESET::validate( void ) +{ + // verify the integrity of this object's data + if( validated ) + return valid; + + // ensure we have at least coordinates and their normals + if( (NULL == m_Coords && NULL == m_RCoords) + || (NULL == m_Normals && NULL == m_RNormals) + || (NULL == m_CoordIndices) ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; no vertices, vertex indices, or normals\n"; +#endif + validated = true; + valid = false; + return false; + } + + // check that there are >3 vertices + SGCOORDS* coords = m_Coords; + + if( NULL == coords ) + coords = m_RCoords; + + size_t nCoords = 0; + SGPOINT* lCoords = NULL; + coords->GetCoordsList( nCoords, lCoords ); + + if( nCoords < 3 ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; fewer than 3 vertices\n"; +#endif + validated = true; + valid = false; + return false; + } + + // check that nVertices is divisible by 3 (facets are triangles) + size_t nCIdx = 0; + int* lCIdx = NULL; + m_CoordIndices->GetIndices( nCIdx, lCIdx ); + + if( nCIdx < 3 || ( nCIdx % 3 > 0 ) ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; no vertex indices or not multiple of 3\n"; +#endif + validated = true; + valid = false; + return false; + } + + // check that vertex[n] >= 0 and < nVertices + for( size_t i = 0; i < nCIdx; ++i ) + { + if( lCIdx[i] < 0 || lCIdx[i] >= nCoords ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; vertex index out of bounds\n"; +#endif + validated = true; + valid = false; + return false; + } + } + + // check that there are as many normals as vertices + size_t nNorms = 0; + SGVECTOR* lNorms = NULL; + SGNORMALS* pNorms = m_Normals; + + if( NULL == pNorms ) + pNorms = m_RNormals; + + pNorms->GetNormalList( nNorms, lNorms ); + + if( nNorms != nCoords ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; number of normals does not match number of vertices\n"; +#endif + validated = true; + valid = false; + return false; + } + + // if there are colors then ensure there are as many colors as vertices + SGCOLORS* pColors = m_Colors; + + if( NULL == pColors ) + pColors = m_RColors; + + if( NULL != pColors ) + { + if( NULL == m_ColorIndices ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; no color indices\n"; +#endif + validated = true; + valid = false; + return false; + } + + // we must have at least 1 color in the list + size_t nColor = 0; + SGCOLOR* pColor = NULL; + pColors->GetColorList( nColor, pColor ); + + if( nColor < 1 ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; no colors\n"; +#endif + validated = true; + valid = false; + return false; + } + + size_t nCLIdx = 0; + int* pCLIdx = NULL; + m_ColorIndices->GetIndices( nCLIdx, pCLIdx ); + + if( nCLIdx != nCoords ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; color indices do not match number of vertices\n"; +#endif + validated = true; + valid = false; + return false; + } + + // check that color[n] >= 0 and < nColors + for( size_t i = 0; i < nCLIdx; ++i ) + { + if( pCLIdx[i] < 0 || pCLIdx[i] >= nCLIdx ) + { +#ifdef DEBUG + std::cerr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n"; + std::cerr << " * [INFO] bad model; color index out of bounds\n"; +#endif + validated = true; + valid = false; + return false; + } + } + } + + validated = true; + valid = true; + return true; +} diff --git a/3d-viewer/3d_cache/sg/sg_faceset.h b/3d-viewer/3d_cache/sg/sg_faceset.h new file mode 100644 index 0000000000..fa21ef3bb1 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_faceset.h @@ -0,0 +1,112 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_helpers.cpp b/3d-viewer/3d_cache/sg/sg_helpers.cpp new file mode 100644 index 0000000000..a738b5adf9 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_helpers.cpp @@ -0,0 +1,306 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_helpers.h b/3d-viewer/3d_cache/sg/sg_helpers.h new file mode 100644 index 0000000000..14309181dd --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_helpers.h @@ -0,0 +1,209 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#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 diff --git a/3d-viewer/3d_cache/sg/sg_index.cpp b/3d-viewer/3d_cache/sg/sg_index.cpp new file mode 100644 index 0000000000..076c5fb8d8 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_index.cpp @@ -0,0 +1,342 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_index.h b/3d-viewer/3d_cache/sg/sg_index.h new file mode 100644 index 0000000000..a82ed9eff2 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_index.h @@ -0,0 +1,98 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_node.cpp b/3d-viewer/3d_cache/sg/sg_node.cpp new file mode 100644 index 0000000000..dc1054c4a5 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_node.cpp @@ -0,0 +1,367 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_node.h b/3d-viewer/3d_cache/sg/sg_node.h new file mode 100644 index 0000000000..264602f384 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_node.h @@ -0,0 +1,229 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#include +#include +#include +#include + +#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 diff --git a/3d-viewer/3d_cache/sg/sg_normals.cpp b/3d-viewer/3d_cache/sg/sg_normals.cpp new file mode 100644 index 0000000000..cab5729c42 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_normals.cpp @@ -0,0 +1,314 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_normals.h b/3d-viewer/3d_cache/sg/sg_normals.h new file mode 100644 index 0000000000..777ae80676 --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_normals.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_shape.cpp b/3d-viewer/3d_cache/sg/sg_shape.cpp new file mode 100644 index 0000000000..71db77528d --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_shape.cpp @@ -0,0 +1,748 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#include +#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; +} diff --git a/3d-viewer/3d_cache/sg/sg_shape.h b/3d-viewer/3d_cache/sg/sg_shape.h new file mode 100644 index 0000000000..8239c7232c --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_shape.h @@ -0,0 +1,85 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 +#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 diff --git a/3d-viewer/3d_cache/sg/sg_types.h b/3d-viewer/3d_cache/sg/sg_types.h new file mode 100644 index 0000000000..5a4dc6e4be --- /dev/null +++ b/3d-viewer/3d_cache/sg/sg_types.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 diff --git a/3d-viewer/3d_cache/str_rsort.h b/3d-viewer/3d_cache/str_rsort.h new file mode 100644 index 0000000000..13c00e05fb --- /dev/null +++ b/3d-viewer/3d_cache/str_rsort.h @@ -0,0 +1,87 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Cirilo Bernardo + * + * 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 + +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 diff --git a/3d-viewer/3d_cache/testmd5.cpp b/3d-viewer/3d_cache/testmd5.cpp new file mode 100644 index 0000000000..027ba93956 --- /dev/null +++ b/3d-viewer/3d_cache/testmd5.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#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; +} \ No newline at end of file diff --git a/3d-viewer/3d_canvas.h b/3d-viewer/3d_canvas.h index f3cd5d4d24..1f1ff5dd9c 100644 --- a/3d-viewer/3d_canvas.h +++ b/3d-viewer/3d_canvas.h @@ -45,7 +45,7 @@ #include <3d_struct.h> #include #include -#include +#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h" class BOARD_DESIGN_SETTINGS; class EDA_3D_FRAME; diff --git a/3d-viewer/3d_canvas/cinfo3d_visu.h b/3d-viewer/3d_canvas/cinfo3d_visu.h new file mode 100644 index 0000000000..aff2491070 --- /dev/null +++ b/3d-viewer/3d_canvas/cinfo3d_visu.h @@ -0,0 +1,376 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 +#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 +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * 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 diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index ba0a2bab3d..2937dd7047 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -45,7 +45,7 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include #include #ifdef __WINDOWS__ #include // must be included before gl.h @@ -1128,16 +1128,24 @@ void EDA_3D_CANVAS::render3DComponentShape( MODULE* module, shape3D->Render( aIsRenderingJustNonTransparentObjects, 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 - float currentColor[4]; - glGetFloatv( GL_CURRENT_COLOR,currentColor ); - currentColor[3] = 1.0f; - glColor4fv( currentColor ); + if( isEnabled( FL_RENDER_SHOW_MODEL_BBOX ) ) + { + // Set the alpha current color to opaque + float currentColor[4]; + glGetFloatv( GL_CURRENT_COLOR,currentColor ); + currentColor[3] = 1.0f; + glColor4fv( currentColor ); - CBBOX thisBBox = shape3D->getBBox(); - thisBBox.GLdebug(); + CBBOX thisBBox = shape3D->getBBox(); + thisBBox.GLdebug(); + } } glPopMatrix(); diff --git a/3d-viewer/3d_draw_board_body.cpp b/3d-viewer/3d_draw_board_body.cpp index 37d985826e..62251fdd40 100644 --- a/3d-viewer/3d_draw_board_body.cpp +++ b/3d-viewer/3d_draw_board_body.cpp @@ -45,7 +45,7 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include #include #ifdef __WINDOWS__ #include // must be included before gl.h diff --git a/3d-viewer/3d_material.h b/3d-viewer/3d_material.h index bee9e85253..3bff7e600c 100644 --- a/3d-viewer/3d_material.h +++ b/3d-viewer/3d_material.h @@ -32,7 +32,7 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include class S3D_MASTER; diff --git a/3d-viewer/3d_math/3d_fastmath.h b/3d-viewer/3d_math/3d_fastmath.h new file mode 100644 index 0000000000..683082b302 --- /dev/null +++ b/3d-viewer/3d_math/3d_fastmath.h @@ -0,0 +1,138 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 +#include +#include + + +// 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 diff --git a/3d-viewer/3d_math/3d_math.h b/3d-viewer/3d_math/3d_math.h new file mode 100644 index 0000000000..af3ca2a5b7 --- /dev/null +++ b/3d-viewer/3d_math/3d_math.h @@ -0,0 +1,125 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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() * 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 diff --git a/3d-viewer/3d_mesh_model.cpp b/3d-viewer/3d_mesh_model.cpp index 41906e6dd7..04dcdbb4a4 100644 --- a/3d-viewer/3d_mesh_model.cpp +++ b/3d-viewer/3d_mesh_model.cpp @@ -31,8 +31,8 @@ #include <3d_mesh_model.h> #include #define GLM_FORCE_RADIANS -#include -#include +#include +#include #ifdef __WXMAC__ # ifdef __DARWIN__ diff --git a/3d-viewer/3d_mesh_model.h b/3d-viewer/3d_mesh_model.h index 85777f02bb..734789fbd6 100644 --- a/3d-viewer/3d_mesh_model.h +++ b/3d-viewer/3d_mesh_model.h @@ -34,10 +34,10 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include #include "3d_struct.h" #include "3d_material.h" -#include "CBBox.h" +#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h" class S3D_MESH; diff --git a/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp new file mode 100644 index 0000000000..2899c0dc70 --- /dev/null +++ b/3d-viewer/3d_model_viewer/c3d_model_viewer.cpp @@ -0,0 +1,436 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 +#include "c3d_model_viewer.h" +#include "3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h" +#include "common_ogl/ogl_utils.h" +#include + +/** + * 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 ) +{ + +} + diff --git a/3d-viewer/3d_model_viewer/c3d_model_viewer.h b/3d-viewer/3d_model_viewer/c3d_model_viewer.h new file mode 100644 index 0000000000..690dfd886e --- /dev/null +++ b/3d-viewer/3d_model_viewer/c3d_model_viewer.h @@ -0,0 +1,131 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 + + +/** + * 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_ diff --git a/3d-viewer/3d_read_mesh.cpp b/3d-viewer/3d_read_mesh.cpp index dcebd4b7cb..af269ce979 100644 --- a/3d-viewer/3d_read_mesh.cpp +++ b/3d-viewer/3d_read_mesh.cpp @@ -34,7 +34,7 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include #include <3d_viewer.h> #include #include "3d_struct.h" diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp new file mode 100644 index 0000000000..fec8dbda51 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp @@ -0,0 +1,816 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 + +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(*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(ii->first); + + if( !m_settings.Is3DLayerEnabled( layer_id ) ) + continue; + + const CBVHCONTAINER2D *container2d = static_cast(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(*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 *object2d_B = CSGITEM_EMPTY; + + if( m_settings.GetFlag( FL_RENDER_SHOW_HOLES_IN_ZONES ) ) + { + object2d_B = new std::vector(); + + // 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(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(*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(*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 ) ); +} diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp new file mode 100644 index 0000000000..555c16eb61 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp @@ -0,0 +1,723 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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(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(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(ii->second); + delete pointer; + } + + m_triangles.clear(); + + delete m_ogl_disp_list_board; + m_ogl_disp_list_board = 0; +} diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h new file mode 100644 index 0000000000..2bdd331548 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.h @@ -0,0 +1,80 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 + + +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_ diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp new file mode 100644 index 0000000000..cd6b4e06f2 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp @@ -0,0 +1,281 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 + + +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] ); +} diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h new file mode 100644 index 0000000000..26ba5a8e8e --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.h @@ -0,0 +1,85 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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_ diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.cpp new file mode 100644 index 0000000000..a69712a387 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.cpp @@ -0,0 +1,441 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 clayer_triangles.cpp + * @brief + */ + + +#include "clayer_triangles.h" +#include // For the wxASSERT + + +CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER(unsigned int aNrReservedTriangles, bool aReserveNormals) +{ + wxASSERT( aNrReservedTriangles > 0 ); + + m_vertexs.clear(); + m_normals.clear(); + + m_vertexs.reserve( aNrReservedTriangles * 3 ); + + if( aReserveNormals ) + m_normals.reserve( aNrReservedTriangles * 3 ); +} + + +void CLAYER_TRIANGLE_CONTAINER::AddQuad( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4 ) +{ + m_vertexs.push_back( aV1 ); + m_vertexs.push_back( aV2 ); + m_vertexs.push_back( aV3 ); + + m_vertexs.push_back( aV3 ); + m_vertexs.push_back( aV4 ); + m_vertexs.push_back( aV1 ); +} + + +void CLAYER_TRIANGLE_CONTAINER::AddTriangle( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3 ) +{ + m_vertexs.push_back( aV1 ); + m_vertexs.push_back( aV2 ); + m_vertexs.push_back( aV3 ); +} + + +void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3 ) +{ + m_normals.push_back( aN1 ); + m_normals.push_back( aN2 ); + m_normals.push_back( aN3 ); +} + +void CLAYER_TRIANGLE_CONTAINER::AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3, const SFVEC3F &aN4 ) +{ + m_normals.push_back( aN1 ); + m_normals.push_back( aN2 ); + m_normals.push_back( aN3 ); + + m_normals.push_back( aN3 ); + m_normals.push_back( aN4 ); + m_normals.push_back( aN1 ); +} + + +CLAYER_TRIANGLES::CLAYER_TRIANGLES( unsigned int aNrReservedTriangles ) +{ + wxASSERT( aNrReservedTriangles > 0 ); + + m_layer_top_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false ); + m_layer_top_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false ); + m_layer_middle_contourns_quads = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, true ); + m_layer_bot_triangles = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false ); + m_layer_bot_segment_ends = new CLAYER_TRIANGLE_CONTAINER( aNrReservedTriangles, false ); +} + + +CLAYER_TRIANGLES::~CLAYER_TRIANGLES() +{ + delete m_layer_top_segment_ends; + m_layer_top_segment_ends = 0; + + delete m_layer_top_triangles; + m_layer_top_triangles = 0; + + delete m_layer_middle_contourns_quads; + m_layer_middle_contourns_quads = 0; + + delete m_layer_bot_triangles; + m_layer_bot_triangles = 0; + + delete m_layer_bot_segment_ends; + m_layer_bot_segment_ends = 0; +} + + +CLAYERS_OGL_DISP_LISTS::CLAYERS_OGL_DISP_LISTS(const CLAYER_TRIANGLES &aLayerTriangles, + GLuint aTextureIndexForSegEnds, + const SFVEC3F& aLayerColor ) +{ + wxASSERT( glIsTexture( aTextureIndexForSegEnds ) ); + + m_layer_top_segment_ends = 0; + m_layer_top_triangles = 0; + m_layer_middle_contourns_quads = 0; + m_layer_bot_triangles = 0; + m_layer_bot_segment_ends = 0; + + m_layer_top_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_top_segment_ends, aLayerColor, true, aTextureIndexForSegEnds ); + m_layer_top_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_top_triangles, aLayerColor, true ); + m_layer_bot_triangles = generate_top_or_bot_triangles( aLayerTriangles.m_layer_bot_triangles, aLayerColor, false ); + m_layer_bot_segment_ends = generate_top_or_bot_seg_ends( aLayerTriangles.m_layer_bot_segment_ends, aLayerColor, false, aTextureIndexForSegEnds ); + + m_layer_middle_contourns_quads = generate_middle_triangles( aLayerTriangles.m_layer_middle_contourns_quads, aLayerColor ); +} + + +CLAYERS_OGL_DISP_LISTS::~CLAYERS_OGL_DISP_LISTS() +{ + if( glIsList( m_layer_top_segment_ends ) ) + glDeleteLists( m_layer_top_segment_ends, 1 ); + + if( glIsList( m_layer_top_triangles ) ) + glDeleteLists( m_layer_top_triangles, 1 ); + + if( glIsList( m_layer_middle_contourns_quads ) ) + glDeleteLists( m_layer_middle_contourns_quads, 1 ); + + if( glIsList( m_layer_bot_triangles ) ) + glDeleteLists( m_layer_bot_triangles, 1 ); + + if( glIsList( m_layer_bot_segment_ends ) ) + glDeleteLists( m_layer_bot_segment_ends, 1 ); +} + + +void CLAYERS_OGL_DISP_LISTS::DrawTopAndMiddle() const +{ + if( glIsList( m_layer_top_triangles ) ) + glCallList( m_layer_top_triangles ); + + if( glIsList( m_layer_middle_contourns_quads ) ) + glCallList( m_layer_middle_contourns_quads ); + + if( glIsList( m_layer_top_segment_ends ) ) + glCallList( m_layer_top_segment_ends ); + +} + + +void CLAYERS_OGL_DISP_LISTS::DrawBotAndMiddle() const +{ + if( glIsList( m_layer_bot_triangles ) ) + glCallList( m_layer_bot_triangles ); + + if( glIsList( m_layer_middle_contourns_quads ) ) + glCallList( m_layer_middle_contourns_quads ); + + if( glIsList( m_layer_bot_segment_ends ) ) + glCallList( m_layer_bot_segment_ends ); + +} + + +void CLAYERS_OGL_DISP_LISTS::DrawTop() const +{ + if( glIsList( m_layer_top_triangles ) ) + glCallList( m_layer_top_triangles ); + + if( glIsList( m_layer_top_segment_ends ) ) + glCallList( m_layer_top_segment_ends ); +} + + +void CLAYERS_OGL_DISP_LISTS::DrawBot() const +{ + if( glIsList( m_layer_bot_triangles ) ) + glCallList( m_layer_bot_triangles ); + + if( glIsList( m_layer_bot_segment_ends ) ) + glCallList( m_layer_bot_segment_ends ); +} + + +void CLAYERS_OGL_DISP_LISTS::DrawMiddle() const +{ + if( glIsList( m_layer_middle_contourns_quads ) ) + glCallList( m_layer_middle_contourns_quads ); +} + + +void CLAYERS_OGL_DISP_LISTS::DrawAll() const +{ + + if( glIsList( m_layer_top_triangles ) ) + glCallList( m_layer_top_triangles ); + + if( glIsList( m_layer_middle_contourns_quads ) ) + glCallList( m_layer_middle_contourns_quads ); + + if( glIsList( m_layer_bot_triangles ) ) + glCallList( m_layer_bot_triangles ); + + if( glIsList( m_layer_top_segment_ends ) ) + glCallList( m_layer_top_segment_ends ); + + if( glIsList( m_layer_bot_segment_ends ) ) + glCallList( m_layer_bot_segment_ends ); + +} + + +GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_seg_ends(const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor, bool aIsNormalUp, GLuint aTextureId ) const +{ + wxASSERT( aTriangleContainer != NULL ); + + wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 ); + + wxASSERT( aTriangleContainer->GetNormalsSize() == 0 ); + + if( (aTriangleContainer->GetVertexSize() > 0) && + ((aTriangleContainer->GetVertexSize() % 3) == 0) ) + { + GLuint listIdx = glGenLists( 1 ); + + if( glIsList( listIdx ) ) + { + // Prepare an array of UV text coordinates + SFVEC2F *uvArray = new SFVEC2F[aTriangleContainer->GetVertexSize()]; + + for( unsigned int i = 0; i < aTriangleContainer->GetVertexSize(); i += 3 ) + { + uvArray[i + 0] = SFVEC2F( 1.0f, 0.0f ); + uvArray[i + 1] = SFVEC2F( 0.0f, 1.0f ); + uvArray[i + 2] = SFVEC2F( 0.0f, 0.0f ); + } + + glEnableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState( GL_COLOR_ARRAY ); + glDisableClientState( GL_NORMAL_ARRAY ); + glEnableClientState( GL_VERTEX_ARRAY ); + glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); + glTexCoordPointer( 2, GL_FLOAT, 0, uvArray ); + + glNewList( listIdx, GL_COMPILE ); + + glEnable( GL_TEXTURE_2D ); + glBindTexture( GL_TEXTURE_2D, aTextureId ); + + glAlphaFunc( GL_GREATER, 0.60f ); + glEnable( GL_ALPHA_TEST ); + + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + //SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + //glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x ); + //glDisable( GL_COLOR_MATERIAL ); + glEnable( GL_COLOR_MATERIAL ); + glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + + // OGL_SetMaterial() + glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f ); + + glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() ); + + glDisable( GL_TEXTURE_2D ); + glDisable( GL_ALPHA_TEST ); + glDisable( GL_BLEND ); + glDisable( GL_COLOR_MATERIAL ); + + glEndList(); + + glDisableClientState( GL_VERTEX_ARRAY ); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + delete uvArray; + return listIdx; + } + } + + return 0; +} + + +GLuint CLAYERS_OGL_DISP_LISTS::generate_top_or_bot_triangles(const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor , bool aIsNormalUp) const +{ + wxASSERT( aTriangleContainer != NULL ); + + wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 ); + + wxASSERT( aTriangleContainer->GetNormalsSize() == 0 ); + + if( (aTriangleContainer->GetVertexSize() > 0) && + ((aTriangleContainer->GetVertexSize() % 3) == 0) ) + { + GLuint listIdx = glGenLists( 1 ); + + if( glIsList( listIdx ) ) + { + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState( GL_COLOR_ARRAY ); + glDisableClientState( GL_NORMAL_ARRAY ); + glEnableClientState( GL_VERTEX_ARRAY ); + glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); + + glNewList( listIdx, GL_COMPILE ); + + //SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + //glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x ); + glEnable( GL_COLOR_MATERIAL ); + glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + + // OGL_SetMaterial() + glNormal3f( 0.0f, 0.0f, aIsNormalUp?1.0f:-1.0f ); + + glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() ); +/* + glEnable( GL_COLOR_MATERIAL ); + glColor3f( 0.0,1.0,1.0); + for( unsigned int i=0; i < aTriangleContainer->GetVertexSize(); ++i ) + { + const SFVEC3F &v1 = aTriangleContainer->GetVertexPointer()[ i * 3]; + + glBegin(GL_LINES); + glVertex3f( v1.x, v1.y, v1.z ); + if( aIsNormalUp ) + { + glVertex3f( v1.x, v1.y, v1.z+1.0f*.0051f ); + } + else + { + glVertex3f( v1.x, v1.y, v1.z-1.0f*.0051f ); + } + glEnd(); + } +*/ + glEndList(); + + glDisableClientState( GL_VERTEX_ARRAY ); + + return listIdx; + } + } + + return 0; +} + +GLuint CLAYERS_OGL_DISP_LISTS::generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER *aTriangleContainer, const SFVEC3F &aLayerColor ) const +{ + wxASSERT( aTriangleContainer != NULL ); + + // We expect that it is a multiple of 3 vertex + wxASSERT( (aTriangleContainer->GetVertexSize() % 3) == 0 ); + + // We expect that it is a multiple of 6 vertex (because we expect to add quads) + wxASSERT( (aTriangleContainer->GetVertexSize() % 6) == 0 ); + + // We expect that there are normals with same size as vertex + wxASSERT( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ); + + + if( ( aTriangleContainer->GetVertexSize() > 0 ) && + ( (aTriangleContainer->GetVertexSize() % 3) == 0 ) && + ( (aTriangleContainer->GetVertexSize() % 6) == 0 ) && + ( aTriangleContainer->GetNormalsSize() == aTriangleContainer->GetVertexSize() ) ) + { + GLuint listIdx = glGenLists( 1 ); + + if( glIsList( listIdx ) ) + { + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState( GL_COLOR_ARRAY ); + glEnableClientState( GL_NORMAL_ARRAY ); + glEnableClientState( GL_VERTEX_ARRAY ); + glVertexPointer( 3, GL_FLOAT, 0, aTriangleContainer->GetVertexPointer() ); + glNormalPointer( GL_FLOAT, 0, aTriangleContainer->GetNormalsPointer() ); + + glNewList( listIdx, GL_COMPILE ); +/* + 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 );*/ + + //SFVEC4F layerColor4 = SFVEC4F( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + //glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &layerColor4.x ); + //glDisable( GL_COLOR_MATERIAL ); + glEnable( GL_COLOR_MATERIAL ); + glColor4f( aLayerColor.x, aLayerColor.y, aLayerColor.z, 1.0f ); + + // OGL_SetMaterial() + + glDrawArrays( GL_TRIANGLES, 0, aTriangleContainer->GetVertexSize() ); +/* + glEnable( GL_COLOR_MATERIAL ); + glColor3f( 1.0,0.0,1.0); + for( unsigned int i=0; i < aTriangleContainer->GetVertexSize() / 3 ; ++i ) + { + const SFVEC3F &v1 = ((const SFVEC3F*)aTriangleContainer->GetVertexPointer())[i * 3]; + const SFVEC3F &n1 = ((const SFVEC3F*)aTriangleContainer->GetNormalsPointer())[i * 3]; + glBegin(GL_LINES); + glVertex3f( v1.x, v1.y, v1.z ); + glVertex3f( v1.x+n1.x*.01f, v1.y+n1.y*.01f, v1.z+n1.z*.01f ); + glEnd(); + } +*/ + glEndList(); + + glDisableClientState( GL_VERTEX_ARRAY ); + glDisableClientState( GL_NORMAL_ARRAY ); + + return listIdx; + } + } + + return 0; +} + diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.h new file mode 100644 index 0000000000..9709a00eb4 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/clayer_triangles.h @@ -0,0 +1,215 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 clayer_triangles.h + * @brief + */ + +#ifndef CLAYER_TRIANGLES_H_ +#define CLAYER_TRIANGLES_H_ + +#include "common_ogl/openGL_includes.h" +#include "3d_xv3d/xv3d_types.h" +#include + + +typedef std::vector< SFVEC3F > SFVEC3F_VECTOR; + + +/** + * @brief The CLAYER_TRIANGLE_CONTAINER class stores an manage vector of triangles + */ +class CLAYER_TRIANGLE_CONTAINER +{ + +public: + + /** + * @brief CLAYER_TRIANGLE_CONTAINER + * @param aNrReservedTriangles: number of triangles expected to be used + * @param aReserveNormals: if you will use normals, set it to bool to pre reserve space + */ + CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles, bool aReserveNormals ); + + /** + * @brief AddTriangle + * @param aV1 + * @param aV2 + * @param aV3 + */ + void AddTriangle( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3 ); + + /** + * @brief AddQuad + * @param aV1 + * @param aV2 + * @param aV3 + * @param aV4 + */ + void AddQuad( const SFVEC3F &aV1, const SFVEC3F &aV2, const SFVEC3F &aV3, const SFVEC3F &aV4 ); + + /** + * @brief AddNormal + * @param aN1 + * @param aN2 + * @param aN3 + */ + void AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3 ); + + /** + * @brief AddNormal + * @param aN1 + * @param aN2 + * @param aN3 + */ + void AddNormal( const SFVEC3F &aN1, const SFVEC3F &aN2, const SFVEC3F &aN3, const SFVEC3F &aN4 ); + + /** + * @brief GetVertexPointer - Get the array of vertexes + * @return The pointer to the start of array vertex + */ + const float *GetVertexPointer() const { return (const float *)&m_vertexs[0].x; } + + /** + * @brief GetNormalsPointer - Get the array of normals + * @return The pointer to start of array of normals + */ + const float *GetNormalsPointer() const { return (const float *)&m_normals[0].x; } + + /** + * @brief GetVertexSize + * @return + */ + unsigned int GetVertexSize() const { return m_vertexs.size(); } + + /** + * @brief GetNormalsSize + * @return + */ + unsigned int GetNormalsSize() const { return m_normals.size(); } + +private: + SFVEC3F_VECTOR m_vertexs; ///< vertex array + SFVEC3F_VECTOR m_normals; ///< normals array +}; + + +/** + * @brief The CLAYER_TRIANGLES class stores arrays of triangles to be used to + * create display lists + */ +class CLAYER_TRIANGLES +{ +public: + /** + * @brief CLAYER_TRIANGLES - initialize arrays with reserved triangles + * @param aNrReservedTriangles: number of pre alloc triangles to reserve + */ + CLAYER_TRIANGLES( unsigned int aNrReservedTriangles ); + + /** + * @brief ~CLAYER_TRIANGLES - Free containers + */ + ~CLAYER_TRIANGLES(); + + /** + * @brief IsLayersSizeValid - check if the vertex arrays of the layers are as expected + * @return TRUE if layers are correctly setup + */ + bool IsLayersSizeValid(); + + CLAYER_TRIANGLE_CONTAINER *m_layer_top_segment_ends; + CLAYER_TRIANGLE_CONTAINER *m_layer_top_triangles; + CLAYER_TRIANGLE_CONTAINER *m_layer_middle_contourns_quads; + CLAYER_TRIANGLE_CONTAINER *m_layer_bot_triangles; + CLAYER_TRIANGLE_CONTAINER *m_layer_bot_segment_ends; +}; + + +/** + * @brief The CLAYERS_OGL_DISP_LISTS class stores the openGL display lists to + * related with a layer + */ +class CLAYERS_OGL_DISP_LISTS +{ +public: + /** + * @brief CLAYERS_OGL_DISP_LISTS - Creates the display lists for a layer + * @param aLayerTriangles: contains the layers array of vertex to render to display lists + * @param aTextureIndexForSegEnds: texture index to be used by segment ends. It is a black and white squared texture with a center circle diameter of the size of the texture. + */ + CLAYERS_OGL_DISP_LISTS( const CLAYER_TRIANGLES &aLayerTriangles, + GLuint aTextureIndexForSegEnds, + const SFVEC3F& aLayerColor ); + + /** + * @brief ~CLAYERS_OGL_DISP_LISTS - Destroy this class while free the display lists from GPU mem + */ + ~CLAYERS_OGL_DISP_LISTS(); + + /** + * @brief DrawTopAndMiddle - This function calls the display lists for the top elements and middle contourns + */ + void DrawTopAndMiddle() const; + + /** + * @brief DrawBotAndMiddle - This function calls the display lists for the botton elements and middle contourns + */ + void DrawBotAndMiddle() const; + + /** + * @brief DrawTop - This function calls the display lists for the top elements + */ + void DrawTop() const; + + /** + * @brief DrawBot - This function calls the display lists for the botton elements + */ + void DrawBot() const; + + /** + * @brief DrawMiddle - This function calls the display lists for the middle elements + */ + void DrawMiddle() const; + + /** + * @brief DrawAll - This function calls all the display lists + */ + void DrawAll() const; + +private: + GLuint generate_top_or_bot_seg_ends(const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor, bool aIsNormalUp , GLuint aTextureId ) const; + GLuint generate_top_or_bot_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor, bool aIsNormalUp ) const; + GLuint generate_middle_triangles( const CLAYER_TRIANGLE_CONTAINER * aTriangleContainer, const SFVEC3F& aLayerColor ) const; + +private: + GLuint m_layer_top_segment_ends; + GLuint m_layer_top_triangles; + GLuint m_layer_middle_contourns_quads; + GLuint m_layer_bot_triangles; + GLuint m_layer_bot_segment_ends; +}; + +#endif // CLAYER_TRIANGLES_H_ diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.cpp b/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.cpp new file mode 100644 index 0000000000..e256e3e388 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.cpp @@ -0,0 +1,265 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ogl_legacy_utils.cpp + * @brief + */ + + +#include "common_ogl/openGL_includes.h" +#include "ogl_legacy_utils.h" +#include +#include // For the wxASSERT + +#define RADPERDEG 0.0174533 + +void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize ) +{ + wxASSERT( aSize > 0.0f ); + + SFVEC3F vec = (aTargetPos - aPosition); + float length = glm::length( vec ); + + GLUquadricObj *quadObj; + + glPushMatrix (); + + glTranslatef( aPosition.x, aPosition.y, aPosition.z ); + + if( ( vec.x != 0.0f ) || ( vec.y != 0.0f ) ) + { + glRotatef( atan2(vec.y, vec.x) / RADPERDEG, 0.0f, 0.0f, 1.0f ); + glRotatef( atan2(sqrt(vec.x * vec.x + vec.y * vec.y), vec.z) / RADPERDEG, 0.0f, 1.0f, 0.0f ); + } else if( vec.z < 0.0f ) + { + glRotatef( 180.0f, 1.0f, 0.0f, 0.0f ); + } + + glTranslatef( 0.0f, 0.0f, length - 4.0f * aSize ); + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluCylinder( quadObj, 2.0 * aSize, 0.0, 4.0 * aSize, 12, 1 ); + gluDeleteQuadric( quadObj ); + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluDisk( quadObj, 0.0, 2.0 * aSize, 12, 1 ); + gluDeleteQuadric( quadObj ); + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluDisk( quadObj, 0.0, aSize, 12, 1 ); + gluDeleteQuadric( quadObj ); + + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluSphere( quadObj, aSize, 24, 24 ); + gluDeleteQuadric( quadObj ); + + glTranslatef( 0.0f , 0.0f ,-length + 4.0f * aSize ); + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle(quadObj, GLU_FILL ); + gluQuadricNormals(quadObj, GLU_SMOOTH ); + gluCylinder( quadObj, aSize, aSize, length - 4.0 * aSize, 12, 1 ); + gluDeleteQuadric( quadObj ); +/* + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluSphere( quadObj, aSize, 24, 24 ); + gluDeleteQuadric( quadObj ); +*/ + + quadObj = gluNewQuadric(); + gluQuadricDrawStyle( quadObj, GLU_FILL ); + gluQuadricNormals( quadObj, GLU_SMOOTH ); + gluDisk( quadObj, 0.0, aSize, 12, 1 ); + gluDeleteQuadric( quadObj ); + + glPopMatrix (); +} + + +void OGL_draw_bbox( const CBBOX &aBBox ) +{ + wxASSERT( aBBox.IsInitialized() ); + + glBegin( GL_LINE_LOOP ); + glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z ); + glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z ); + glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z ); + glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z ); + glEnd(); + + glBegin( GL_LINE_LOOP ); + glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z ); + glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z ); + glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z ); + glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z ); + glEnd(); + + glBegin( GL_LINE_STRIP ); + glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Min().z ); + glVertex3f( aBBox.Min().x, aBBox.Min().y, aBBox.Max().z ); + glEnd(); + + glBegin( GL_LINE_STRIP ); + glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Min().z ); + glVertex3f( aBBox.Max().x, aBBox.Min().y, aBBox.Max().z ); + glEnd(); + + glBegin( GL_LINE_STRIP ); + glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Min().z ); + glVertex3f( aBBox.Max().x, aBBox.Max().y, aBBox.Max().z ); + glEnd(); + + glBegin( GL_LINE_STRIP ); + glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Min().z ); + glVertex3f( aBBox.Min().x, aBBox.Max().y, aBBox.Max().z ); + glEnd(); +} + + +void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle ) +{ + if( aNrSidesPerCircle > 1 ) + { + float radius = 0.5f; + int delta = 3600 / aNrSidesPerCircle; + + // Generate bottom + glNormal3f( 0.0f, 0.0f,-1.0f ); + glBegin( GL_TRIANGLE_FAN ); + glVertex3f( 0.0, 0.0, 0.0 ); // This is the V0 of the FAN + for( int ii = 0; ii < 1800; ii += delta ) + { + SFVEC2D corner = SFVEC2D( 0.0, radius ); + RotatePoint( &corner.x, &corner.y, ii ); + glVertex3f( corner.x, corner.y, 0.0 ); + } + glVertex3d( 0.0, -radius, 0.0 ); + glEnd(); + + // Generate top + glNormal3f( 0.0f, 0.0f, 1.0f ); + glBegin( GL_TRIANGLE_FAN ); + glVertex3f( 0.0, 0.0, 1.0 ); // This is the V0 of the FAN + for( int ii = 1800; ii > 0; ii -= delta ) + { + SFVEC2D corner = SFVEC2D( 0.0, radius ); + RotatePoint( &corner.x, &corner.y, ii ); + glVertex3f( corner.x, corner.y, 1.0 ); + } + glVertex3f( 0.0, radius, 1.0 ); + glEnd(); + + // Generate contours + glBegin( GL_QUAD_STRIP ); + for( int ii = 1800; ii > 0; ii -= delta ) + { + SFVEC2D corner = SFVEC2D( 0.0, radius ); + RotatePoint( &corner.x, &corner.y, ii ); + glNormal3f( corner.x * 2.0f, corner.y * 2.0f, 0.0f ); + glVertex3f( corner.x, corner.y, 1.0 ); + glVertex3f( corner.x, corner.y, 0.0 ); + } + glNormal3f( 0.0, 1.0f, 0.0f ); + glVertex3d( 0.0, radius, 1.0 ); + glVertex3d( 0.0, radius, 0.0 ); + glEnd(); + } +} + + +void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment, unsigned int aNrSidesPerCircle ) +{ + glPushMatrix(); + + const SFVEC2F start = aSegment.GetStart(); + const SFVEC2F end = aSegment.GetEnd(); + const SFVEC2F end_minus_start = aSegment.GetEnd_minus_Start(); + const float radius = aSegment.GetRadius(); + const float width = aSegment.GetWidth(); + const float lenght = aSegment.GetLenght(); + + glTranslatef( start.x, start.y, 0.0f ); + + if( ( end_minus_start.x != 0.0f ) || ( end_minus_start.y != 0.0f ) ) + { + glRotatef( atan2(end_minus_start.y, end_minus_start.x) / RADPERDEG, 0.0f, 0.0f, 1.0f ); + } + + glPushMatrix(); + glTranslatef( lenght, 0.0, 0.0f ); + glScalef( width, width, 1.0f ); + OGL_draw_half_open_cylinder( aNrSidesPerCircle ); + glPopMatrix (); + + glBegin( GL_QUADS ); + glNormal3f( 0.0,-1.0, 0.0 ); + glVertex3f( lenght,-radius, 1.0 ); + glVertex3f( 0.0, -radius, 1.0 ); + glVertex3f( 0.0, -radius, 0.0 ); + glVertex3f( lenght,-radius, 0.0 ); + glEnd(); + + glBegin( GL_QUADS ); + glNormal3f( 0.0, 1.0, 0.0 ); + glVertex3f( lenght, radius, 0.0 ); + glVertex3f( 0.0, radius, 0.0 ); + glVertex3f( 0.0, radius, 1.0 ); + glVertex3f( lenght, radius, 1.0 ); + glEnd(); + + glBegin( GL_QUADS ); + glNormal3f( 0.0, 0.0, 1.0 ); + glVertex3f( lenght, radius, 1.0 ); + glVertex3f( 0.0, radius, 1.0 ); + glVertex3f( 0.0, -radius, 1.0 ); + glVertex3f( lenght,-radius, 1.0 ); + glEnd(); + + glBegin( GL_QUADS ); + glNormal3f( 0.0, 0.0,-1.0 ); + glVertex3f( lenght,-radius, 0.0 ); + glVertex3f( 0.0, -radius, 0.0 ); + glVertex3f( 0.0, radius, 0.0 ); + glVertex3f( lenght, radius, 0.0 ); + glEnd(); + + glScalef( width, width, 1.0f ); + glRotatef( 180, 0.0, 0.0, 1.0 ); + OGL_draw_half_open_cylinder( aNrSidesPerCircle ); + + glPopMatrix (); +} diff --git a/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h b/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h new file mode 100644 index 0000000000..cc619b7b69 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.h @@ -0,0 +1,67 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ogl_legacy_utils.h + * @brief + */ + +#ifndef OGL_LEGACY_UTILS_H_ +#define OGL_LEGACY_UTILS_H_ + +#include "3d_xv3d/xv3d_types.h" +#include "3d_render_raytracing/shapes3D/cbbox.h" +#include "3d_render_raytracing/shapes2D/croundsegment2d.h" + +/** + * @brief OGL_draw_arrow - draw a round arrow + * @param aPosition: start position of the arrow + * @param aTargetPos: end position of the arror + * @param aSize: diameter size + */ +void OGL_draw_arrow( SFVEC3F aPosition, SFVEC3F aTargetPos, float aSize ); + + +/** + * @brief OGL_draw_bbox - draw the bounding box lines + * @param aBBox + */ +void OGL_draw_bbox( const CBBOX &aBBox ); + + +/** + * @brief OGL_draw_half_open_cylinder - draws an open half cylinder + * with diameter 1.0f and Height 1.0f + * the bottom center is at (0,0,0) and top center is at (0,0,1) + */ +void OGL_draw_half_open_cylinder( unsigned int aNrSidesPerCircle ); + + +/** + * @brief OGL_Draw_segment + * @param aSegment + */ +void OGL_Draw_segment( const CROUNDSEGMENT2D &aSegment, unsigned int aNrSidesPerCircle ); + +#endif // OGL_LEGACY_UTILS_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer.h b/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer.h new file mode 100644 index 0000000000..7026d4e746 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer.h @@ -0,0 +1,83 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ccontainer.h + * @brief + */ + +#ifndef _CCONTAINER_H_ +#define _CCONTAINER_H_ + +#include "../shapes3D/cobject.h" +#include +#include + +typedef std::list LIST_OBJECT; +typedef std::vector VECTOR_OBJECT; +typedef std::vector CONST_VECTOR_OBJECT; + +class GLM_ALIGN(CLASS_ALIGNMENT) CGENERICCONTAINER +{ +protected: + CBBOX m_bbox; + LIST_OBJECT m_objects; + +public: + CGENERICCONTAINER(); + + virtual ~CGENERICCONTAINER(); + + void Add( COBJECT *aObject ) + { + if( aObject ) // Only add if it is a valid pointer + { + m_objects.push_back( aObject ); + m_bbox.Union( aObject->GetBBox() ); + } + } + + void Clear(); + + const LIST_OBJECT &GetList() const { return m_objects; } + + const void ConvertTo( CONST_VECTOR_OBJECT &aOutVector ) const; + + const CBBOX &GetBBox() const { return m_bbox; } + + virtual bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const = 0; + virtual bool IntersectP( const RAY &aRay, float aMaxDistance ) const = 0; + +private: +}; + + +class GLM_ALIGN(CLASS_ALIGNMENT) CCONTAINER : public CGENERICCONTAINER +{ +public: + bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const; + bool IntersectP( const RAY &aRay, float aMaxDistance ) const; +}; + +#endif // _CCONTAINER_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h new file mode 100644 index 0000000000..eda1aa94b2 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h @@ -0,0 +1,116 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ccontainer2d.h + * @brief + */ + +#ifndef _CCONTAINER2D_H_ +#define _CCONTAINER2D_H_ + +#include "../shapes2D/cobject2d.h" +#include + +typedef std::list LIST_OBJECT2D; +typedef std::list CONST_LIST_OBJECT2D; + + +class GLM_ALIGN(CLASS_ALIGNMENT) CGENERICCONTAINER2D +{ +protected: + CBBOX2D m_bbox; + LIST_OBJECT2D m_objects; + +public: + CGENERICCONTAINER2D( OBJECT2D_TYPE aObjType ); + + virtual ~CGENERICCONTAINER2D(); + + void Add( COBJECT2D *aObject ) + { + if( aObject ) // Only add if it is a valid pointer + { + m_objects.push_back( aObject ); + m_bbox.Union( aObject->GetBBox() ); + } + }// automatically releases the lock when lck goes out of scope. + + void Clear(); + + const LIST_OBJECT2D &GetList() const { return m_objects; } + + /** + * @brief GetListObjectsIntersects - Get a list of objects that intersects a bbox + * @param aBBox - a bbox to make the query + * @param aOutList - A list of objects that intersects the bbox + */ + virtual void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const = 0; + +private: +}; + + +class GLM_ALIGN(CLASS_ALIGNMENT) CCONTAINER2D : public CGENERICCONTAINER2D +{ +public: + CCONTAINER2D(); + + // Imported from CGENERICCONTAINER2D + void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const; +}; + + +struct BVH_CONTAINER_NODE_2D +{ + CBBOX2D m_BBox; + BVH_CONTAINER_NODE_2D *m_Children[2]; + CONST_LIST_OBJECT2D m_LeafList; ///< Store the list of objects if that node is a Leaf +}; + + +class GLM_ALIGN(CLASS_ALIGNMENT) CBVHCONTAINER2D : public CGENERICCONTAINER2D +{ +public: + CBVHCONTAINER2D(); + ~CBVHCONTAINER2D(); + + void BuildBVH(); + +private: + bool m_isInitialized; + std::list m_elements_to_delete; + BVH_CONTAINER_NODE_2D *m_Tree; + + void destroy(); + void recursiveBuild_MIDDLE_SPLIT( BVH_CONTAINER_NODE_2D *aNodeParent ); + void recursiveGetListObjectsIntersects( const BVH_CONTAINER_NODE_2D *aNode, const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const; + +public: + + // Imported from CGENERICCONTAINER2D + void GetListObjectsIntersects( const CBBOX2D & aBBox, CONST_LIST_OBJECT2D &aOutList ) const; +}; + +#endif // _CCONTAINER2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/cfrustum.h b/3d-viewer/3d_rendering/3d_render_raytracing/cfrustum.h new file mode 100644 index 0000000000..d777f791ea --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/cfrustum.h @@ -0,0 +1,53 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cfrustum.h + * @brief + */ + +#ifndef _CFRUSTUM_H_ +#define _CFRUSTUM_H_ + +#include "../../3d_xv3d/xv3d_types.h" +#include "shapes3D/cbbox.h" +#include "ray.h" + +// !TODO: optimize wih SSE +//#if(GLM_ARCH != GLM_ARCH_PURE) +#if 0 +#error not implemented +#else +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CFRUSTUM +{ + SFVEC3F m_normals[4]; + SFVEC3F m_point[4]; + + void GenerateFrustum( const RAY &topLeft, const RAY &topRight, const RAY &bottomLeft, const RAY &bottomRight ); + bool Intersect( const CBBOX &aBBox ) const; +}; +#endif + + +#endif // _CFRUSTUM_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h new file mode 100644 index 0000000000..8b31b38107 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/cmaterial.h @@ -0,0 +1,95 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cmaterial.h + * @brief + */ + +#ifndef _CMATERIAL_H_ +#define _CMATERIAL_H_ + +#include "ray.h" +#include "hitinfo.h" + +/// +class GLM_ALIGN(CLASS_ALIGNMENT) CMATERIAL +{ +public: + CMATERIAL(); + CMATERIAL( const SFVEC3F &aAmbient, const SFVEC3F &aEmissive, const SFVEC3F &aSpecular, float aShinness, float aTransparency ); + + const SFVEC3F &GetAmbientColor() const { return m_ambientColor; } + const SFVEC3F &GetEmissiveColor() const { return m_emissiveColor; } + const SFVEC3F &GetSpecularColor() const { return m_specularColor; } + + float GetShinness() const { return m_shinness; } + float GetTransparency() const { return m_transparency; } + + void SetCastShadows( bool aCastShadows ) { m_cast_shadows = aCastShadows; } + bool GetCastShadows() const { return m_cast_shadows; } + + virtual SFVEC3F Shade( const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, bool aIsInShadow ) const = 0; + +/* + + + virtual SFVEC3F GetReflect(Vec3f point){ return reflectiveColor;} + virtual Vec3f GetTrans(Vec3f point){ return transparentColor;} + virtual float getIndexOfRefrac(Vec3f point){ return indexOfRefraction;} + + virtual bool isReflect(Vec3f point){return ((reflectiveColor.x()>0)||(reflectiveColor.y()>0)||(reflectiveColor.z()>0));} + virtual bool isTransparent(Vec3f point){return ((transparentColor.x()>0)||(transparentColor.y()>0)||(transparentColor.z()>0));} +*/ +protected: + SFVEC3F m_ambientColor; + // NOTE: we will not use diffuse color material here, + // because it will be stored in object, since there are objects (i.e: triangles) + // that can have per vertex color + + SFVEC3F m_emissiveColor; + SFVEC3F m_specularColor; + float m_shinness; + float m_transparency; ///< 1.0 is completely transparent, 0.0 completely opaque + bool m_cast_shadows; ///< true if this object will block the light +}; + + +/// https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model +class GLM_ALIGN(CLASS_ALIGNMENT) CBLINN_PHONG_MATERIAL : public CMATERIAL +{ +public: + CBLINN_PHONG_MATERIAL() : CMATERIAL() {} + + CBLINN_PHONG_MATERIAL( const SFVEC3F &aAmbient, + const SFVEC3F &aEmissive, + const SFVEC3F &aSpecular, + float aShinness, + float aTransparency ) : + CMATERIAL( aAmbient, aEmissive, aSpecular, aShinness, aTransparency ) {} + + SFVEC3F Shade( const RAY &aRay, const HITINFO &aHitInfo, float NdotL, const SFVEC3F &aDiffuseObjColor, const SFVEC3F &aDirToLight, const SFVEC3F &aLightColor, bool aIsInShadow ) const; +}; + +#endif // _CMATERIAL_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/hitinfo.h b/3d-viewer/3d_rendering/3d_render_raytracing/hitinfo.h new file mode 100644 index 0000000000..b500fb1cc9 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/hitinfo.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 hitinfo.h + * @brief + */ + +#ifndef _HITINFO_H_ +#define _HITINFO_H_ + +#include "../../3d_xv3d/xv3d_types.h" +#include "raypacket.h" + +//#define RAYTRACING_RAY_STATISTICS + +class COBJECT; + +/// Stores the hit information of a ray with a point on the surface of a object +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) HITINFO +{ + SFVEC3F m_HitNormal; ///< (12) normal at the hit point + float m_tHit; ///< ( 4) distance + + const COBJECT *pHitObject; ///< ( 4) Object that was hitted + SFVEC2F m_UV; ///< ( 8) 2-D texture coordinates + + unsigned int m_acc_node_info; ///< ( 4) The acc should store here information (Ex: the node that it hits) + +#ifdef RAYTRACING_RAY_STATISTICS + // Statistics + unsigned int m_NrRayObjTests; ///< Number of ray-objects tests + unsigned int m_NrTransversedNodes; ///< Number of transversed nodes in the acc structure +#endif +}; + +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) HITINFO_PACKET +{ + bool m_hitresult; + HITINFO m_HitInfo; + +}; + +#endif // _HITINFO_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/ray.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/ray.cpp new file mode 100644 index 0000000000..e8f11a8e95 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/ray.cpp @@ -0,0 +1,394 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ray.cpp + * @brief + */ + + +#include "ray.h" +#include "3d_math/3d_fastmath.h" +#include +#include + +static unsigned int gs_next_rayID = 0; + +void RAY::Init( const SFVEC3F& o, const SFVEC3F& d ) +{ + m_Origin = o; + m_Dir = d; + m_InvDir = 1.0f / d; + + if( fabs(m_Dir.x) < FLT_EPSILON ) + m_InvDir.x = NextFloatDown(FLT_MAX); + + if( fabs(m_Dir.y) < FLT_EPSILON ) + m_InvDir.y = NextFloatDown(FLT_MAX); + + if( fabs(m_Dir.z) < FLT_EPSILON ) + m_InvDir.z = NextFloatDown(FLT_MAX); + + rayID = gs_next_rayID; + gs_next_rayID++; + + // An Efficient and Robust Ray–Box Intersection Algorithm + // Amy Williams Steve Barrus R. Keith Morley Peter Shirley + // University of Utah + // http://people.csail.mit.edu/amy/papers/box-jgt.pdf + m_dirIsNeg[0] = m_Dir.x < 0.0f; + m_dirIsNeg[1] = m_Dir.y < 0.0f; + m_dirIsNeg[2] = m_Dir.z < 0.0f; + + // ray slope + + // "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes" + // by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor + // Computer Graphics Lab, TU Braunschweig, Germany and + // University of Koblenz-Landau, Germany + // Licence: "This source code is public domain, but please mention us if you use it." + // + // https://github.com/rjw57/mcvoxel/tree/master/third-party/rayslope + // https://github.com/rjw57/mcvoxel/blob/master/third-party/rayslope/ray.cpp + + ibyj = m_Dir.x * m_InvDir.y; + jbyi = m_Dir.y * m_InvDir.x; + jbyk = m_Dir.y * m_InvDir.z; + kbyj = m_Dir.z * m_InvDir.y; + ibyk = m_Dir.x * m_InvDir.z; + kbyi = m_Dir.z * m_InvDir.x; + c_xy = m_Origin.y - jbyi * m_Origin.x; + c_xz = m_Origin.z - kbyi * m_Origin.x; + c_yx = m_Origin.x - ibyj * m_Origin.y; + c_yz = m_Origin.z - kbyj * m_Origin.y; + c_zx = m_Origin.x - ibyk * m_Origin.z; + c_zy = m_Origin.y - jbyk * m_Origin.z; + + // ray slope classification + if( m_Dir.x < 0 ) + { + if( m_Dir.y < 0 ) + { + if( m_Dir.z < 0 ) + { + m_Classification = MMM; + } + else if( m_Dir.z > 0 ){ + m_Classification = MMP; + } + else//( m_Dir.z >= 0 ) + { + m_Classification = MMO; + } + } + else//( m_Dir.y >= 0 ) + { + if( m_Dir.z < 0 ) + { + m_Classification = MPM; + if( m_Dir.y == 0 ) + m_Classification = MOM; + } + else//( m_Dir.z >= 0 ) + { + if( ( m_Dir.y == 0 ) && ( m_Dir.z == 0 ) ) + m_Classification = MOO; + else if( m_Dir.z == 0 ) + m_Classification = MPO; + else if( m_Dir.y == 0 ) + m_Classification = MOP; + else + m_Classification = MPP; + } + } + } + else//( m_Dir.x >= 0 ) + { + if( m_Dir.y < 0 ) + { + if( m_Dir.z < 0 ) + { + m_Classification = PMM; + if( m_Dir.x == 0 ) + m_Classification = OMM; + } + else//( m_Dir.z >= 0 ) + { + if( ( m_Dir.x == 0 ) && ( m_Dir.z == 0 ) ) + m_Classification = OMO; + else if( m_Dir.z == 0 ) + m_Classification = PMO; + else if( m_Dir.x == 0 ) + m_Classification = OMP; + else + m_Classification = PMP; + } + } + else//( m_Dir.y >= 0 ) + { + if( m_Dir.z < 0 ) + { + if( ( m_Dir.x == 0 ) && ( m_Dir.y == 0 ) ) + m_Classification = OOM; + else if( m_Dir.x == 0 ) + m_Classification = OPM; + else if( m_Dir.y == 0 ) + m_Classification = POM; + else + m_Classification = PPM; + } + else//( m_Dir.z > 0 ) + { + if( m_Dir.x == 0 ) + { + if( m_Dir.y == 0 ) + m_Classification = OOP; + else if( m_Dir.z == 0 ) + m_Classification = OPO; + else + m_Classification = OPP; + } + else + { + if( ( m_Dir.y == 0 ) && ( m_Dir.z == 0 ) ) + m_Classification = POO; + else if( m_Dir.y == 0 ) + m_Classification = POP; + else if( m_Dir.z == 0 ) + m_Classification = PPO; + else + m_Classification = PPP; + } + } + } + } +} + + +bool IntersectSegment( const SFVEC2F &aStartA, const SFVEC2F &aEnd_minus_startA, + const SFVEC2F &aStartB, const SFVEC2F &aEnd_minus_startB ) +{ + float rxs = aEnd_minus_startA.x * aEnd_minus_startB.y - aEnd_minus_startA.y * aEnd_minus_startB.x; + + if( fabs(rxs) > glm::epsilon() ) + { + float inv_rxs = 1.0f / rxs; + + SFVEC2F pq = aStartB - aStartA; + + float t = (pq.x * aEnd_minus_startB.y - pq.y * aEnd_minus_startB.x) * inv_rxs; + + if( (t < 0.0f) || (t > 1.0f) ) + return false; + + float u = (pq.x * aEnd_minus_startA.y - pq.y * aEnd_minus_startA.x) * inv_rxs; + + if( (u < 0.0f) || (u > 1.0f) ) + return false; + + return true; + } + + return false; +} + +// !TODO: not tested +bool RAY::IntersectSphere( const SFVEC3F &aCenter, float aRadius, float &aOutT0, float &aOutT1 ) const +{ +/* + // Ray-sphere intersection: algebraic + + SFVEC3F CO = m_Origin - aCenter; + + float a = glm::dot( m_Dir, m_Dir ); + float b = 2.0f * glm::dot( CO, m_Dir ); + float c = glm::dot( CO, CO ) - aRadius*aRadius; + + float discriminant = b * b - 4.0f * a * c; + + if( discriminant < 0.0f ) + return false; + + aOutT0 = (-b - sqrtf(discriminant)) / (2.0f * a); + aOutT1 = (-b + sqrtf(discriminant)) / (2.0f * a); + + if( aOutT0 > aOutT1 ) + { + float temp = aOutT0; + aOutT0 = aOutT1; + aOutT1 = temp; + } + + return true; +*/ + + // Ray-sphere intersection: geometric + SFVEC3F OC = aCenter - m_Origin; + float p_dot_d = glm::dot( OC, m_Dir ); + + if( p_dot_d < 0.0f ) + return 0.0f; + + float p_dot_p = glm::dot( OC, OC ); + float discriminant = p_dot_p - p_dot_d * p_dot_d; + + if( discriminant > aRadius*aRadius ) + return false; + + discriminant = sqrtf( aRadius*aRadius - discriminant ); + + aOutT0 = p_dot_d - discriminant; + aOutT1 = p_dot_d + discriminant; + + if( aOutT0 > aOutT1 ) + { + float temp = aOutT0; + aOutT0 = aOutT1; + aOutT1 = temp; + } + + return true; +} + +RAYSEG2D::RAYSEG2D( const SFVEC2F& s, const SFVEC2F& e ) +{ + m_Start = s; + m_End = e; + m_End_minus_start = e - s; + m_Length = glm::length( m_End_minus_start ); + m_Dir = glm::normalize( m_End_minus_start ); + m_InvDir = (1.0f / m_Dir); + + if( fabs(m_Dir.x) < FLT_EPSILON ) + m_InvDir.x = NextFloatDown(FLT_MAX); + + if( fabs(m_Dir.y) < FLT_EPSILON ) + m_InvDir.y = NextFloatDown(FLT_MAX); + + m_DOT_End_minus_start = glm::dot( m_End_minus_start, m_End_minus_start ); +} + + +bool RAYSEG2D::IntersectSegment( const SFVEC2F &aStart, const SFVEC2F &aEnd_minus_start, float *aOutT ) const +{ + float rxs = m_End_minus_start.x * aEnd_minus_start.y - m_End_minus_start.y * aEnd_minus_start.x; + + if( fabs(rxs) > glm::epsilon() ) + { + float inv_rxs = 1.0f / rxs; + + SFVEC2F pq = aStart - m_Start; + + float t = (pq.x * aEnd_minus_start.y - pq.y * aEnd_minus_start.x) * inv_rxs; + + if( (t < 0.0f) || (t > 1.0f) ) + return false; + + float u = (pq.x * m_End_minus_start.y - pq.y * m_End_minus_start.x) * inv_rxs; + + if( (u < 0.0f) || (u > 1.0f) ) + return false; + + *aOutT = t; + + return true; + } + + return false; +} + + +// http://geomalgorithms.com/a02-_lines.html +float RAYSEG2D::DistanceToPointSquared( const SFVEC2F &aPoint ) const +{ + SFVEC2F p = aPoint - m_Start; + + float c1 = glm::dot( p, m_End_minus_start ); + + if( c1 < FLT_EPSILON ) + return glm::dot( p, p ); + + if( m_DOT_End_minus_start <= c1 ) + p = aPoint - m_End; + else + { + float b = c1 / m_DOT_End_minus_start; + SFVEC2F pb = m_Start + m_End_minus_start * b; + p = aPoint - pb; + } + + return glm::dot( p, p ); +} + + +bool RAYSEG2D::IntersectCircle( const SFVEC2F &aCenter, float aRadius, float *aOutT0, float *aOutT1, SFVEC2F *aOutNormalT0, SFVEC2F *aOutNormalT1 ) const +{ + // This code used directly from Steve Marschner's CS667 framework + // http://cs665pd.googlecode.com/svn/trunk/photon/sphere.cpp + + // Compute some factors used in computation + float qx = m_Start.x - aCenter.x; + float qy = m_Start.y - aCenter.y; + + float qd = qx * m_Dir.x + qy * m_Dir.y; + float qq = qx * qx + qy * qy; + + // solving the quadratic equation for t at the pts of intersection + // dd*t^2 + (2*qd)*t + (qq-r^2) = 0 + float discriminantsqr = (qd * qd - (qq - aRadius * aRadius)); + + // If the discriminant is less than zero, there is no intersection + if( discriminantsqr < FLT_EPSILON ) + return false; + + + // Otherwise check and make sure that the intersections occur on the ray (t + // > 0) and return the closer one + float discriminant = sqrt(discriminantsqr); + float t1 = (-qd - discriminant); + float t2 = (-qd + discriminant); + + if( (( t1 < 0.0f ) || ( t1 > m_Length ) ) && + (( t2 < 0.0f ) || ( t2 > m_Length ) ) ) + return false;// Neither intersection was in the ray's half line. + + // Convert the intersection to a normalized + *aOutT0 = t1 / m_Length; + *aOutT1 = t2 / m_Length; + + SFVEC2F hitPointT1 = at( t1 ); + SFVEC2F hitPointT2 = at( t2 ); + + *aOutNormalT0 = (hitPointT1 - aCenter) / aRadius; + *aOutNormalT1 = (hitPointT2 - aCenter) / aRadius; + + return true; +} + + +void RAY::debug() const +{ + printf("O(%f, %f, %f) D(%f, %f, %f)\n", m_Origin.x, m_Origin.y, m_Origin.z, + m_Dir.x, m_Dir.y, m_Dir.z ); +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/ray.h b/3d-viewer/3d_rendering/3d_render_raytracing/ray.h new file mode 100644 index 0000000000..e7a990ca87 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/ray.h @@ -0,0 +1,129 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ray.h + * @brief + */ + +#ifndef _RAY_H_ +#define _RAY_H_ + +#include "3d_xv3d/xv3d_types.h" + + +enum RAY_CLASSIFICATION +{ + MMM, MMP, MPM, MPP, PMM, PMP, PPM, PPP, POO, MOO, OPO, OMO, OOP, OOM, OMM, + OMP,OPM,OPP,MOM,MOP,POM,POP,MMO,MPO,PMO,PPO +}; + + +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY +{ + SFVEC3F m_Origin; + unsigned int rayID; ///< unique ray ID + + SFVEC3F m_Dir; + RAY_CLASSIFICATION m_Classification; + + SFVEC3F m_InvDir; + + float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi; // slope + float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy; + + unsigned int m_dirIsNeg[3]; + + void Init( const SFVEC3F& o, const SFVEC3F& d ); + + bool IntersectSphere( const SFVEC3F &aCenter, float aRadius, float &aOutT0, float &aOutT1 ) const; + + SFVEC3F at( float t ) const { return m_Origin + m_Dir * t; } + SFVEC2F at2D( float t ) const { return SFVEC2F( m_Origin.x + m_Dir.x * t, m_Origin.y + m_Dir.y * t ); } + + void debug() const; +}; + + +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY2D +{ + SFVEC2F m_Origin; + SFVEC2F m_Dir; + SFVEC2F m_InvDir; + + RAY2D( const SFVEC2F& o, const SFVEC2F& d ) { m_Origin = o; m_Dir = d; m_InvDir = (1.0f / d); } + + SFVEC2F at( float t ) const { return m_Origin + m_Dir * t; } +}; + + +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAYSEG2D +{ + SFVEC2F m_Start; + SFVEC2F m_End; + SFVEC2F m_End_minus_start; + SFVEC2F m_Dir; + SFVEC2F m_InvDir; + float m_Length; + float m_DOT_End_minus_start; ///< dot( m_End_minus_start, m_End_minus_start) + + RAYSEG2D( const SFVEC2F& s, const SFVEC2F& e ); + + bool IntersectSegment( const SFVEC2F &aStart, const SFVEC2F &aEnd_minus_start, float *aOutT ) const; + bool IntersectCircle( const SFVEC2F &aCenter, float aRadius, float *aOutT0, float *aOutT1, SFVEC2F *aOutNormalT0, SFVEC2F *aOutNormalT1 ) const; + + float DistanceToPointSquared( const SFVEC2F &aPoint ) const; + /** + * Function atNormalized - returns the position at t + * t - value 0.0 ... 1.0 + */ + SFVEC2F atNormalized( float t ) const { return m_Start + m_End_minus_start * t; } + + SFVEC2F at( float t ) const { return m_Start + m_Dir * t; } +}; + + +bool IntersectSegment( const SFVEC2F &aStartA, const SFVEC2F &aEnd_minus_startA, + const SFVEC2F &aStartB, const SFVEC2F &aEnd_minus_startB ); + +#if(GLM_ARCH != GLM_ARCH_PURE) +/* +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAY4 +{ + glm::simdVec4 m_orgX; ///< x coordinate of ray origin + glm::simdVec4 m_orgy; ///< y coordinate of ray origin + glm::simdVec4 m_orgz; ///< z coordinate of ray origin + + glm::simdVec4 m_dirX; ///< x direction of ray + glm::simdVec4 m_diry; ///< y direction of ray + glm::simdVec4 m_dirz; ///< z direction of ray + + glm::simdVec4 m_tnear; ///< Start of ray segment + glm::simdVec4 m_tfar; ///< End of ray segment +};*/ + +#endif + + +#endif // _RAY_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/raypacket.h b/3d-viewer/3d_rendering/3d_render_raytracing/raypacket.h new file mode 100644 index 0000000000..bc9b2d9e43 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/raypacket.h @@ -0,0 +1,53 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 raypacket.h + * @brief + */ + +#ifndef _RAYPACKET_H_ +#define _RAYPACKET_H_ + +#include "ray.h" +#include "cfrustum.h" +#include "../ccamera.h" + +#define RAYPACKET_DIM (1 << 3) +#define RAYPACKET_MASK (unsigned int)( (RAYPACKET_DIM - 1)) +#define RAYPACKET_INVMASK (unsigned int)(~(RAYPACKET_DIM - 1)) +#define RAYPACKET_RAYS_PER_PACKET (RAYPACKET_DIM * RAYPACKET_DIM) + + +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) RAYPACKET +{ + CFRUSTUM m_Frustum; + RAY m_ray[RAYPACKET_RAYS_PER_PACKET]; + + RAYPACKET( const CCAMERA &aCamera, const SFVEC2I &aWindowsPosition ); + RAYPACKET( const CCAMERA &aCamera, const SFVEC2I &aWindowsPosition, unsigned int aPixelMultiple ); +}; + + +#endif // _RAYPACKET_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.cpp new file mode 100644 index 0000000000..01fa466214 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.cpp @@ -0,0 +1,307 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 CBBOX2D2d.cpp + * @brief Bounding Box class implementation + */ + +#include "3d_math/3d_fastmath.h" + +#include "cbbox2d.h" +#include +#include + + +CBBOX2D::CBBOX2D() +{ + Reset(); +} + + +CBBOX2D::CBBOX2D( const SFVEC2F &aPbInit ) +{ + m_min = aPbInit; + m_max = aPbInit; +} + + +CBBOX2D::CBBOX2D( const SFVEC2F &aPbMin, const SFVEC2F &aPbMax ) +{ + Set( aPbMin, aPbMax ); +} + + +CBBOX2D::~CBBOX2D() +{ +} + + +void CBBOX2D::Set( const SFVEC2F &aPbMin, const SFVEC2F &aPbMax ) +{ + m_min.x = fminf( aPbMin.x, aPbMax.x ); + m_min.y = fminf( aPbMin.y, aPbMax.y ); + + m_max.x = fmaxf( aPbMin.x, aPbMax.x ); + m_max.y = fmaxf( aPbMin.y, aPbMax.y ); +} + + +void CBBOX2D::Set( const CBBOX2D &aBBox ) +{ + wxASSERT( aBBox.IsInitialized() ); + + Set( aBBox.Min(), aBBox.Max() ); +} + + +bool CBBOX2D::IsInitialized() const +{ + return !( ( FLT_MAX == m_min.x) || + ( FLT_MAX == m_min.y) || + (-FLT_MAX == m_max.x) || + (-FLT_MAX == m_max.y) ); +} + + +void CBBOX2D::Reset() +{ + m_min = SFVEC2F( FLT_MAX, FLT_MAX ); + m_max = SFVEC2F(-FLT_MAX,-FLT_MAX ); +} + + +void CBBOX2D::Union( const SFVEC2F &aPoint ) +{ + // get the minimun value between the added point and the existent bounding box + m_min.x = fminf( m_min.x, aPoint.x ); + m_min.y = fminf( m_min.y, aPoint.y ); + + // get the maximun value between the added point and the existent bounding box + m_max.x = fmaxf( m_max.x, aPoint.x ); + m_max.y = fmaxf( m_max.y, aPoint.y ); +} + + +void CBBOX2D::Union( const CBBOX2D &aBBox ) +{ + // get the minimun value between the added bounding box and the existent bounding box + m_min.x = fminf( m_min.x, aBBox.m_min.x ); + m_min.y = fminf( m_min.y, aBBox.m_min.y ); + + // get the maximun value between the added bounding box and the existent bounding box + m_max.x = fmaxf( m_max.x, aBBox.m_max.x ); + m_max.y = fmaxf( m_max.y, aBBox.m_max.y ); +} + + +SFVEC2F CBBOX2D::GetCenter() const +{ + return (m_max + m_min) * 0.5f; +} + + +SFVEC2F CBBOX2D::GetExtent() const +{ + return m_max - m_min; +} + + +unsigned int CBBOX2D::MaxDimension() const +{ + unsigned int result = 0; + SFVEC2F extent = GetExtent(); + + if( extent.y > extent.x ) result = 1; + + return result; +} + + +float CBBOX2D::Perimeter() const +{ + SFVEC2F extent = GetExtent(); + return 2.0f * ( extent.x + extent.y ); +} + + +void CBBOX2D::Scale( float aScale ) +{ + wxASSERT( IsInitialized() ); + + SFVEC2F scaleV( aScale, aScale ); + SFVEC2F centerV = GetCenter(); + + m_min = (m_min - centerV) * scaleV + centerV; + m_max = (m_max - centerV) * scaleV + centerV; +} + + +void CBBOX2D::ScaleNextUp() +{ + m_min.x = NextFloatDown( m_min.x ); + m_min.y = NextFloatDown( m_min.y ); + + m_max.x = NextFloatUp( m_max.x ); + m_max.y = NextFloatUp( m_max.y ); +} + + +void CBBOX2D::ScaleNextDown() +{ + m_min.x = NextFloatUp( m_min.x ); + m_min.y = NextFloatUp( m_min.y ); + + m_max.x = NextFloatDown( m_max.x ); + m_max.y = NextFloatDown( m_max.y ); +} + + +// http://goanna.cs.rmit.edu.au/~gl/teaching/rtr&3dgp/notes/intersection.pdf +// http://www.mrtc.mdh.se/projects/3Dgraphics/paperF.pdf +bool CBBOX2D::Intersects( const SFVEC2F &aCenter, float aRadiusSquared ) const +{ + float fDistSq = 0.0f; + + for ( unsigned int i = 0; i < 2; i++ ) + { + if( aCenter[i] < m_min[i] ) + { + float fDist = aCenter[i] - m_min[i]; + fDistSq += fDist * fDist; + } + else + { + if( aCenter[i] > m_max[i] ) + { + float fDist = aCenter[i] - m_max[i]; + fDistSq += fDist * fDist; + } + } + } + + return ( fDistSq <= aRadiusSquared ); +} + + +bool CBBOX2D::Intersects( const CBBOX2D &aBBox ) const +{ + wxASSERT( IsInitialized() ); + wxASSERT( aBBox.IsInitialized() ); + + bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x ); + bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y ); + + return ( x && y ); +} + + +bool CBBOX2D::Inside( const SFVEC2F &aPoint ) const +{ + wxASSERT( IsInitialized() ); + + return ( ( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) && + ( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) ); +} + + +float CBBOX2D::Area() const +{ + SFVEC2F extent = GetExtent(); + return extent.x * extent.y; +} + + +// http://tavianator.com/fast-branchless-raybounding-box-intersections/ +bool CBBOX2D::Intersect( const RAY2D &aRay, float *t ) const +{ + wxASSERT( t ); + + float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float tmin = glm::min( tx1, tx2 ); + float tmax = glm::max( tx1, tx2 ); + + float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + tmin = glm::max( tmin, glm::min( ty1, ty2 ) ); + tmax = glm::min( tmax, glm::max( ty1, ty2 ) ); + + if( tmin > 0.0f ) + *t = tmin; + else + *t = tmax; + + return (tmax >= 0.0f) && (tmax >= tmin); +} + + +bool CBBOX2D::Intersect( const RAYSEG2D &aRaySeg ) const +{ + float tx1 = (m_min.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x; + float tx2 = (m_max.x - aRaySeg.m_Start.x) * aRaySeg.m_InvDir.x; + + float tmin = glm::min( tx1, tx2 ); + float tmax = glm::max( tx1, tx2 ); + + float ty1 = (m_min.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y; + float ty2 = (m_max.y - aRaySeg.m_Start.y) * aRaySeg.m_InvDir.y; + + tmin = glm::max( tmin, glm::min( ty1, ty2 ) ); + tmax = glm::min( tmax, glm::max( ty1, ty2 ) ); + + if( (tmax >= 0.0f) && (tmax >= tmin) ) + { + float t = (tmin > 0.0f)?tmin:tmax; + return ( t < aRaySeg.m_Length ); + } + + return false; +} + + +bool CBBOX2D::Intersect( const RAY2D &aRay, float *aOutHitT0, float *aOutHitT1 ) const +{ + wxASSERT( aOutHitT0 ); + wxASSERT( aOutHitT1 ); + + float tx1 = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + float tx2 = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float tmin = glm::min( tx1, tx2 ); + float tmax = glm::max( tx1, tx2 ); + + float ty1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + float ty2 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + tmin = glm::max( tmin, glm::min( ty1, ty2 ) ); + tmax = glm::min( tmax, glm::max( ty1, ty2 ) ); + + *aOutHitT0 = (tmin > 0.0f)?tmin:0.0f; + *aOutHitT1 = tmax; + + return (tmax >= 0.0f) && (tmax >= tmin); +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.h new file mode 100644 index 0000000000..4ad88c5ab8 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cbbox2d.h @@ -0,0 +1,216 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cbbox2d.h + * @brief 2D Bounding Box class definition + */ + +#ifndef _CBBOX2D_H_ +#define _CBBOX2D_H_ + +#include "3d_xv3d/xv3d_types.h" +#include "3d_rendering/3d_render_raytracing/ray.h" + + +/** + * Class CBBOX + * manages a bounding box defined by two SFVEC2F min max points. + */ +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CBBOX2D +{ + +public: + + /** + * Constructor CBBOX2D + * Create with default values a bounding box (not inizialized) + */ + CBBOX2D(); + + /** + * Constructor CBBOX2D + * Initialize a bounding box with a given point + * @param aPbInit a point for the bounding box initialization + */ + CBBOX2D( const SFVEC2F &aPbInit ); + + /** + * Constructor CBBOX2D + * Initialize a bounding box with a minimon and a maximun point + * @param aPbMin the minimun point to initialize the bounding box + * @param aPbMax the maximun point to initialize the bounding box + */ + CBBOX2D( const SFVEC2F &aPbMin, const SFVEC2F &aPbMax ); + + ~CBBOX2D(); + + + /** + * Function Set + * Set bounding box with new parameters + * @param aPbMin the minimun point to initialize the bounding box + * @param aPbMax the maximun point to initialize the bounding box + */ + void Set( const SFVEC2F &aPbMin, const SFVEC2F &aPbMax ); + + /** + * Function Set + * Set bounding box based on another bounding box + * @param CBBOX2D a bounding box to initialize this one + */ + void Set( const CBBOX2D &aBBox ); + + /** + * Function Union + * recalculate the bounding box adding a point + * @param aPoint the point to be bounded + */ + void Union( const SFVEC2F &aPoint ); + + /** + * Function Union + * recalculate the bounding box adding other bounding box + * @param aBBox the bounding box to be bounded + */ + void Union( const CBBOX2D &aBBox ); + + /** + * Function Scale + * scales a bounding box by its center + * @param aScale scale factor to apply + */ + void Scale( float aScale ); + + /** + * Function ScaleNextUp + * scales a bounding box to the next float representation making it larger + */ + void ScaleNextUp(); + + /** + * Function ScaleNextDown + * scales a bounding box to the next float representation making it smaller + */ + void ScaleNextDown(); + + /** + * Function Intersects + * test if a bounding box intersects this box + * @param aBBox the bounding box to check if it inversects + */ + bool Intersects( const CBBOX2D &aBBox ) const; + + /** + * Function Intersects + * test if a circle intersects this box + * @param aBBox the bounding box to check if it intersects + */ + bool Intersects( const SFVEC2F &aCenter, float aRadiusSquared ) const; + + /** + * Function Inside + * check is a point is inside this bounding box + * @param aPoint point to test + */ + bool Inside( const SFVEC2F &aPoint ) const; + + /** + * Function Area + * calculate the area of a bounding box + * @return float - area of this bounding box + */ + float Area() const; + + /** + * Function IsInitialized + * check if this bounding box is already initialized + * @return bool - return true if it was initialized, false if otherwise + */ + bool IsInitialized() const; + + /** + * Function Reset + * reset the bounding box to zero and de-initialized it + */ + void Reset(); + + /** + * Function GetCenter + * return the center point of the bounding box + * @return SFVEC2F - the position of the center of this bounding box + */ + SFVEC2F GetCenter() const; + + /** + * Function GetExtent + * @return SFVEC2F - max-min + */ + SFVEC2F GetExtent() const; + + /** + * Function Min + * return the minimun vertex pointer + * @return SFVEC2F - the minimun vertice position + */ + const SFVEC2F &Min() const { return m_min; } + + /** + * Function Max + * return the maximum vertex pointer + * @return SFVEC2F - the maximun vertice position + */ + const SFVEC2F &Max() const { return m_max; } + + + /** + * Function MaxDimension + * @return the index of the max dimention (0=x, 1=y) + */ + unsigned int MaxDimension() const; + + /** + * Function Perimeter + * @return the surface are of the box + */ + float Perimeter() const; + + /** + * Function Intersect + * @param aRay = ray to intersect the box + * @param t = distance point of the ray of the intersection (if true) + * @return true if the ray hits the box + */ + bool Intersect( const RAY2D &aRay, float *t ) const; + + bool Intersect( const RAY2D &aRay, float *aOutHitT0, float *aOutHitT1 ) const; + + bool Intersect( const RAYSEG2D &aRaySeg ) const; + +private: + SFVEC2F m_min; ///< point of the lower position of the bounding box + SFVEC2F m_max; ///< point of the higher position of the bounding box +}; + +#endif // CBBox2d_h diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h new file mode 100644 index 0000000000..fc1d7ec020 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cfilledcircle2d.h @@ -0,0 +1,59 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cfilledcircle2d.h + * @brief + */ + +#ifndef _CFILLEDCIRCLE2D_H_ +#define _CFILLEDCIRCLE2D_H_ + +#include "cobject2d.h" + +class GLM_ALIGN(CLASS_ALIGNMENT) CFILLEDCIRCLE2D : public COBJECT2D +{ +public: + float GetRadius() const { return m_radius; } + const SFVEC2F &GetCenter() const { return m_center; } + float GetRadiusSquared() const { return m_radius_squared; } + +private: + SFVEC2F m_center; + float m_radius; + float m_radius_squared; + +public: + CFILLEDCIRCLE2D( const SFVEC2F &aCenter, float aRadius, const BOARD_ITEM &aBoardItem ); + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +#endif // _CFILLEDCIRCLE2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.cpp new file mode 100644 index 0000000000..b6418c8e1d --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.cpp @@ -0,0 +1,68 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cobject2d.cpp + * @brief + */ + +#include "cobject2d.h" +#include + + +COBJECT2D_STATS *COBJECT2D_STATS::s_instance = 0; + + +COBJECT2D::COBJECT2D( OBJECT2D_TYPE aObjType, const BOARD_ITEM &aBoardItem ) + : m_boardItem(aBoardItem) +{ + m_obj_type = aObjType; + COBJECT2D_STATS::Instance().AddOne( aObjType ); +} + + +static const char *OBJECT2D_STR[OBJ2D_MAX] = +{ + "OBJ2D_FILLED_CIRCLE", + "OBJ2D_CSG", + "OBJ2D_POLYGON", + "OBJ2D_DUMMYBLOCK", + "OBJ2D_POLYGON4PT", + "OBJ2D_RING", + "OBJ2D_ROUNDSEG", + "OBJ2D_TRIANGLE", + "OBJ2D_CONTAINER", + "OBJ2D_BVHCONTAINER" +}; + + +void COBJECT2D_STATS::PrintStats() +{ + printf( "OBJ2D Statistics:\n" ); + + for( unsigned int i = 0; i < OBJ2D_MAX; ++i ) + { + printf( " %20s %u\n", OBJECT2D_STR[i], m_counter[i] ); + } +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.h new file mode 100644 index 0000000000..a129bd04ef --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cobject2d.h @@ -0,0 +1,160 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cobject2d.h + * @brief + */ + +#ifndef _COBJECT2D_H_ +#define _COBJECT2D_H_ + +#include "3d_xv3d/xv3d_types.h" +#include "cbbox2d.h" +#include + +#include + +enum INTERSECTION_RESULT +{ + INTR_MISSES, + INTR_INTERSECTS, + INTR_FULL_INSIDE +}; + + +enum OBJECT2D_TYPE +{ + OBJ2D_FILLED_CIRCLE, + OBJ2D_CSG, + OBJ2D_POLYGON, + OBJ2D_DUMMYBLOCK, + OBJ2D_POLYGON4PT, + OBJ2D_RING, + OBJ2D_ROUNDSEG, + OBJ2D_TRIANGLE, + OBJ2D_CONTAINER, + OBJ2D_BVHCONTAINER, + OBJ2D_MAX +}; + + +class GLM_ALIGN(CLASS_ALIGNMENT) COBJECT2D +{ +protected: + CBBOX2D m_bbox; + SFVEC2F m_centroid; + OBJECT2D_TYPE m_obj_type; + + const BOARD_ITEM &m_boardItem; +public: + + COBJECT2D( OBJECT2D_TYPE aObjType, const BOARD_ITEM &aBoardItem ); + virtual ~COBJECT2D() {} + + const BOARD_ITEM &GetBoardItem() const { return m_boardItem; } + + /** Function Overlaps + * @brief Test if the box overlaps the object + * Conformance + * The function overlaps implements function Overlaps from the OGC Simple Feature Specification. + * http://www.opengeospatial.org/standards/sfa + * a.Overlaps(b) ⇔ ( dim(I(a)) = dim(I(b)) = dim(I(a) ∩ I(b))) ∧ (a ∩ b ≠ a) ∧ (a ∩ b ≠ b) + * It means that the result dimension of an overlap is the same dimentions of the bounding box + * (so the overlap cannot be a point or a line) and one of the boxes cannot full contain the other + * box. + * @param aBBox - The bounding box to test + * @return true if the BBox intersects the object or is inside it + */ + virtual bool Overlaps( const CBBOX2D &aBBox ) const = 0; + + /** Function Intersects + * @brief Intersects - a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅) + * It intersects if the result intersection is not null + * @param aBBox + * @return + */ + virtual bool Intersects( const CBBOX2D &aBBox ) const = 0; + + /** Function Intersect + * @brief Intersect + * @param aSegRay + * @param aOutT a value between 0.0 and 1.0 in relation to the time of the hit of the segment + * @param aNormalOut + * @return + */ + virtual bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const = 0; + + /** Function IsBBoxInside + * @brief Tests if the bouding is out, intersects or is complety inside + * @param aBBox - The bounding box to test + * @return INTERSECTION_RESULT + */ + virtual INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const = 0; + + virtual bool IsPointInside( const SFVEC2F &aPoint ) const = 0; + + const CBBOX2D &GetBBox() const { return m_bbox; } + + const SFVEC2F &GetCentroid() const { return m_centroid; } + + const OBJECT2D_TYPE GetObjectType() const { return m_obj_type; } +}; + + + +/// Implements a class for object statistics +/// using Singleton pattern +class COBJECT2D_STATS +{ +public: + void ResetStats() { memset( m_counter, 0, sizeof(unsigned int) * OBJ2D_MAX ); } + + unsigned int GetCountOf( OBJECT2D_TYPE aObjType ) const { return m_counter[aObjType]; } + + void AddOne( OBJECT2D_TYPE aObjType ) { m_counter[aObjType]++; } + + void PrintStats(); + + static COBJECT2D_STATS &Instance() + { + if( !s_instance ) + s_instance = new COBJECT2D_STATS; + + return *s_instance; + } + +private: + COBJECT2D_STATS(){ ResetStats(); } + COBJECT2D_STATS( const COBJECT2D_STATS &old ); + const COBJECT2D_STATS &operator=( const COBJECT2D_STATS &old ); + ~COBJECT2D_STATS(){} + +private: + unsigned int m_counter[OBJ2D_MAX]; + + static COBJECT2D_STATS *s_instance; +}; + +#endif // _COBJECT2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h new file mode 100644 index 0000000000..e4a7d8cd3e --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon2d.h @@ -0,0 +1,154 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cpolygon2d.h + * @brief + */ + +#ifndef _CPOLYGON2D_H_ +#define _CPOLYGON2D_H_ + +#include "cobject2d.h" +#include "../accelerators/ccontainer2d.h" +#include +#include +#include + + +typedef struct +{ + SFVEC2F m_Start; + float m_inv_JY_minus_IY; + float m_JX_minus_IX; +}POLYSEGMENT; + + +typedef struct +{ + SFVEC2F m_Start; + SFVEC2F m_End; +}SEG_NORMALS; + + +typedef struct +{ + SFVEC2F m_Start; + SFVEC2F m_Precalc_slope; + SEG_NORMALS m_Normals; +}SEGMENT_WITH_NORMALS; + + +typedef std::vector< POLYSEGMENT > SEGMENTS; + + +/// This list will be used to test ray2d intersections. It will be a subset +/// of an original polygon. The normals will be passed already interpolated. +typedef std::vector< SEGMENT_WITH_NORMALS > SEGMENTS_WIDTH_NORMALS; + + +/// This structured will be used to handle a sub set of a polygon. +/// It can contain multiple closed polygons and holes. +/// It will be used to test if points are inside. A point will be inside the +/// polygon if it is not inside a hole and it is inside a Outer polygon. +typedef struct +{ + std::vector m_Outers; + std::vector m_Holes; +}OUTERS_AND_HOLES; + + +/// This class represents a sub polygon block. This polygon block was created +/// from a general polygon definition that was sub divided and create blocks of +/// polygons. This polygon class represent a sub part of that main polygon. +/// There is information for the contours (used to test the ray2d intersection) +/// and a close definition of the block polygon to test if a point is inside. +class GLM_ALIGN(CLASS_ALIGNMENT) CPOLYGONBLOCK2D : public COBJECT2D +{ +private: + /// This is the outter part of the polygon. This list is used to test a ray + /// intersection with the boundaries of this sub polygon. + /// It contains also the interpolated normals that are passed from the main + /// polygon. + SEGMENTS_WIDTH_NORMALS m_open_segments; + + /// A polygon block can have multiple polygon and holes + OUTERS_AND_HOLES m_outers_and_holes; + +public: + CPOLYGONBLOCK2D( const SEGMENTS_WIDTH_NORMALS &aOpenSegmentList, + const OUTERS_AND_HOLES &aOuter_and_holes, + const BOARD_ITEM &aBoardItem ); + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +/// This dummy block will be defined by a 2d box size. If the point is inside +/// the bounding box it will return allways true. However, the intersection with +/// a ray will return allways false. +/// This is used as a sub block extrated from polygon (pcb polygon areas) and +/// represents an area that is full filled. +class GLM_ALIGN(CLASS_ALIGNMENT) CDUMMYBLOCK2D : public COBJECT2D +{ + +public: + CDUMMYBLOCK2D(const SFVEC2F &aPbMin, const SFVEC2F &aPbMax , const BOARD_ITEM &aBoardItem ); + CDUMMYBLOCK2D( const CBBOX2D &aBBox, const BOARD_ITEM &aBoardItem ); + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + +/** + * @brief Convert_path_polygon_to_polygon_blocks_and_dummy_blocks + * This function will use a polygon in the format of the ClipperLib::Path + * will process it and will create multiple 2d objects (CPOLYGONBLOCK2D and + * CDUMMYBLOCK2D) that can be used to represent this polygon area. + * @param aMainPath - the polygon are that was converted from the pcb board + * @param aDstContainer - the destination container to put the created sub blocks + * @param aBiuTo3DunitsScale - the rendering target 3d scale + * @param aDivFactor - a division factor (in 3Dunits) to divide the polygon plane, 0.0f will use the internal polygon segm statistics + */ +void Convert_path_polygon_to_polygon_blocks_and_dummy_blocks(const SHAPE_POLY_SET &aMainPath, + CGENERICCONTAINER2D &aDstContainer, + float aBiuTo3DunitsScale, + float aDivFactor, + const BOARD_ITEM &aBoardItem ); + +void Polygon_Calc_BBox_3DU(const SHAPE_POLY_SET &aPolysList, CBBOX2D &aOutBBox , float aBiuTo3DunitsScale ); +void Polygon_Convert( const KI_POLYGON &aPolygon, ClipperLib::Path &aOutPath, CBBOX2D &aOutBBox, float aBiuTo3DunitsScale ); + +void Polygon2d_TestModule(); + +#endif // _CPOLYGON2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h new file mode 100644 index 0000000000..3ef3396101 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cpolygon4pts2d.h @@ -0,0 +1,73 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cpolygon4pts2d.h + * @brief A simplified 4 point polygon + */ + +#ifndef _CPOLYGON4PTS2D_H_ +#define _CPOLYGON4PTS2D_H_ + +#include "cobject2d.h" + +/** + * This handles simple polygons with 4 points. Used for pads. + * (rectangles, trapezoids, with rotation.etc) + * This is a simplified version of the cpolygon2d class + */ +class GLM_ALIGN(CLASS_ALIGNMENT) CPOLYGON4PTS2D : public COBJECT2D +{ +private: + SFVEC2F m_segments[4]; + SFVEC2F m_precalc_slope[4]; + SFVEC2F m_seg_normal[4]; + +public: + CPOLYGON4PTS2D( const SFVEC2F &v1, + const SFVEC2F &v2, + const SFVEC2F &v3, + const SFVEC2F &v4, + const BOARD_ITEM &aBoardItem ); + + const SFVEC2F &GetV0() const { return m_segments[0]; } + const SFVEC2F &GetV1() const { return m_segments[1]; } + const SFVEC2F &GetV2() const { return m_segments[2]; } + const SFVEC2F &GetV3() const { return m_segments[3]; } + + const SFVEC2F &GetN0() const { return m_seg_normal[0]; } + const SFVEC2F &GetN1() const { return m_seg_normal[1]; } + const SFVEC2F &GetN2() const { return m_seg_normal[2]; } + const SFVEC2F &GetN3() const { return m_seg_normal[3]; } + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +#endif // _CPOLYGON4PTS2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cring2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cring2d.h new file mode 100644 index 0000000000..7a414b597a --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/cring2d.h @@ -0,0 +1,65 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cring2d.h + * @brief + */ + +#ifndef _CRING2D_H_ +#define _CRING2D_H_ + +#include "cobject2d.h" + +class GLM_ALIGN(CLASS_ALIGNMENT) CRING2D : public COBJECT2D +{ +public: + const SFVEC2F &GetCenter() const { return m_center; } + float GetInnerRadius() const { return m_inner_radius; } + float GetOuterRadius() const { return m_outer_radius; } + + float GetInnerRadiusSquared() const { return m_inner_radius_squared; } + float GetOuterRadiusSquared() const { return m_outer_radius_squared; } + +private: + SFVEC2F m_center; + float m_inner_radius; + float m_outer_radius; + float m_inner_radius_squared; + float m_outer_radius_squared; + +public: + CRING2D( const SFVEC2F &aCenter, float aInnerRadius, float aOuterRadius, + const BOARD_ITEM &aBoardItem ); + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +#endif // _CRING2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.cpp new file mode 100644 index 0000000000..c78a746f05 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.cpp @@ -0,0 +1,309 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 croundsegment2d.cpp + * @brief + */ + +#include "croundsegment2d.h" +#include + + +CROUNDSEGMENT2D::CROUNDSEGMENT2D( const SFVEC2F &aStart, const SFVEC2F &aEnd, float aWidth, + const BOARD_ITEM &aBoardItem ) : + COBJECT2D( OBJ2D_ROUNDSEG, aBoardItem ), + m_segment( aStart, aEnd ) +{ + m_radius = (aWidth / 2.0f); + m_radius_squared = m_radius * m_radius; + m_width = aWidth; + + SFVEC2F leftRadiusOffset( -m_segment.m_Dir.y * m_radius, m_segment.m_Dir.x * m_radius); + m_leftStart = aStart + leftRadiusOffset; + m_leftEnd = aEnd + leftRadiusOffset; + m_leftEnd_minus_start = m_leftEnd - m_leftStart; + m_leftDir = glm::normalize( m_leftEnd_minus_start ); + + SFVEC2F rightRadiusOffset( -leftRadiusOffset.x, -leftRadiusOffset.y ); + m_rightStart = aEnd + rightRadiusOffset; + m_rightEnd = aStart + rightRadiusOffset; + m_rightEnd_minus_start = m_rightEnd - m_rightStart; + m_rightDir = glm::normalize( m_rightEnd_minus_start ); + + m_bbox.Reset(); + m_bbox.Set( aStart, aEnd ); + m_bbox.Set( m_bbox.Min() - SFVEC2F( m_radius, m_radius ), m_bbox.Max() + SFVEC2F( m_radius, m_radius ) ); + m_bbox.ScaleNextUp(); + m_centroid = m_bbox.GetCenter(); + + wxASSERT( m_bbox.IsInitialized() ); +} + + +bool CROUNDSEGMENT2D::Intersects( const CBBOX2D &aBBox ) const +{ + if( !m_bbox.Intersects( aBBox ) ) + return false; + + if( (aBBox.Max().x > m_bbox.Max().x) && + (aBBox.Max().y > m_bbox.Max().x) && + (aBBox.Min().x < m_bbox.Min().x) && + (aBBox.Min().y < m_bbox.Min().y) + ) + return true; + + SFVEC2F v[4]; + + v[0] = aBBox.Min(); + v[1] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ); + v[2] = aBBox.Max(); + v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ); + + // Test against the main rectangle segment + if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[0], v[1] - v[0] ) ) return true; + if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[1], v[2] - v[1] ) ) return true; + if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[2], v[3] - v[2] ) ) return true; + if( IntersectSegment( m_leftStart, m_leftEnd_minus_start, v[3], v[0] - v[3] ) ) return true; + + if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[0], v[1] - v[0] ) ) return true; + if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[1], v[2] - v[1] ) ) return true; + if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[2], v[3] - v[2] ) ) return true; + if( IntersectSegment( m_rightStart, m_rightEnd_minus_start, v[3], v[0] - v[3] ) ) return true; + + // Test the two circles + if( aBBox.Intersects( m_segment.m_Start, m_radius_squared ) ) return true; + if( aBBox.Intersects( m_segment.m_End, m_radius_squared ) ) return true; + + return false; +} + + +bool CROUNDSEGMENT2D::Overlaps( const CBBOX2D &aBBox ) const +{ + // NOT IMPLEMENTED + return false; +} + + +bool CROUNDSEGMENT2D::Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const +{ + wxASSERT( aOutT ); + wxASSERT( aNormalOut ); + + bool start_is_inside = IsPointInside( aSegRay.m_Start ); + bool end_is_inside = IsPointInside( aSegRay.m_End ); + + // If segment if inside there are no hits + if( start_is_inside && end_is_inside ) + return false; + + bool hitted = false; + + float closerHitT = FLT_MAX; + float farHitT = FLT_MAX; + + SFVEC2F closerHitNormal; + SFVEC2F farHitNormal; + + float leftSegT; + bool leftSegmentHit = aSegRay.IntersectSegment( m_leftStart, m_leftEnd_minus_start, &leftSegT ); + + if( leftSegmentHit ) + { + hitted = true; + closerHitT = leftSegT; + farHitT = leftSegT; + + closerHitNormal = SFVEC2F( -m_leftDir.y, m_leftDir.x ); + farHitNormal = SFVEC2F( -m_leftDir.y, m_leftDir.x ); + } + + float rightSegT; + bool rightSegmentHit = aSegRay.IntersectSegment( m_rightStart, m_rightEnd_minus_start, &rightSegT ); + + if( rightSegmentHit ) + { + if( !start_is_inside ) + if( (hitted == false) || (rightSegT < closerHitT) ) + { + closerHitT = rightSegT; + closerHitNormal = SFVEC2F( -m_rightDir.y, m_rightDir.x ); + } + + if( start_is_inside ) + if( (hitted == false) || (rightSegT > farHitT) ) + { + farHitT = rightSegT; + farHitNormal = SFVEC2F( -m_rightDir.y, m_rightDir.x ); + } + + hitted = true; + } + + float circleStart_T0; + float circleStart_T1; + SFVEC2F circleStart_N0; + SFVEC2F circleStart_N1; + + bool startCircleHit = aSegRay.IntersectCircle( m_segment.m_Start, m_radius, + &circleStart_T0, &circleStart_T1, + &circleStart_N0, &circleStart_N1 ); + + if( startCircleHit ) + { + if( circleStart_T0 > 0.0f ) + { + if( !start_is_inside ) + if( (hitted == false) || (circleStart_T0 < closerHitT) ) + { + closerHitT = circleStart_T0; + closerHitNormal = circleStart_N0; + } + + if( start_is_inside ) + if( (hitted == false) || (circleStart_T1 > farHitT) ) + { + farHitT = circleStart_T1; + farHitNormal = circleStart_N1; + } + } + else + { + // This can only happen if the ray starts inside + if( (hitted == false) || (circleStart_T1 > farHitT) ) + { + farHitT = circleStart_T1; + farHitNormal = circleStart_N1; + } + } + + hitted = true; + } + + float circleEnd_T0; + float circleEnd_T1; + SFVEC2F circleEnd_N0; + SFVEC2F circleEnd_N1; + + bool rightCircleHit = aSegRay.IntersectCircle( m_segment.m_End, m_radius, + &circleEnd_T0, &circleEnd_T1, + &circleEnd_N0, &circleEnd_N1 ); + if( rightCircleHit ) + { + if( circleEnd_T0 > 0.0f ) + { + if( !start_is_inside ) + if( (hitted == false) || (circleEnd_T0 < closerHitT) ) + { + closerHitT = circleEnd_T0; + closerHitNormal = circleEnd_N0; + } + + if( start_is_inside ) + if( (hitted == false) || (circleEnd_T1 > farHitT) ) + { + farHitT = circleEnd_T1; + farHitNormal = circleEnd_N1; + } + } + else + { + // This can only happen if the ray starts inside + if( (hitted == false) || (circleEnd_T1 > farHitT) ) + { + farHitT = circleEnd_T1; + farHitNormal = circleEnd_N1; + } + } + + hitted = true; + } + + if( hitted ) + { + if( !start_is_inside ) + { + *aOutT = closerHitT; + //wxASSERT( (closerHitT > 0.0f) && (closerHitT <= 1.0f) ); + *aNormalOut = closerHitNormal; + } + else + { + wxASSERT( (farHitT > 0.0f) && (farHitT <= 1.0f) ); + *aOutT = farHitT; + *aNormalOut = farHitNormal; + } + } + + return hitted; +} + + +INTERSECTION_RESULT CROUNDSEGMENT2D::IsBBoxInside( const CBBOX2D &aBBox ) const +{ + if( !m_bbox.Intersects( aBBox ) ) + return INTR_MISSES; + + SFVEC2F v[4]; + + v[0] = aBBox.Min(); + v[1] = aBBox.Max(); + v[2] = SFVEC2F( aBBox.Min().x, aBBox.Max().y ); + v[3] = SFVEC2F( aBBox.Max().x, aBBox.Min().y ); + + bool isInside[4]; + + isInside[0] = IsPointInside( v[0] ); + isInside[1] = IsPointInside( v[1] ); + isInside[2] = IsPointInside( v[2] ); + isInside[3] = IsPointInside( v[3] ); + + // Check if all points are inside the circle + if( isInside[0] && + isInside[1] && + isInside[2] && + isInside[3] ) + return INTR_FULL_INSIDE; + + // Check if any point is inside the circle + if( isInside[0] || + isInside[1] || + isInside[2] || + isInside[3] ) + return INTR_INTERSECTS; + + return INTR_MISSES; +} + + +bool CROUNDSEGMENT2D::IsPointInside( const SFVEC2F &aPoint ) const +{ + float dSquared = m_segment.DistanceToPointSquared( aPoint ); + + if( dSquared <= m_radius_squared ) + return true; + + return false; +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h new file mode 100644 index 0000000000..7431b00cbc --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/croundsegment2d.h @@ -0,0 +1,89 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 croundsegment2d.h + * @brief + */ + +#ifndef _CROUNDSEGMENT2D_H_ +#define _CROUNDSEGMENT2D_H_ + +#include "cobject2d.h" + +class GLM_ALIGN(CLASS_ALIGNMENT) CROUNDSEGMENT2D : public COBJECT2D +{ + +friend class CROUNDSEG; + +private: + RAYSEG2D m_segment; + + SFVEC2F m_leftStart; + SFVEC2F m_leftEnd; + SFVEC2F m_leftEnd_minus_start; + SFVEC2F m_leftDir; + + SFVEC2F m_rightStart; + SFVEC2F m_rightEnd; + SFVEC2F m_rightEnd_minus_start; + SFVEC2F m_rightDir; + + float m_radius; + float m_radius_squared; + float m_width; + +public: + CROUNDSEGMENT2D( const SFVEC2F &aStart, const SFVEC2F &aEnd, float aWidth, + const BOARD_ITEM &aBoardItem ); + + float GetRadius() const { return m_radius; } + float GetRadiusSquared() const { return m_radius_squared; } + float GetWidth() const { return m_width; } + float GetLenght() const { return m_segment.m_Length; } + + const SFVEC2F &GetStart() const { return m_segment.m_Start; } + const SFVEC2F &GetEnd() const { return m_segment.m_End; } + const SFVEC2F &GetEnd_minus_Start() const { return m_segment.m_End_minus_start; } + + const SFVEC2F &GetLeftStar() const { return m_leftStart; } + const SFVEC2F &GetLeftEnd() const { return m_leftEnd; } + const SFVEC2F &GetLeftEnd_minus_Start() const { return m_leftEnd_minus_start; } + const SFVEC2F &GetLeftDir() const { return m_leftDir; } + + const SFVEC2F &GetRightStar() const { return m_rightStart; } + const SFVEC2F &GetRightEnd() const { return m_rightEnd; } + const SFVEC2F &GetRightEnd_minus_Start() const { return m_rightEnd_minus_start; } + const SFVEC2F &GetRightDir() const { return m_rightDir; } + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +#endif // _CROUNDSEGMENT2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h new file mode 100644 index 0000000000..34769fc020 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes2D/ctriangle2d.h @@ -0,0 +1,75 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ctriangle2d.h + * @brief + */ + +#ifndef _CTRIANGLE2D_H_ +#define _CTRIANGLE2D_H_ + +#include "cobject2d.h" +#include "../accelerators/ccontainer2d.h" +#include +#include +#include + +class GLM_ALIGN(CLASS_ALIGNMENT) CTRIANGLE2D : public COBJECT2D +{ +private: + SFVEC2F p1; + SFVEC2F p2; + SFVEC2F p3; + + float m_inv_denominator; + float m_p2y_minus_p3y; + float m_p3x_minus_p2x; + float m_p3y_minus_p1y; + float m_p1x_minus_p3x; + +public: + CTRIANGLE2D ( const SFVEC2F &aV1, + const SFVEC2F &aV2, + const SFVEC2F &aV3, + const BOARD_ITEM &aBoardItem ); + + const SFVEC2F &GetP1() const { return p1; } + const SFVEC2F &GetP2() const { return p2; } + const SFVEC2F &GetP3() const { return p3; } + + // Imported from COBJECT2D + bool Overlaps( const CBBOX2D &aBBox ) const; + bool Intersects( const CBBOX2D &aBBox ) const; + bool Intersect( const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut ) const; + INTERSECTION_RESULT IsBBoxInside( const CBBOX2D &aBBox ) const; + bool IsPointInside( const SFVEC2F &aPoint ) const; +}; + + +void Convert_shape_line_polygon_to_triangles( const SHAPE_POLY_SET &aPolyList, + CGENERICCONTAINER2D &aDstContainer, + float aBiuTo3DunitsScale, + const BOARD_ITEM &aBoardItem ); +#endif // _CTRIANGLE2D_H_ diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.cpp new file mode 100644 index 0000000000..f771e95c94 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.cpp @@ -0,0 +1,373 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cbbox.cpp + * @brief Bounding Box class implementation + */ +#include "3d_math/3d_fastmath.h" + +#include "cbbox.h" +#include +#include // For the wxASSERT + + +CBBOX::CBBOX() +{ + Reset(); +} + + +CBBOX::CBBOX( const SFVEC3F &aPbInit ) +{ + m_min = aPbInit; + m_max = aPbInit; +} + + +CBBOX::CBBOX( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax ) +{ + Set( aPbMin, aPbMax ); +} + + +CBBOX::~CBBOX() +{ +} + + +void CBBOX::Set( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax ) +{ + m_min.x = fminf( aPbMin.x, aPbMax.x ); + m_min.y = fminf( aPbMin.y, aPbMax.y ); + m_min.z = fminf( aPbMin.z, aPbMax.z ); + + m_max.x = fmaxf( aPbMin.x, aPbMax.x ); + m_max.y = fmaxf( aPbMin.y, aPbMax.y ); + m_max.z = fmaxf( aPbMin.z, aPbMax.z ); +} + + +void CBBOX::Set( const CBBOX &aBBox ) +{ + wxASSERT( aBBox.IsInitialized() ); + + Set( aBBox.Min(), aBBox.Max() ); +} + + +bool CBBOX::IsInitialized() const +{ + return !( ( FLT_MAX == m_min.x) || + ( FLT_MAX == m_min.y) || + ( FLT_MAX == m_min.z) || + (-FLT_MAX == m_max.x) || + (-FLT_MAX == m_max.y) || + (-FLT_MAX == m_max.z) ); +} + + +void CBBOX::Reset() +{ + m_min = SFVEC3F( FLT_MAX, FLT_MAX, FLT_MAX ); + m_max = SFVEC3F(-FLT_MAX,-FLT_MAX,-FLT_MAX ); +} + + +void CBBOX::Union( const SFVEC3F &aPoint ) +{ + // get the minimun value between the added point and the existent bounding box + m_min.x = fminf( m_min.x, aPoint.x ); + m_min.y = fminf( m_min.y, aPoint.y ); + m_min.z = fminf( m_min.z, aPoint.z ); + + // get the maximun value between the added point and the existent bounding box + m_max.x = fmaxf( m_max.x, aPoint.x ); + m_max.y = fmaxf( m_max.y, aPoint.y ); + m_max.z = fmaxf( m_max.z, aPoint.z ); +} + + +void CBBOX::Union( const CBBOX &aBBox ) +{ + wxASSERT( aBBox.IsInitialized() ); + + // get the minimun value between the added bounding box and the existent bounding box + m_min.x = fmin( m_min.x, aBBox.m_min.x ); + m_min.y = fmin( m_min.y, aBBox.m_min.y ); + m_min.z = fmin( m_min.z, aBBox.m_min.z ); + + // get the maximun value between the added bounding box and the existent bounding box + m_max.x = fmax( m_max.x, aBBox.m_max.x ); + m_max.y = fmax( m_max.y, aBBox.m_max.y ); + m_max.z = fmax( m_max.z, aBBox.m_max.z ); +} + + +SFVEC3F CBBOX::GetCenter() const +{ + return (m_max + m_min) * 0.5f; +} + + +float CBBOX::GetCenter( unsigned int aAxis ) const +{ + wxASSERT( aAxis < 3 ); + return (m_max[aAxis] + m_min[aAxis]) * 0.5f; +} + + +const SFVEC3F CBBOX::GetExtent() const +{ + return m_max - m_min; +} + + +unsigned int CBBOX::MaxDimension() const +{ + unsigned int result = 0; + + SFVEC3F extent = GetExtent(); + + if( extent.y > extent.x ) result = 1; + if( extent.z > extent.y ) result = 2; + + return result; +} + + +float CBBOX::GetMaxDimension() const +{ + unsigned int max_dimensions_idx = 0; + + SFVEC3F extent = GetExtent(); + + if( extent.y > extent.x ) max_dimensions_idx = 1; + if( extent.z > extent.y ) max_dimensions_idx = 2; + + return extent[max_dimensions_idx]; +} + + +float CBBOX::SurfaceArea() const +{ + SFVEC3F extent = GetExtent(); + + return 2.0f * ( extent.x * extent.z + + extent.x * extent.y + + extent.y * extent.z ); +} + + +void CBBOX::Scale( float aScale ) +{ + wxASSERT( IsInitialized() ); + + SFVEC3F scaleV = SFVEC3F( aScale, aScale, aScale ); + SFVEC3F centerV = GetCenter(); + + m_min = (m_min - centerV) * scaleV + centerV; + m_max = (m_max - centerV) * scaleV + centerV; +} + + +void CBBOX::ScaleNextUp() +{ + m_min.x = NextFloatDown( m_min.x ); + m_min.y = NextFloatDown( m_min.y ); + m_min.z = NextFloatDown( m_min.z ); + + m_max.x = NextFloatUp( m_max.x ); + m_max.y = NextFloatUp( m_max.y ); + m_max.z = NextFloatUp( m_max.z ); +} + + +void CBBOX::ScaleNextDown() +{ + m_min.x = NextFloatUp( m_min.x ); + m_min.y = NextFloatUp( m_min.y ); + m_min.z = NextFloatUp( m_min.z ); + + m_max.x = NextFloatDown( m_max.x ); + m_max.y = NextFloatDown( m_max.y ); + m_max.z = NextFloatDown( m_max.z ); +} + + +bool CBBOX::Intersects( const CBBOX &aBBox ) const +{ + wxASSERT( IsInitialized() ); + wxASSERT( aBBox.IsInitialized() ); + + bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x ); + bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y ); + bool z = ( m_max.z >= aBBox.m_min.z ) && ( m_min.z <= aBBox.m_max.z ); + + return ( x && y && z ); +} + + +bool CBBOX::Inside( const SFVEC3F &aPoint ) const +{ + wxASSERT( IsInitialized() ); + + return (( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) && + ( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) && + ( aPoint.z >= m_min.z ) && ( aPoint.z <= m_max.z )); +} + + +float CBBOX::Volume() const +{ + wxASSERT( IsInitialized() ); + + SFVEC3F extent = GetExtent(); + + return extent.x * extent.y * extent.z; +} + + +SFVEC3F CBBOX::Offset( const SFVEC3F &p ) const +{ + return (p - m_min) / (m_max - m_min); +} + + +// Intersection code based on the book: +// "Physical Based Ray Tracing" (by Matt Pharr and Greg Humphrey) +// https://github.com/mmp/pbrt-v2/blob/master/src/core/geometry.cpp#L68 +// ///////////////////////////////////////////////////////////////////////// +#if 0 +bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) +{ + float t0 = 0.0f; + float t1 = FLT_MAX; + + for( unsigned int i = 0; i < 3; ++i ) + { + // Update interval for _i_th bounding box slab + float tNear = (m_min[i] - aRay.m_Origin[i]) * aRay.m_InvDir[i]; + float tFar = (m_max[i] - aRay.m_Origin[i]) * aRay.m_InvDir[i]; + + // Update parametric interval from slab intersection + if( tNear > tFar ) + { + // Swap + float ftemp = tNear; + tNear = tFar; + tFar = ftemp; + } + + t0 = tNear > t0 ? tNear : t0; + t1 = tFar < t1 ? tFar : t1; + + if( t0 > t1 ) + return false; + } + + if( aOutHitt0 ) *aOutHitt0 = t0; + if( aOutHitt1 ) *aOutHitt1 = t1; + + return true; +} +#else +// https://github.com/mmp/pbrt-v2/blob/master/src/accelerators/bvh.cpp#L126 +bool CBBOX::Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) const +{ + wxASSERT( aOutHitt0 ); + wxASSERT( aOutHitt1 ); + + const SFVEC3F bounds[2] = {m_min, m_max}; + + // Check for ray intersection against x and y slabs + float tmin = (bounds[ aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x; + float tmax = (bounds[1 - aRay.m_dirIsNeg[0]].x - aRay.m_Origin.x) * aRay.m_InvDir.x; + float tymin = (bounds[ aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y; + float tymax = (bounds[1 - aRay.m_dirIsNeg[1]].y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if( (tmin > tymax) || (tymin > tmax) ) + return false; + + tmin = (tymin > tmin)? tymin : tmin; + tmax = (tymax < tmax)? tymax : tmax; + + // Check for ray intersection against z slab + float tzmin = (bounds[ aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z; + float tzmax = (bounds[1 - aRay.m_dirIsNeg[2]].z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if( (tmin > tzmax) || (tzmin > tmax) ) + return false; + + tmin = (tzmin > tmin)? tzmin : tmin; + tmin = ( tmin < 0.0f)? 0.0f : tmin; + + tmax = (tzmax < tmax)? tzmax : tmax; + + *aOutHitt0 = tmin; + *aOutHitt1 = tmax; + + return true; +} +#endif + + +void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix ) +{ + wxASSERT( IsInitialized() ); + + SFVEC3F v1 = SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ); + SFVEC3F v2 = SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ); + + Reset(); + Union( v1 ); + Union( v2 ); +} + + +void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix ) +{ + wxASSERT( IsInitialized() ); + + // apply the transformation matrix for each of vertices of the bounding box + // and make a union with all vertices + CBBOX tmpBBox = CBBOX( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) ); + tmpBBox.Union( SFVEC3F( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) ); + + m_min = tmpBBox.m_min; + m_max = tmpBBox.m_max; +} + + +void CBBOX::debug() const +{ + printf( "min(%f, %f, %f) - max(%f, %f, %f)\n", m_min.x, m_min.y, m_min.z, + m_max.x, m_max.y, m_max.z ); +} diff --git a/3d-viewer/CBBox.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.h similarity index 54% rename from 3d-viewer/CBBox.h rename to 3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.h index f883cb6ba0..ccd2840185 100644 --- a/3d-viewer/CBBox.h +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox.h @@ -23,23 +23,22 @@ */ /** - * @file CBBox.h + * @file cbbox.h * @brief Bounding Box class definition */ -#ifndef CBBox_h -#define CBBox_h - -#define GLM_FORCE_RADIANS -#include -#include <3d_types.h> +#ifndef _CBBOX_H_ +#define _CBBOX_H_ +#include "3d_xv3d/xv3d_types.h" +#include "3d_rendering/3d_render_raytracing/ray.h" +#include // For the DBG( /** * Class CBBOX - * manages a bounding box defined by two S3D_VERTEX points. + * manages a bounding box defined by two SFVEC3F min max points. */ -class CBBOX +GLM_ALIGNED_STRUCT(CLASS_ALIGNMENT) CBBOX { public: @@ -55,7 +54,7 @@ public: * Initialize a bounding box with a given point * @param aPbInit a point for the bounding box initialization */ - CBBOX( const S3D_VERTEX &aPbInit ); + CBBOX( const SFVEC3F &aPbInit ); /** * Constructor CBBOX @@ -63,7 +62,7 @@ public: * @param aPbMin the minimun point to initialize the bounding box * @param aPbMax the maximun point to initialize the bounding box */ - CBBOX( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ); + CBBOX( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax ); ~CBBOX(); @@ -74,14 +73,16 @@ public: * @param aPbMin the minimun point to initialize the bounding box * @param aPbMax the maximun point to initialize the bounding box */ - void Set( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ); + void Set( const SFVEC3F &aPbMin, const SFVEC3F &aPbMax ); + + void Set( const CBBOX &aBBox ); /** * Function Union * recalculate the bounding box adding a point * @param aPoint the point to be bounded */ - void Union( const S3D_VERTEX &aPoint ); + void Union( const SFVEC3F &aPoint ); /** * Function Union @@ -98,18 +99,30 @@ public: void Scale( float aScale ); /** - * Function OverlapsBox - * test if a bounding box overlaps this box - * @param aBBox the bounding box to check if it overlaps + * Function ScaleNextUp + * scales a bounding box to the next float representation making it larger */ - bool OverlapsBox( const CBBOX &aBBox ) const; + void ScaleNextUp(); + + /** + * Function ScaleNextDown + * scales a bounding box to the next float representation making it smaller + */ + void ScaleNextDown(); + + /** + * Function Intersects + * test if a bounding box intersects this box + * @param aBBox the bounding box to check if it intersects + */ + bool Intersects( const CBBOX &aBBox ) const; /** * Function Inside * check is a point is inside this bounding box * @param aPoint point to test */ - bool Inside( const S3D_VERTEX &aPoint ) const; + bool Inside( const SFVEC3F &aPoint ) const; /** * Function ApplyTransformation @@ -134,10 +147,10 @@ public: float Volume() const; /** - * Function GLdebug - * render a wired bounding box using openGL + * Function debug + * output to stdout */ - void GLdebug() const; + void debug() const; /** * Function IsInitialized @@ -155,28 +168,86 @@ public: /** * Function GetCenter * return the center point of the bounding box - * @return S3D_VERTEX - the position of the center of this bounding box + * @return SFVEC3F - the position of the center of this bounding box */ - S3D_VERTEX GetCenter() const; + SFVEC3F GetCenter() const; + + /** + * Function GetCenter + * return the center point of the bounding box for one Axis (0, 1 or 2) + * @return float - the position of the center of this bounding box for the axis + */ + float GetCenter( unsigned int aAxis ) const; + + /** Function Offset + * + * @return SFVEC3F - return the offset relative to max-min + */ + SFVEC3F Offset( const SFVEC3F &p ) const; + + /** + * Function GetExtent + * @return SFVEC3F - max-min + */ + const SFVEC3F GetExtent() const; /** * Function Min * return the minimun vertex pointer - * @return S3D_VERTEX - the minimun vertice position + * @return SFVEC3F - the minimun vertice position */ - S3D_VERTEX Min() const; + const SFVEC3F &Min() const { return m_min; } /** * Function Max * return the maximum vertex pointer - * @return S3D_VERTEX - the maximun vertice position + * @return SFVEC3F - the maximun vertice position */ - S3D_VERTEX Max() const; + const SFVEC3F &Max() const { return m_max; } + + + /** + * Function MaxDimension + * @return the index of the max dimention (0=x, 1=y, 2=z) + */ + unsigned int MaxDimension() const; + + /** + * @brief GetMaxDimension + * @return the max dimension + */ + float GetMaxDimension() const; + + /** + * Function SurfaceArea + * @return the surface are of the box + */ + float SurfaceArea() const; + + /** + * Function Intersect + * @param aRay = ray to intersect the box + * @param t = distance point of the ray of the intersection (if true) + * @return true if the ray hits the box + */ + bool Intersect( const RAY &aRay, float *t ) const; + + bool Intersect( const RAY &aRay ) const; + + /** + * Function Intersect - Useful for get the enter and exit position + * If the ray starts inside the bbox, it will return aOutHitt0 = 0.0 + * @param aRay = ray to intersect the box + * @param aOutHitt0 = distance point of the ray of the intersection (if true) + * @param aOutHitt1 = distance point of the ray of the exit (if true) + * @return true if the ray hits the box + */ + bool Intersect( const RAY &aRay, float *aOutHitt0, float *aOutHitt1 ) const; private: - S3D_VERTEX m_min; ///< point of the lower position of the bounding box - S3D_VERTEX m_max; ///< point of the higher position of the bounding box - bool m_initialized; ///< initialization status of the bounding box. true - if initialized, false otherwise + + SFVEC3F m_min; ///< (12) point of the lower position of the bounding box + SFVEC3F m_max; ///< (12) point of the higher position of the bounding box }; #endif // CBBox_h diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox_ray.cpp b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox_ray.cpp new file mode 100644 index 0000000000..7e45a94c4b --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cbbox_ray.cpp @@ -0,0 +1,905 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cbbox_ray.cpp + * @brief Bounding Box - Ray test intersection + */ + +#include "cbbox.h" +#include +#include + +// This BBOX Ray intersection test have the following credits: + +// "This source code accompanies the Journal of Graphics Tools paper: +// +// "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes" +// by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor +// Computer Graphics Lab, TU Braunschweig, Germany and +// University of Koblenz-Landau, Germany +// +// This source code is public domain, but please mention us if you use it." + + +bool CBBOX::Intersect( const RAY &aRay, float *t ) const +{ + switch ( aRay.m_Classification ) + { + case MMM: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + // compute the intersection distance + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + + case MMP: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case MPM: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case MPP: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case PMM: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + + case PMP: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case PPM: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case PPP: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case OMM: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + ) + return false; + + *t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case OMP: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + ) + return false; + + *t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case OPM: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + ) + return false; + + *t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case OPP: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + ) + return false; + + *t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + + case MOM: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + + case MOP: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case POM: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t2 = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + + case POP: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t2 = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + if(t2 > *t) + *t = t2; + + return true; + } + + case MMO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + return true; + } + + case MPO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + return true; + } + + + case PMO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + return true; + } + + case PPO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + float t1 = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + if(t1 > *t) + *t = t1; + + return true; + } + + + case MOO: + { + if(( aRay.m_Origin.x < m_min.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + + *t = (m_max.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + return true; + } + + case POO: + { + if(( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + + *t = (m_min.x - aRay.m_Origin.x) * aRay.m_InvDir.x; + + return true; + } + + case OMO: + { + if(( aRay.m_Origin.y < m_min.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + + *t = (m_max.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + return true; + } + + case OPO: + { + if(( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + + *t = (m_min.y - aRay.m_Origin.y) * aRay.m_InvDir.y; + + return true; + } + + + case OOM: + { + if(( aRay.m_Origin.z < m_min.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + ) + return false; + + *t = (m_max.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + return true; + } + + case OOP: + { + if(( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + ) + return false; + + *t = (m_min.z - aRay.m_Origin.z) * aRay.m_InvDir.z; + + return true; + } + } + + return false; +} + + +bool CBBOX::Intersect( const RAY &aRay ) const +{ + switch ( aRay.m_Classification ) + { + case MMM: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + + case MMP: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + case MPM: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + case MPP: + { + if (( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + case PMM: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + + case PMP: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + case PPM: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + case PPP: + { + if (( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + case OMM: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyk * m_min.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_max.z + aRay.c_yz > 0) + ) + return false; + return true; + } + + case OMP: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyk * m_max.z - m_max.y + aRay.c_zy > 0) + || ( aRay.kbyj * m_min.y - m_min.z + aRay.c_yz < 0) + ) + return false; + return true; + } + + case OPM: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.jbyk * m_min.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_max.z + aRay.c_yz > 0) + ) + return false; + return true; + } + + case OPP: + { + if(( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y > m_max.y) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.jbyk * m_max.z - m_min.y + aRay.c_zy < 0) + || ( aRay.kbyj * m_max.y - m_min.z + aRay.c_yz < 0) + ) + return false; + return true; + } + + + case MOM: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.kbyi * m_min.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + + case MOP: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.kbyi * m_min.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_max.x + aRay.c_zx > 0) + ) + return false; + return true; + } + + case POM: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z < m_min.z) + || ( aRay.kbyi * m_max.x - m_max.z + aRay.c_xz > 0) + || ( aRay.ibyk * m_min.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + + case POP: + { + if(( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.kbyi * m_max.x - m_min.z + aRay.c_xz < 0) + || ( aRay.ibyk * m_max.z - m_min.x + aRay.c_zx < 0) + ) + return false; + return true; + } + + case MMO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y < m_min.y) + || ( aRay.jbyi * m_min.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_max.x + aRay.c_yx > 0) + ) + return false; + return true; + } + + case MPO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.jbyi * m_min.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_max.x + aRay.c_yx > 0) + ) + return false; + return true; + } + + + case PMO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y < m_min.y) + || ( aRay.jbyi * m_max.x - m_max.y + aRay.c_xy > 0) + || ( aRay.ibyj * m_min.y - m_min.x + aRay.c_yx < 0) + ) + return false; + return true; + } + + case PPO: + { + if(( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x > m_max.x) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.jbyi * m_max.x - m_min.y + aRay.c_xy < 0) + || ( aRay.ibyj * m_max.y - m_min.x + aRay.c_yx < 0) + ) + return false; + return true; + } + + + case MOO: + { + if(( aRay.m_Origin.x < m_min.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + return true; + } + + case POO: + { + if(( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + return true; + } + + case OMO: + { + if(( aRay.m_Origin.y < m_min.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + return true; + } + + case OPO: + { + if(( aRay.m_Origin.y > m_max.y) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.z < m_min.z) || ( aRay.m_Origin.z > m_max.z) + ) + return false; + return true; + } + + + case OOM: + { + if(( aRay.m_Origin.z < m_min.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + ) + return false; + return true; + } + + case OOP: + { + if(( aRay.m_Origin.z > m_max.z) + || ( aRay.m_Origin.x < m_min.x) || ( aRay.m_Origin.x > m_max.x) + || ( aRay.m_Origin.y < m_min.y) || ( aRay.m_Origin.y > m_max.y) + ) + return false; + return true; + } + } + + return false; +} diff --git a/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h new file mode 100644 index 0000000000..897a914905 --- /dev/null +++ b/3d-viewer/3d_rendering/3d_render_raytracing/shapes3D/cobject.h @@ -0,0 +1,135 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cobject.h + * @brief + */ + +#ifndef _COBJECT_H_ +#define _COBJECT_H_ + +#include "../../../3d_xv3d/xv3d_types.h" +#include "cbbox.h" +#include "../hitinfo.h" +#include "../cmaterial.h" + + +enum OBJECT3D_TYPE +{ + OBJ3D_CYLINDER, + OBJ3D_DUMMYBLOCK, + OBJ3D_LAYERITEM, + OBJ3D_XYPLANE, + OBJ3D_ROUNDSEG, + OBJ3D_TRIANGLE, + OBJ3D_MAX +}; + +class GLM_ALIGN(CLASS_ALIGNMENT) COBJECT +{ +protected: + CBBOX m_bbox; + SFVEC3F m_centroid; + OBJECT3D_TYPE m_obj_type; + const CMATERIAL *m_material; + +public: + + COBJECT( OBJECT3D_TYPE aObjType ); + + void SetMaterial( const CMATERIAL *aMaterial ) { m_material = aMaterial; } + const CMATERIAL *GetMaterial() const { return m_material; } + + virtual SFVEC3F GetDiffuseColor( const HITINFO &aHitInfo ) const = 0; + + virtual ~COBJECT() {} + + /** Function Intersects + * @brief Intersects - a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅) + * It intersects if the result intersection is not null + * @param aBBox + * @return + */ + virtual bool Intersects( const CBBOX &aBBox ) const = 0; + + + /** Functions Intersect + * @brief Intersect + * @param aRay + * @param aHitInfo + * @return TRUE if the aRay intersects the object + */ + virtual bool Intersect( const RAY &aRay, HITINFO &aHitInfo ) const = 0; + + /** Functions Intersect for shadow test + * @brief Intersect + * @param aRay + * @param aDistance - max distance of the test + * @return TRUE if the aRay intersects the object + */ + virtual bool IntersectP( const RAY &aRay, float aMaxDistance ) const = 0; + + const CBBOX &GetBBox() const { return m_bbox; } + + const SFVEC3F &GetCentroid() const { return m_centroid; } +}; + + +/// Implements a class for object statistics +/// using Singleton pattern +class COBJECT3D_STATS +{ +public: + + void ResetStats() { memset( m_counter, 0, sizeof(unsigned int) * OBJ3D_MAX ); } + + unsigned int GetCountOf( OBJECT3D_TYPE aObjType ) const { return m_counter[aObjType]; } + + void AddOne( OBJECT3D_TYPE aObjType ) { m_counter[aObjType]++; } + + void PrintStats(); + + static COBJECT3D_STATS &Instance() + { + if( !s_instance ) + s_instance = new COBJECT3D_STATS; + + return *s_instance; + } + +private: + COBJECT3D_STATS(){ ResetStats(); } + COBJECT3D_STATS( const COBJECT3D_STATS &old ); + const COBJECT3D_STATS &operator=( const COBJECT3D_STATS &old ); + ~COBJECT3D_STATS(){} + +private: + unsigned int m_counter[OBJ3D_MAX]; + + static COBJECT3D_STATS *s_instance; +}; + + +#endif // _COBJECT_H_ diff --git a/3d-viewer/3d_rendering/c3d_render_base.h b/3d-viewer/3d_rendering/c3d_render_base.h new file mode 100644 index 0000000000..7182d0f4f7 --- /dev/null +++ b/3d-viewer/3d_rendering/c3d_render_base.h @@ -0,0 +1,82 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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_base.h + * @brief + */ + +#ifndef C3D_RENDER_BASE_H +#define C3D_RENDER_BASE_H + + +#include +#include "../3d_canvas/cinfo3d_visu.h" +#include "3d_cache/3d_cache.h" + +/** + * This is a base class to hold data and functions for render targets. + */ +class C3D_RENDER_BASE +{ + + + // Operations +public: + + C3D_RENDER_BASE( CINFO3D_VISU &aSettings, + S3D_CACHE *a3DModelManager ); + + virtual ~C3D_RENDER_BASE() = 0; + + virtual void SetCurWindowSize( const wxSize &aSize ) = 0; + + virtual void Redraw( bool aIsMoving ) = 0; + + void ReloadRequest() { m_reloadRequested = true; } + + // Attributes + +protected: + CINFO3D_VISU &m_settings; + S3D_CACHE *m_3d_model_manager; + + bool m_is_opengl_initialized; + bool m_reloadRequested; + + /** + * The window size that this camera is working. + */ + wxSize m_windowSize; + + /** + * 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_3D_RENDER". See the wxWidgets documentation on wxLogTrace for + * more information. + */ + static const wxChar *m_logTrace; +}; + +#endif // C3D_RENDER_BASE_H diff --git a/3d-viewer/3d_rendering/c3dmodel.h b/3d-viewer/3d_rendering/c3dmodel.h new file mode 100644 index 0000000000..e17af15dbf --- /dev/null +++ b/3d-viewer/3d_rendering/c3dmodel.h @@ -0,0 +1,106 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 c3dmodel.h + * @brief define an internal structure to be used by the 3D renders + */ + + +#ifndef C3DMODEL_H +#define C3DMODEL_H + +#include "3d_xv3d/xv3d_types.h" +#include +//#include + +/** + * Scale convertion from 3d model units to pcb units + */ +#define UNITS3D_TO_UNITSPCB (IU_PER_MM) + + +typedef struct +{ + SFVEC3F m_Ambient; // + SFVEC3F m_Diffuse; ///< Default diffuse color if m_Color is NULL + SFVEC3F m_Emissive; // + SFVEC3F m_Specular; // + float m_Shininess; // + float m_Transparency; ///< 1.0 is completely transparent, 0.0 completely opaque + + // !TODO: to be implemented + /*struct textures + { + wxString m_Ambient; // map_Ka + wxString m_Diffuse; // map_Kd + wxString m_Specular; // map_Ks + wxString m_Specular_highlight; // map_Ns + wxString m_Bump; // map_bump, bump + wxString m_Displacement; // disp + wxString m_Alpha; // map_d + };*/ +} SMATERIAL; + + +/// Per-vertex normal/color/texcoors structure. +/// CONDITIONS: +/// m_Positions size == m_Normals size == m_Texcoords size == m_Color size +/// m_Texcoords can be NULL, textures will not be applied in that case +/// m_Color can be NULL, it will use the m_Diffuse color for every triangle +/// any m_FaceIdx must be an index of a the element lists +/// m_MaterialIdx must be an existent material index stored in the parent model +/// SCALES: +/// m_Positions units are in mm, example: +/// 0.1 unit == 0.1 mm +/// 1.0 unit == 1.0 mm +/// 10.0 unit == 10.0 mm +/// +/// To convert this units to pcbunits, use the convertion facto UNITS3D_TO_UNITSPCB +/// +/// m_Normals, m_Color and m_Texcoords are beween 0.0f and 1.0f +typedef struct +{ + unsigned int m_VertexSize; ///< Number of vertex in the arrays + SFVEC3F *m_Positions; ///< Vertex position array + SFVEC3F *m_Normals; ///< Vertex normals array + SFVEC2F *m_Texcoords; ///< Vertex texture coordinates array, can be NULL + SFVEC3F *m_Color; ///< Vertex color array, can be NULL + unsigned int m_FaceIdxSize; ///< Number of elements of the m_FaceIdx array + unsigned int *m_FaceIdx; ///< Triangle Face Indexes + unsigned int m_MaterialIdx; ///< Material Index to be used in this mesh (must be < m_MaterialsSize ) +} SMESH; + + +/// Store the a model based on meshes and materials +typedef struct +{ + unsigned int m_MeshesSize; ///< Number of meshes in the array + SMESH *m_Meshes; ///< The meshes list of this model + + unsigned int m_MaterialsSize; ///< Number of materials in the material array + SMATERIAL *m_Materials; ///< The materials list of this model +} S3DMODEL; + +#endif // C3DMODEL_H diff --git a/3d-viewer/3d_rendering/ccamera.cpp b/3d-viewer/3d_rendering/ccamera.cpp new file mode 100644 index 0000000000..3749ac80ad --- /dev/null +++ b/3d-viewer/3d_rendering/ccamera.cpp @@ -0,0 +1,493 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ccamera.cpp + * @brief + */ + +#include "../common_ogl/openGL_includes.h" +#include "ccamera.h" +#include + + +/** + * 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_CCAMERA". See the wxWidgets documentation on wxLogTrace for + * more information. + */ +const wxChar *CCAMERA::m_logTrace = wxT( "KI_TRACE_CCAMERA" ); + + +CCAMERA::CCAMERA( float aRangeScale ) +{ + wxLogTrace( m_logTrace, wxT( "CCAMERA::CCAMERA" ) ); + + m_parametersChanged = true; + m_projectionType = PROJECTION_PERSPECTIVE; + m_projectionMatrix = glm::mat4( 1.0f ); + m_projectionMatrix_inv = glm::mat4( 1.0f ); + m_rotationMatrix = glm::mat4( 1.0f ); + m_lastPosition = wxPoint( 0, 0 ); + m_windowSize = wxSize( 0, 0 ); + m_zoom = 1.0f; + m_range_scale = aRangeScale; + m_camera_pos_init = SFVEC3F( 0.0f, 0.0f, -aRangeScale ); + m_camera_pos = m_camera_pos_init; + m_boardLookAt_pos = SFVEC3F( 0.0, 0.0, 0.0 ); + updateViewMatrix(); + m_viewMatrix_inverse = glm::inverse( m_viewMatrix ); + m_scr_nX.clear(); + m_scr_nY.clear(); +} + + +void CCAMERA::updateViewMatrix() +{ + m_viewMatrix = glm::translate( glm::mat4( 1.0f ), m_camera_pos ) * + m_rotationMatrix * glm::translate( glm::mat4( 1.0f ), m_boardLookAt_pos ); +} + + +const glm::mat4 &CCAMERA::GetRotationMatrix() const +{ + return m_rotationMatrix; +} + + +void CCAMERA::rebuildProjection() +{ + m_frustum.ratio = (float) m_windowSize.x / m_windowSize.y; + m_frustum.nearD = 0.01f; + m_frustum.farD = glm::length( m_camera_pos_init ) * 2.0f; // Consider that we can render double the lenght, review if that is OK... + + switch( m_projectionType ) + { + case PROJECTION_PERSPECTIVE: + // Ratio width / height of the window display + m_frustum.angle = 45.0f * m_zoom; + + + m_projectionMatrix = glm::perspective( m_frustum.angle * ( glm::pi() / 180.0f ), + m_frustum.ratio, + m_frustum.nearD, + m_frustum.farD ); + + m_projectionMatrix_inv = glm::inverse( m_projectionMatrix ); + + m_frustum.tang = (float)tan( m_frustum.angle * ( glm::pi() / 180.0f ) * 0.5f ) ; + + m_focalLen.x = ( (float)m_windowSize.y / (float)m_windowSize.x ) / m_frustum.tang; + m_focalLen.y = 1.0f / m_frustum.tang; + + m_frustum.nh = m_frustum.nearD * m_frustum.tang; + m_frustum.nw = m_frustum.nh * m_frustum.ratio; + m_frustum.fh = m_frustum.farD * m_frustum.tang; + m_frustum.fw = m_frustum.fh * m_frustum.ratio; + break; + + case PROJECTION_ORTHO: + const float orthoReductionFactor = m_zoom / 400.0f; + + // Initialize Projection Matrix for Ortographic View + m_projectionMatrix = glm::ortho( -m_windowSize.x * orthoReductionFactor, + m_windowSize.x * orthoReductionFactor, + -m_windowSize.y * orthoReductionFactor, + m_windowSize.y * orthoReductionFactor, + m_frustum.nearD, + m_frustum.farD ); + + m_projectionMatrix_inv = glm::inverse( m_projectionMatrix ); + + m_frustum.nw = m_windowSize.x * orthoReductionFactor * 2.0f; + m_frustum.nh = m_windowSize.y * orthoReductionFactor * 2.0f; + m_frustum.fw = m_frustum.nw; + m_frustum.fh = m_frustum.nh; + + break; + } + + m_scr_nX.resize( m_windowSize.x ); + m_scr_nY.resize( m_windowSize.y ); + + // Precalc X values for camera -> ray generation + for( unsigned int x = 0; x < (unsigned int)m_windowSize.x; x++ ) + { + // Converts 0.0 .. 1.0 + float xNormalizedDeviceCoordinates = ( ( (float)x + 0.5f ) / (m_windowSize.x - 0.0f) ); + + // Converts -1.0 .. 1.0 + m_scr_nX[x] = 2.0f * xNormalizedDeviceCoordinates - 1.0f; + } + + // Precalc Y values for camera -> ray generation + for( unsigned int y = 0; y < (unsigned int)m_windowSize.y; y++ ) + { + // Converts 0.0 .. 1.0 + float yNormalizedDeviceCoordinates = ( ( (float)y + 0.5f ) / (m_windowSize.y - 0.0f) ); + + // Converts -1.0 .. 1.0 + m_scr_nY[y] = 2.0f * yNormalizedDeviceCoordinates - 1.0f; + } + + updateFrustum(); +} + + +void CCAMERA::updateFrustum() +{ + // Update matrix and vectors + m_viewMatrix_inverse = glm::inverse( m_viewMatrix ); + + m_right = glm::normalize( SFVEC3F( m_viewMatrix_inverse * glm::vec4( SFVEC3F( 1.0, 0.0, 0.0 ), 0.0 ) ) ); + m_up = glm::normalize( SFVEC3F( m_viewMatrix_inverse * glm::vec4( SFVEC3F( 0.0, 1.0, 0.0 ), 0.0 ) ) ); + m_dir = glm::normalize( SFVEC3F( m_viewMatrix_inverse * glm::vec4( SFVEC3F( 0.0, 0.0, 1.0 ), 0.0 ) ) ); + m_pos = SFVEC3F( m_viewMatrix_inverse * glm::vec4( SFVEC3F( 0.0, 0.0, 0.0 ), 1.0 ) ); + + + /* + * Frustum is a implementation based on a tutorial by + * http://www.lighthouse3d.com/tutorials/view-frustum-culling/ + */ + + // compute the centers of the near and far planes + m_frustum.nc = m_pos - m_dir * m_frustum.nearD; + m_frustum.fc = m_pos - m_dir * m_frustum.farD; + + // compute the 4 corners of the frustum on the near plane + m_frustum.ntl = m_frustum.nc + m_up * m_frustum.nh - m_right * m_frustum.nw; + m_frustum.ntr = m_frustum.nc + m_up * m_frustum.nh + m_right * m_frustum.nw; + m_frustum.nbl = m_frustum.nc - m_up * m_frustum.nh - m_right * m_frustum.nw; + m_frustum.nbr = m_frustum.nc - m_up * m_frustum.nh + m_right * m_frustum.nw; + + // compute the 4 corners of the frustum on the far plane + m_frustum.ftl = m_frustum.fc + m_up * m_frustum.fh - m_right * m_frustum.fw; + m_frustum.ftr = m_frustum.fc + m_up * m_frustum.fh + m_right * m_frustum.fw; + m_frustum.fbl = m_frustum.fc - m_up * m_frustum.fh - m_right * m_frustum.fw; + m_frustum.fbr = m_frustum.fc - m_up * m_frustum.fh + m_right * m_frustum.fw; + + // Reserve size for precalc values + m_right_nX.resize( m_windowSize.x ); + m_up_nY.resize( m_windowSize.y ); + + // Precalc X values for camera -> ray generation + SFVEC3F right_nw = m_right * m_frustum.nw; + + for( unsigned int x = 0; x < (unsigned int)m_windowSize.x; x++ ) + m_right_nX[x] = right_nw * m_scr_nX[x]; + + // Precalc Y values for camera -> ray generation + SFVEC3F up_nh = m_up * m_frustum.nh; + + for( unsigned int y = 0; y < (unsigned int)m_windowSize.y; y++ ) + m_up_nY[y] = m_frustum.nc + (up_nh * m_scr_nY[y]); +} + + +void CCAMERA::MakeRay( const SFVEC2I &aWindowPos, SFVEC3F &aOutOrigin, SFVEC3F &aOutDirection ) const +{ + aOutOrigin = m_up_nY[aWindowPos.y] + + m_right_nX[aWindowPos.x]; + + aOutDirection = glm::normalize( aOutOrigin - m_pos ); +} + + +void CCAMERA::GLdebug_Lines() +{ + SFVEC3F ntl = m_frustum.ntl; + SFVEC3F ntr = m_frustum.ntr; + SFVEC3F nbl = m_frustum.nbl; + SFVEC3F nbr = m_frustum.nbr; + + SFVEC3F ftl = m_frustum.ftl; + SFVEC3F ftr = m_frustum.ftr; + SFVEC3F fbl = m_frustum.fbl; + SFVEC3F fbr = m_frustum.fbr; + + glColor4f( 1.0, 1.0, 1.0, 0.7 ); + + glBegin(GL_LINE_LOOP); + //near plane + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(nbl.x,nbl.y,nbl.z); + glEnd(); + + glBegin(GL_LINE_LOOP); + //far plane + glVertex3f(ftr.x,ftr.y,ftr.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + glEnd(); + + glBegin(GL_LINE_LOOP); + //bottom plane + glVertex3f(nbl.x,nbl.y,nbl.z); + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + glEnd(); + + glBegin(GL_LINE_LOOP); + //top plane + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + glVertex3f(ftr.x,ftr.y,ftr.z); + glEnd(); + + glBegin(GL_LINE_LOOP); + //left plane + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(nbl.x,nbl.y,nbl.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + glEnd(); + + glBegin(GL_LINE_LOOP); + // right plane + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(ftr.x,ftr.y,ftr.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + glEnd(); +} + + +void CCAMERA::GLdebug_Vectors() +{ + SFVEC3F right = m_pos + m_right * m_frustum.nearD; + SFVEC3F up = m_pos + m_up * m_frustum.nearD; + SFVEC3F dir = m_pos - m_dir * m_frustum.nearD; + + glColor4f( 1.0, 0.0, 0.0, 1.0 ); + glBegin( GL_LINES ); + glVertex3fv( &m_pos.x ); + glVertex3fv( &right.x ); + glEnd(); + + glColor4f( 0.0, 1.0, 0.0, 1.0 ); + glBegin( GL_LINES ); + glVertex3fv( &m_pos.x ); + glVertex3fv( &up.x ); + glEnd(); + + glColor4f( 0.0, 0.0, 1.0, 1.0 ); + glBegin( GL_LINES ); + glVertex3fv( &m_pos.x ); + glVertex3fv( &dir.x ); + glEnd(); +} + + +void CCAMERA::GLdebug_Planes() +{ + SFVEC3F ntl = m_frustum.ntl; + SFVEC3F ntr = m_frustum.ntr; + SFVEC3F nbl = m_frustum.nbl; + SFVEC3F nbr = m_frustum.nbr; + + SFVEC3F ftl = m_frustum.ftl; + SFVEC3F ftr = m_frustum.ftr; + SFVEC3F fbl = m_frustum.fbl; + SFVEC3F fbr = m_frustum.fbr; + + // Initialize alpha blending function. + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + glBegin(GL_QUADS); + + //near plane + glColor4f( 0.0, 0.0, 0.5, 0.6 ); + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(nbl.x,nbl.y,nbl.z); + + //far plane + glColor4f( 0.0, 0.0, 0.5, 0.6 ); + glVertex3f(ftr.x,ftr.y,ftr.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + + //bottom plane + glColor4f( 0.0, 0.5, 0.0, 0.6 ); + glVertex3f(nbl.x,nbl.y,nbl.z); + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + + //top plane + glColor4f( 0.0, 0.5, 0.0, 0.6 ); + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + glVertex3f(ftr.x,ftr.y,ftr.z); + + //left plane + glColor4f( 0.5, 0.0, 0.0, 0.6 ); + glVertex3f(ntl.x,ntl.y,ntl.z); + glVertex3f(nbl.x,nbl.y,nbl.z); + glVertex3f(fbl.x,fbl.y,fbl.z); + glVertex3f(ftl.x,ftl.y,ftl.z); + + // right plane + glColor4f( 0.5, 0.0, 0.0, 0.6 ); + glVertex3f(nbr.x,nbr.y,nbr.z); + glVertex3f(ntr.x,ntr.y,ntr.z); + glVertex3f(ftr.x,ftr.y,ftr.z); + glVertex3f(fbr.x,fbr.y,fbr.z); + + glEnd(); + + glDisable( GL_BLEND ); +/* + glColor3f( 0.0, 0.0, 1.0 ); + OGL_draw_arrow( m_pos, + m_frustum.nc, + 0.1);*/ + + +} + + +const glm::mat4 &CCAMERA::GetProjectionMatrix() const +{ + return m_projectionMatrix; +} + + +const glm::mat4 &CCAMERA::GetProjectionMatrixInv() const +{ + return m_projectionMatrix_inv; +} + + +const glm::mat4 &CCAMERA::GetViewMatrix() const +{ + return m_viewMatrix; +} + + +const glm::mat4 &CCAMERA::GetViewMatrix_Inv() const +{ + return m_viewMatrix_inverse; +} + + +void CCAMERA::SetCurMousePosition( const wxPoint &aNewMousePosition ) +{ + m_lastPosition = aNewMousePosition; +} + + +void CCAMERA::SetProjection( PROJECTION_TYPE aProjectionType ) +{ + if( m_projectionType != aProjectionType ) + { + m_projectionType = aProjectionType; + rebuildProjection(); + } +} + + +void CCAMERA::SetCurWindowSize( const wxSize &aSize ) +{ + if( m_windowSize != aSize ) + { + m_windowSize = aSize; + rebuildProjection(); + } +} + + +void CCAMERA::ZoomReset() +{ + m_zoom = 1.0f; + + m_camera_pos.z = m_camera_pos_init.z; + + updateViewMatrix(); + rebuildProjection(); +} + + +void CCAMERA::ZoomIn( float aFactor ) +{ + float old_zoom = m_zoom; + + m_zoom /= aFactor; + + if( m_zoom <= 0.05f ) + m_zoom = 0.05f; + + m_camera_pos.z = m_zoom * m_camera_pos_init.z; + + if( old_zoom != m_zoom ) + { + updateViewMatrix(); + rebuildProjection(); + } +} + + +void CCAMERA::ZoomOut( float aFactor ) +{ + float old_zoom = m_zoom; + + m_zoom *= aFactor; + + if( m_zoom >= 1.5f ) + m_zoom = 1.5f; + + m_camera_pos.z = m_zoom * m_camera_pos_init.z; + + if( old_zoom != m_zoom ) + { + updateViewMatrix(); + rebuildProjection(); + } +} + + +float CCAMERA::ZoomGet() const +{ + return m_zoom; +} + + +bool CCAMERA::ParametersChanged() +{ + bool parametersChanged = m_parametersChanged; + + m_parametersChanged = false; + + return parametersChanged; +} diff --git a/3d-viewer/3d_rendering/ccamera.h b/3d-viewer/3d_rendering/ccamera.h new file mode 100644 index 0000000000..32436a187d --- /dev/null +++ b/3d-viewer/3d_rendering/ccamera.h @@ -0,0 +1,229 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ccamera.h + * @brief Define an abstract camera + */ + +#ifndef CCAMERA_H +#define CCAMERA_H + +#include "../3d_xv3d/xv3d_types.h" +#include "../3d_rendering/3d_render_raytracing/ray.h" +#include // for wxSize +#include + +enum PROJECTION_TYPE +{ + PROJECTION_ORTHO, + PROJECTION_PERSPECTIVE +}; + +/** + * Frustum structure + * Frustum is a implementation based on a tutorial by + * http://www.lighthouse3d.com/tutorials/view-frustum-culling/ + */ +struct FRUSTUM +{ + SFVEC3F nc; + SFVEC3F fc; + SFVEC3F ntl; ///< Near Top Left + SFVEC3F ntr; ///< Near Top Right + SFVEC3F nbl; ///< Near Bottom Left + SFVEC3F nbr; ///< Near Bottom Right + SFVEC3F ftl; ///< Far Top Left + SFVEC3F ftr; ///< Far Top Right + SFVEC3F fbl; ///< Far Bottom Left + SFVEC3F fbr; ///< Far Bottom Right + float nearD, farD, ratio, angle, tang; + float nw, nh, fw, fh; +}; + +/** + * Class CCAMERA + * is a virtual class used to derive CCAMERA objects from. + * + * It must be derived to other classes to implement a real camera object. + */ +class CCAMERA +{ + + public: + + /** + * @brief CCAMERA initialize a camera + * @param aRangeScale: it will be expected that the board will have a -aRangeScale/2 to +aRangeScale/2 + * it will initialize the initial Z position with aRangeScale + */ + CCAMERA( float aRangeScale ); + + + /** + * Function GetRotationMatrix + * Get the rotation matrix to be applied in a transformation camera + * @return the rotation matrix of the camera + */ + const glm::mat4 &GetRotationMatrix() const; + + const glm::mat4 &GetViewMatrix() const; + const glm::mat4 &GetViewMatrix_Inv() const; + + const glm::mat4 &GetProjectionMatrix() const; + const glm::mat4 &GetProjectionMatrixInv() const; + + const SFVEC3F &GetRight() const { return m_right; } + const SFVEC3F &GetUp() const { return m_up; } + const SFVEC3F &GetDir() const { return m_dir; } + const SFVEC3F &GetPos() const { return m_pos; } + const SFVEC2F &GetFocalLen() const { return m_focalLen; } + float GetNear() const { return m_frustum.nearD; } + float GetFar() const { return m_frustum.farD; } + + virtual void SetBoardLookAtPos( const SFVEC3F &aBoardPos ) = 0; + + /** + * Calculate a new mouse drag position + */ + virtual void Drag( const wxPoint &aNewMousePosition ) = 0; + + virtual void Pan( const wxPoint &aNewMousePosition ) = 0; + + virtual void Pan( const SFVEC3F &aDeltaOffsetInc ) = 0; + + + /** + * Reset the camera to initial state + */ + virtual void Reset() = 0; + + + /** + * It updates the current mouse position without make any new recalculations on camera. + */ + void SetCurMousePosition( const wxPoint &aPosition ); + + void SetProjection( PROJECTION_TYPE aProjectionType ); + + void SetCurWindowSize( const wxSize &aSize ); + + void ZoomReset(); + + void ZoomIn( float aFactor ); + + void ZoomOut( float aFactor ); + + float ZoomGet() const ; + + /** + * Function ParametersChanged + * @return true if some of the parameters in camera was changed, it will reset the flag + */ + bool ParametersChanged(); + + void MakeRay( const SFVEC2I &aWindowPos, SFVEC3F &aOutOrigin, SFVEC3F &aOutDirection ) const; + + void GLdebug_Lines(); + + void GLdebug_Planes(); + + void GLdebug_Vectors(); + + protected: + + void rebuildProjection(); + void updateFrustum(); + void updateViewMatrix(); + + /** + * @brief m_range_scale - the nominal range expected to be used in the camera. + * It will be used to initialize the Z position + */ + float m_range_scale; + + /** + * 3D zoom value (Min 0.0 ... Max 1.0) + */ + float m_zoom; + + /** + * The window size that this camera is working. + */ + wxSize m_windowSize; + + /** + * The last mouse position in the screen + */ + wxPoint m_lastPosition; + + glm::mat4 m_rotationMatrix; + glm::mat4 m_viewMatrix; + glm::mat4 m_viewMatrix_inverse; + glm::mat4 m_projectionMatrix; + glm::mat4 m_projectionMatrix_inv; + PROJECTION_TYPE m_projectionType; + + FRUSTUM m_frustum; + + SFVEC3F m_right; + SFVEC3F m_up; + SFVEC3F m_dir; + SFVEC3F m_pos; + + SFVEC2F m_focalLen; + + SFVEC3F m_camera_pos_init; + SFVEC3F m_camera_pos; + + SFVEC3F m_boardLookAt_pos; + + /** + * Precalc values array used to calc ray for each pixel (constant for the same window size) + */ + std::vector< float > m_scr_nX; + std::vector< float > m_scr_nY; + + /** + * Precalc values array used to calc ray for each pixel, for X and Y axis of each new camera position + */ + std::vector< SFVEC3F > m_right_nX; + std::vector< SFVEC3F > m_up_nY; + + + /** + * Set to true if any of the parameters in the camera was changed + */ + bool m_parametersChanged; + + /** + * 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_CCAMERA". See the wxWidgets documentation on wxLogTrace for + * more information. + */ + static const wxChar *m_logTrace; +}; + +#endif // CCAMERA_H diff --git a/3d-viewer/3d_rendering/cimage.cpp b/3d-viewer/3d_rendering/cimage.cpp new file mode 100644 index 0000000000..627706acee --- /dev/null +++ b/3d-viewer/3d_rendering/cimage.cpp @@ -0,0 +1,519 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cimage.cpp + * @brief one 8bit-channel image implementation + */ + +#include "cimage.h" +#include // Used for save an image to disk +#include // For memcpy + +#ifndef CLAMP +#define CLAMP(n, min, max) {if (n < min) n=min; else if (n > max) n = max;} +#endif + + +CIMAGE::CIMAGE( unsigned int aXsize, unsigned int aYsize ) +{ + m_wxh = aXsize * aYsize; + m_pixels = (unsigned char*)malloc( m_wxh ); + memset( m_pixels, 0, m_wxh ); + m_width = aXsize; + m_height = aYsize; + m_wraping = (E_WRAP)WRAP_CLAMP; +} + + +CIMAGE::CIMAGE( const CIMAGE &aSrcImage ) +{ + m_wxh = aSrcImage.GetWidth() * aSrcImage.GetHeight(); + m_pixels = (unsigned char*)malloc( m_wxh ); + memcpy( m_pixels, aSrcImage.GetBuffer(), m_wxh ); + m_width = aSrcImage.GetWidth(); + m_height = aSrcImage.GetHeight(); + m_wraping = (E_WRAP)WRAP_CLAMP; +} + + +CIMAGE::~CIMAGE() +{ + free( m_pixels ); +} + + +unsigned char* CIMAGE::GetBuffer() const +{ + return m_pixels; +} + + +bool CIMAGE::wrapCoords( int *aXo, int *aYo ) const +{ + int x = *aXo; + int y = *aYo; + + switch(m_wraping) + { + case WRAP_CLAMP: + x = (x < 0 )?0:x; + x = (x >= (int)(m_width - 1))?(m_width - 1):x; + y = (y < 0)?0:y; + y = (y >= (int)(m_height - 1))?(m_height - 1):y; + break; + case WRAP_WRAP: + x = (x < 0)?((m_width - 1)+x):x; + x = (x >= (int)(m_width - 1))?(x - m_width):x; + y = (y < 0)?((m_height - 1)+y):y; + y = (y >= (int)(m_height - 1))?(y - m_height):y; + break; + default: + break; + } + + if( (x < 0) || (x >= (int)m_width) || + (y < 0) || (y >= (int)m_height) ) + return false; + + *aXo = x; + *aYo = y; + + return true; +} + +void CIMAGE::plot8CircleLines( int aCx, int aCy, int aX, int aY, unsigned char aValue ) +{ + Hline( aCx - aX, aCx + aX, aCy + aY, aValue ); + Hline( aCx - aX, aCx + aX, aCy - aY, aValue ); + Hline( aCx - aY, aCx + aY, aCy + aX, aValue ); + Hline( aCx - aY, aCx + aY, aCy - aX, aValue ); +} + + +void CIMAGE::Setpixel( int aX, int aY, unsigned char aValue ) +{ + if( wrapCoords( &aX, &aY ) ) + m_pixels[aX + aY * m_width] = aValue; +} + + +unsigned char CIMAGE::Getpixel( int aX, int aY ) const +{ + if( wrapCoords( &aX, &aY ) ) + return m_pixels[aX + aY * m_width]; + else + return 0; +} + + +void CIMAGE::Hline( int aXStart, int aXEnd, int aY, unsigned char aValue ) +{ + if( ( aY < 0 ) || + ( aY >= (int)m_height ) || + ( ( aXStart < 0 ) && ( aXEnd < 0) ) || + ( ( aXStart >= (int)m_width ) && ( aXEnd >= (int)m_width) ) ) + return; + + if( aXStart > aXEnd ) + { + int swap = aXStart; + aXStart = aXEnd; + aXEnd = swap; + } + + // Clamp line + if( aXStart < 0 ) + aXStart = 0; + + if( aXEnd >= (int)m_width ) + aXEnd = m_width - 1; + + unsigned char* pixelPtr = &m_pixels[aXStart + aY * m_width]; + unsigned char* pixelPtrEnd = pixelPtr + (unsigned int)((aXEnd - aXStart) + 1); + + while( pixelPtr < pixelPtrEnd ) + { + *pixelPtr = aValue; + pixelPtr++; + } +} + +// Based on paper +// http://web.engr.oregonstate.edu/~sllu/bcircle.pdf +void CIMAGE::CircleFilled(int aCx, int aCy, int aRadius, unsigned char aValue) +{ + int x = aRadius; + int y = 0; + int xChange = 1 - 2 * aRadius; + int yChange = 0; + int radiusError = 0; + + while( x >= y ) + { + plot8CircleLines( aCx, aCy, x, y, aValue ); + y++; + radiusError += yChange; + yChange += 2; + + if( (2 * radiusError + xChange) > 0 ) + { + x--; + radiusError += xChange; + xChange += 2; + } + } +} + + +void CIMAGE::Invert() +{ + for( unsigned int it = 0; it < m_wxh; it++ ) + m_pixels[it] = 255 - m_pixels[it]; +} + + +void CIMAGE::CopyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ) +{ + int aV, bV; + + if( aOperation == COPY_RAW ) + { + if ( aImgA == NULL ) + return; + } + else + { + if ( (aImgA == NULL) || (aImgB == NULL) ) + return; + } + + switch(aOperation) + { + case COPY_RAW: + memcpy( m_pixels, aImgA->m_pixels, m_wxh ); + break; + + case COPY_ADD: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + aV = (aV + bV); + aV = (aV > 255)?255:aV; + + m_pixels[it] = aV; + } + break; + + case COPY_SUB: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + aV = (aV - bV); + aV = (aV < 0)?0:aV; + + m_pixels[it] = aV; + } + break; + + case COPY_DIF: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = abs(aV - bV); + } + break; + + case COPY_MUL: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (unsigned char)((((float)aV / 255.0f) * ((float)bV / 255.0f)) * 255); + } + break; + + case COPY_AND: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] & aImgB->m_pixels[it]; + } + break; + + case COPY_OR: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] | aImgB->m_pixels[it]; + } + break; + + case COPY_XOR: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + m_pixels[it] = aImgA->m_pixels[it] ^ aImgB->m_pixels[it]; + } + break; + + case COPY_BLEND50: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (aV + bV) / 2; + } + break; + + case COPY_MIN: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (aV < bV)?aV:bV; + } + break; + + case COPY_MAX: + for( unsigned int it = 0;it < m_wxh; it++ ) + { + aV = aImgA->m_pixels[it]; + bV = aImgB->m_pixels[it]; + + m_pixels[it] = (aV > bV)?aV:bV; + } + break; + + default: + break; + } +} + +// TIP: If you want create or test filters you can use GIMP +// with a generic convolution matrix and get the values from there. +// http://docs.gimp.org/nl/plug-in-convmatrix.html +static const S_FILTER FILTERS[] = { + // Hi Pass + { + { { 0, -1, -1, -1, 0}, + {-1, 2, -4, 2, -1}, + {-1, -4, 13, -4, -1}, + {-1, 2, -4, 2, -1}, + { 0, -1, -1, -1, 0} + }, + 7, + 255 + }, + + // Blur + { + { { 3, 5, 7, 5, 3}, + { 5, 9, 12, 9, 5}, + { 7, 12, 20, 12, 7}, + { 5, 9, 12, 9, 5}, + { 3, 5, 7, 5, 3} + }, + 182, + 0 + }, + + // Blur Invert + { + { { 0, 0, 0, 0, 0}, + { 0, 0, -1, 0, 0}, + { 0, -1, 0, -1, 0}, + { 0, 0, -1, 0, 0}, + { 0, 0, 0, 0, 0} + }, + 4, + 255 + }, + + // Blur + { + { { 1, 4, 7, 4, 1}, + { 4, 16, 26, 16, 4}, + { 7, 26, 41, 26, 7}, + { 4, 16, 26, 16, 4}, + { 1, 4, 7, 4, 1} + }, + 273, + 0 + }, + + // Cartoon + { + { {-1, -1, -1, -1, 0}, + {-1, 0, 0, 0, 0}, + {-1, 0, 4, 0, 0}, + { 0, 0, 0, 1, 0}, + { 0, 0, 0, 0, 4} + }, + 3, + 0 + }, + + // Emboss + { + { {-1, -1, -1, -1, 0}, + {-1, -1, -1, 0, 1}, + {-1, -1, 0, 1, 1}, + {-1, 0, 1, 1, 1}, + { 0, 1, 1, 1, 1} + }, + 1, + 128 + }, + + // Sharpen + { + { {-1, -1, -1, -1, -1}, + {-1, 2, 2, 2, -1}, + {-1, 2, 8, 2, -1}, + {-1, 2, 2, 2, -1}, + {-1, -1, -1, -1, -1} + }, + 8, + 0 + }, + + // Melt + { + { { 4, 2, 6, 8, 1}, + { 1, 2, 5, 4, 2}, + { 0, -1, 1, -1, 0}, + { 0, 0, -2, 0, 0}, + { 0, 0, 0, 0, 0} + }, + 32, + 0 + }, + + // Sobel Gx + { + { { 0, 0, 0, 0, 0}, + { 0, -1, 0, 1, 0}, + { 0, -2, 0, 2, 0}, + { 0, -1, 0, 1, 0}, + { 0, 0, 0, 0, 0} + }, + 1, + 0 + }, + + // Sobel Gy + { + { { 1, 2, 4, 2, 1}, + {-1, -1, 0, 1, 1}, + {-2, -2, 0, 2, 2}, + {-1, -1, 0, 1, 1}, + {-1, -2, -4, -2, -1}, + }, + 1, + 0 + } +};// Filters + + +//!TODO: This functions can be optimized slipting it between the edges and +// do it without use the getpixel function. +// Optimization can be done to m_pixels[ix + iy * m_width] +// but keep in mind the parallel process of the algorithm +void CIMAGE::EfxFilter( CIMAGE *aInImg, E_FILTER aFilterType ) +{ + S_FILTER filter = FILTERS[aFilterType]; + + aInImg->m_wraping = WRAP_CLAMP; + m_wraping = WRAP_CLAMP; + + #ifdef USE_OPENMP + #pragma omp parallel for + #endif /* USE_OPENMP */ + + for( int iy = 0; iy < (int)m_height; iy++) + { + for( int ix = 0; ix < (int)m_width; ix++ ) + { + int v = 0; + + for( int sy = 0; sy < 5; sy++ ) + { + for( int sx = 0; sx < 5; sx++ ) + { + int factor = filter.kernel[sx][sy]; + unsigned char pixelv = aInImg->Getpixel( ix + sx - 2, iy + sy - 2 ); + v += pixelv * factor; + } + } + + v /= filter.div; + + v += filter.offset; + + CLAMP(v, 0, 255); + + m_pixels[ix + iy * m_width] = v; + } + } +} + + +void CIMAGE::SetPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ) +{ + for( unsigned int i = 0; i < m_wxh; i++ ) + { + int v = aNormalizedFloatArray[i] * 255; + CLAMP(v, 0, 255); + m_pixels[i] = v; + } +} + + +void CIMAGE::SaveAsPNG( wxString aFileName ) const +{ + unsigned char* pixelbuffer = (unsigned char*) malloc( m_wxh * 3 ); + + wxImage image( m_width, m_height ); + + for( unsigned int i = 0; i < m_wxh; i++) + { + unsigned char v = m_pixels[i]; + // Set RGB value with all same values intensities + pixelbuffer[i * 3 + 0] = v; + pixelbuffer[i * 3 + 1] = v; + pixelbuffer[i * 3 + 2] = v; + } + + image.SetData( pixelbuffer ); + image = image.Mirror( false ); + image.SaveFile( aFileName + ".png", wxBITMAP_TYPE_PNG ); + image.Destroy(); +} diff --git a/3d-viewer/3d_rendering/cimage.h b/3d-viewer/3d_rendering/cimage.h new file mode 100644 index 0000000000..88e6f8de3e --- /dev/null +++ b/3d-viewer/3d_rendering/cimage.h @@ -0,0 +1,221 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cimage.h + * @brief one 8bit-channel image definition + */ + +#ifndef CIMAGE_H +#define CIMAGE_H + +#include + +/// Image operation type +enum E_IMAGE_OP { + COPY_RAW, + COPY_ADD, + COPY_SUB, + COPY_DIF, + COPY_MUL, + COPY_AND, + COPY_OR, + COPY_XOR, + COPY_BLEND50, + COPY_MIN, + COPY_MAX +}; + + +/// Image wrap type enumeration +enum E_WRAP { + WRAP_ZERO, ///< Coords that wraps are not evaluated + WRAP_CLAMP, ///< Coords are clamped to image size + WRAP_WRAP ///< Coords are wrapped arround +}; + + +/// Filter type enumeration +enum E_FILTER { + FILTER_HIPASS, + FILTER_GAUSSIAN_BLUR, + FILTER_INVERT_BLUR, + FILTER_GAUSSIAN_BLUR2, +}; + +/// 5x5 Filter struct parameters +typedef struct { + signed char kernel[5][5]; + unsigned char div; + unsigned char offset; +}S_FILTER; + + +/** + * Class CIMAGE + * manages a 8-bit channel image + */ +class CIMAGE +{ + +public: + + /** + * Constructor CIMAGE + * constructs a CIMAGE based on image size + * @param aXsize x size + * @param aYsize y size + */ + CIMAGE( unsigned int aXsize, unsigned int aYsize ); + + /** + * @brief CIMAGE + * constructs a CIMAGE based on an existent image. It will copy the image to + * the new + * @param aSrcImage + */ + CIMAGE( const CIMAGE &aSrcImage ); + + ~CIMAGE(); + + /** + * Function Setpixel + * set a value in a pixel position, position is clamped in accord with the + * current clamp settings + * @param aX x position + * @param aY y position + * @param aValue value to set the pixel + */ + void Setpixel( int aX, int aY, unsigned char aValue ); + + /** + * Function Getpixel + * get the pixel value from pixel position, position is clamped in accord with the + * current clamp settings + * @param aX x position + * @param aY y position + * @return unsigned char - pixel value + */ + unsigned char Getpixel( int aX, int aY ) const; + + /** + * @brief hline - Draws an horizontal line + * @param aXStart - x start position + * @param aXEnd - x end position + * @param aY - y positoin + * @param aValue - value to add + */ + void Hline( int aXStart, int aXEnd, int aY, unsigned char aValue ); + + /** + * @brief CircleFilled + * @param aCx + * @param aCy + * @param aRadius + * @param aValue + */ + void CircleFilled( int aCx, int aCy, int aRadius, unsigned char aValue ); + + /** + * Function CopyFull + * perform a copy operation, based on operation type. The result destination is the self image class + * @param aImgA an image input + * @param aImgB an image input + * @param aOperation operation to perform + * COPY_RAW this <- aImgA + * COPY_ADD this <- CLAMP(aImgA + aImgB) + * COPY_SUB this <- CLAMP(aImgA - aImgB) + * COPY_DIF this <- abs(aImgA - aImgB) + * COPY_MUL this <- aImgA * aImgB + * COPY_AND this <- aImgA & aImgB + * COPY_OR this <- aImgA | aImgB + * COPY_XOR this <- aImgA ^ aImgB + * COPY_BLEND50 this <- (aImgA + aImgB) / 2 + * COPY_MIN this <- (aImgA < aImgB)?aImgA:aImgB + * COPY_MAX this <- (aImgA > aImgB)?aImgA:aImgB + */ + void CopyFull( const CIMAGE *aImgA, const CIMAGE *aImgB, E_IMAGE_OP aOperation ); + + /** + * Function Invert + * invert the values of image this <- (255 - this) + */ + void Invert(); + + /** + * Function EfxFilter + * apply a filter to the input image and stores it in the image class + * this <- FilterType(aInImg) + * @param aInImg input image + * @param aFilterType filter type to apply + */ + void EfxFilter( CIMAGE *aInImg, E_FILTER aFilterType ); + + /** + * Function SaveAsPNG + * save image buffer to a PNG file into the working folder. + * each of RGB channel will have the 8bit-channel from the image. + * @param aFileName fime name (without extension) + */ + void SaveAsPNG( wxString aFileName ) const; + + /** + * Function SetPixelsFromNormalizedFloat + * set the current channel from a float normalized (0.0 - 1.0) buffer + * this <- CLAMP(NormalizedFloat * 255) + * @param aNormalizedFloatArray a float array with the same size of the image + */ + void SetPixelsFromNormalizedFloat( const float * aNormalizedFloatArray ); + + /** + * Function GetBuffer + * get the image buffer pointer + * @return unsigned char * - the pointer of the buffer 8bit channel + */ + unsigned char* GetBuffer() const; + + unsigned int GetWidth() const { return m_width; } + unsigned int GetHeight() const { return m_height; } +private: + + /** + * Function wrapCoords + * calculate the coordinates points in accord with the current clamping settings + * @param aXo X coordinate to be converted (output) + * @param aXo Y coordinate to be converted (output) + * @return bool - true if the coordinates are inside the image, false otherwise + */ + bool wrapCoords( int *aXo, int *aYo ) const; + + void plot8CircleLines( int aCx, int aCy, int aX, int aY, unsigned char aValue ); + +private: + unsigned char* m_pixels; ///< buffer to store the image 8bit-channel + unsigned int m_width; ///< width of the image + unsigned int m_height; ///< height of the image + unsigned int m_wxh; ///< width * height precalc value + E_WRAP m_wraping; ///< current wrapping type +}; + +#endif // CIMAGE_H diff --git a/3d-viewer/3d_rendering/ctrack_ball.cpp b/3d-viewer/3d_rendering/ctrack_ball.cpp new file mode 100644 index 0000000000..517116bab3 --- /dev/null +++ b/3d-viewer/3d_rendering/ctrack_ball.cpp @@ -0,0 +1,117 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ctrack_ball.cpp + * @brief + */ + +#include "common_ogl/openGL_includes.h" +#include "ctrack_ball.h" +#include "trackball.h" +#include + + +CTRACK_BALL::CTRACK_BALL( float aRangeScale ) : CCAMERA( aRangeScale ) +{ + wxLogTrace( m_logTrace, wxT( "CTRACK_BALL::CTRACK_BALL" ) ); + + memset( m_quat, 0, sizeof( m_quat ) ); + trackball( m_quat, 0.0, 0.0, 0.0, 0.0 ); +} + + +void CTRACK_BALL::Drag( const wxPoint &aNewMousePosition ) +{ + m_parametersChanged = true; + + double spin_quat[4]; + + // "Pass the x and y coordinates of the last and current positions of + // the mouse, scaled so they are from (-1.0 ... 1.0)." + float zoom = std::min( m_zoom, 1.0f ); + trackball( spin_quat, + zoom * (2.0 * m_lastPosition.x - m_windowSize.x) / m_windowSize.x, + zoom * (m_windowSize.y - 2.0 * m_lastPosition.y) / m_windowSize.y, + zoom * (2.0 * aNewMousePosition.x - m_windowSize.x) / m_windowSize.x, + zoom * ( m_windowSize.y - 2.0 * aNewMousePosition.y ) / m_windowSize.y); + + add_quats( spin_quat, m_quat, m_quat ); + + GLfloat rotationMatrix[4][4]; + + build_rotmatrix( rotationMatrix, m_quat ); + + m_rotationMatrix = glm::make_mat4( &rotationMatrix[0][0] ); + + updateViewMatrix(); + + updateFrustum(); +} + +void CTRACK_BALL::SetBoardLookAtPos( const SFVEC3F &aBoardPos ) +{ + if( m_boardLookAt_pos != aBoardPos ) + { + m_boardLookAt_pos = -aBoardPos; + + updateViewMatrix(); + updateFrustum(); + m_parametersChanged = true; + } +} + +void CTRACK_BALL::Pan( const wxPoint &aNewMousePosition ) +{ + m_parametersChanged = true; + + // Current zoom and an additional factor are taken into account + // for the amount of panning. + + float zoom = std::min( m_zoom, 1.0f ); + float panFactor = m_range_scale * zoom * (zoom * 4.0f); + m_camera_pos.x -= panFactor * ( m_lastPosition.x - aNewMousePosition.x ) / m_windowSize.x; + m_camera_pos.y -= panFactor * (aNewMousePosition.y - m_lastPosition.y ) / m_windowSize.y; + + updateViewMatrix(); + updateFrustum(); +} + + +void CTRACK_BALL::Pan( const SFVEC3F &aDeltaOffsetInc ) +{ + m_parametersChanged = true; + + m_camera_pos += aDeltaOffsetInc; + + updateViewMatrix(); + updateFrustum(); +} + + +void CTRACK_BALL::Reset() +{ + m_parametersChanged = true; +} + diff --git a/3d-viewer/3d_rendering/ctrack_ball.h b/3d-viewer/3d_rendering/ctrack_ball.h new file mode 100644 index 0000000000..435af66a3d --- /dev/null +++ b/3d-viewer/3d_rendering/ctrack_ball.h @@ -0,0 +1,63 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ctrack_ball.h + * @brief + */ + +#ifndef CTRACK_BALL_H +#define CTRACK_BALL_H + +#include "ccamera.h" + + +class CTRACK_BALL : public CCAMERA +{ + + public: + + CTRACK_BALL( float aRangeScale ); + + void Drag( const wxPoint &aNewMousePosition ); + + void Pan( const wxPoint &aNewMousePosition ); + + void Pan( const SFVEC3F &aDeltaOffsetInc ); + + void SetBoardLookAtPos( const SFVEC3F &aBoardPos ); + + void Reset(); + + + private: + + /** + * quarternion of the trackball + */ + double m_quat[4]; + +}; + +#endif // CTRACK_BALL_H diff --git a/3d-viewer/3d_rendering/trackball.cpp b/3d-viewer/3d_rendering/trackball.cpp new file mode 100644 index 0000000000..b70ef438fe --- /dev/null +++ b/3d-viewer/3d_rendering/trackball.cpp @@ -0,0 +1,323 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * Trackball code: + * + * Implementation of a virtual trackball. + * Implemented by Gavin Bell, lots of ideas from Thant Tessman and + * the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129. + * + * Vector manip code: + * + * Original code from: + * David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli + * + * Much mucking with by: + * Gavin Bell + */ +#include +#include // used only to define GLfloat +#include + +/* + * This size should really be based on the distance from the center of + * rotation to the point on the object underneath the mouse. That + * point would then track the mouse as closely as possible. This is a + * simple example, though, so that is left as an Exercise for the + * Programmer. + */ +#define TRACKBALLSIZE (0.8f) + +/* + * Local function prototypes (not defined in trackball.h) + */ +static double tb_project_to_sphere(double, double, double); +static void normalize_quat(double [4]); + +void +vzero(double *v) +{ + v[0] = 0.0; + v[1] = 0.0; + v[2] = 0.0; +} + +void +vset(double *v, double x, double y, double z) +{ + v[0] = x; + v[1] = y; + v[2] = z; +} + +void +vsub(const double *src1, const double *src2, double *dst) +{ + dst[0] = src1[0] - src2[0]; + dst[1] = src1[1] - src2[1]; + dst[2] = src1[2] - src2[2]; +} + +void +vcopy(const double *v1, double *v2) +{ + register int i; + for (i = 0 ; i < 3 ; i++) + v2[i] = v1[i]; +} + +void +vcross(const double *v1, const double *v2, double *cross) +{ + double temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + vcopy(temp, cross); +} + +double +vlength(const double *v) +{ + return (double) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); +} + +void +vscale(double *v, double div) +{ + v[0] *= div; + v[1] *= div; + v[2] *= div; +} + +void +vnormal(double *v) +{ + vscale(v, 1.0f/vlength(v)); +} + +double +vdot(const double *v1, const double *v2) +{ + return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void +vadd(const double *src1, const double *src2, double *dst) +{ + dst[0] = src1[0] + src2[0]; + dst[1] = src1[1] + src2[1]; + dst[2] = src1[2] + src2[2]; +} + +/* + * Ok, simulate a track-ball. Project the points onto the virtual + * trackball, then figure out the axis of rotation, which is the cross + * product of P1 P2 and O P1 (O is the center of the ball, 0,0,0) + * Note: This is a deformed trackball-- is a trackball in the center, + * but is deformed into a hyperbolic sheet of rotation away from the + * center. This particular function was chosen after trying out + * several variations. + * + * It is assumed that the arguments to this routine are in the range + * (-1.0 ... 1.0) + */ +void +trackball(double q[4], double p1x, double p1y, double p2x, double p2y) +{ + double a[3]; /* Axis of rotation */ + double phi; /* how much to rotate about axis */ + double p1[3], p2[3], d[3]; + double t; + + if (p1x == p2x && p1y == p2y) { + /* Zero rotation */ + vzero(q); + q[3] = 1.0; + return; + } + + /* + * First, figure out z-coordinates for projection of P1 and P2 to + * deformed sphere + */ + vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y)); + vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y)); + + /* + * Now, we want the cross product of P1 and P2 + */ + vcross(p2,p1,a); + + /* + * Figure out how much to rotate around that axis. + */ + vsub(p1, p2, d); + t = vlength(d) / (2.0f*TRACKBALLSIZE); + + /* + * Avoid problems with out-of-control values... + */ + if (t > 1.0) t = 1.0; + if (t < -1.0) t = -1.0; + phi = 2.0f * (double) asin(t); + + axis_to_quat(a,phi,q); +} + +/* + * Given an axis and angle, compute quaternion. + */ +void +axis_to_quat(double a[3], double phi, double q[4]) +{ + vnormal(a); + vcopy(a, q); + vscale(q, (double) sin(phi/2.0)); + q[3] = (double) cos(phi/2.0); +} + +/* + * Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet + * if we are away from the center of the sphere. + */ +static double +tb_project_to_sphere(double r, double x, double y) +{ + double d, t, z; + + d = (double) sqrt(x*x + y*y); + if (d < r * 0.70710678118654752440) { /* Inside sphere */ + z = (double) sqrt(r*r - d*d); + } else { /* On hyperbola */ + t = r / 1.41421356237309504880f; + z = t*t / d; + } + return z; +} + +/* + * Given two rotations, e1 and e2, expressed as quaternion rotations, + * figure out the equivalent single rotation and stuff it into dest. + * + * This routine also normalizes the result every RENORMCOUNT times it is + * called, to keep error from creeping in. + * + * NOTE: This routine is written so that q1 or q2 may be the same + * as dest (or each other). + */ + +#define RENORMCOUNT 97 + +void +add_quats(double q1[4], double q2[4], double dest[4]) +{ + static int count=0; + double t1[4], t2[4], t3[4]; + double tf[4]; + + vcopy(q1,t1); + vscale(t1,q2[3]); + + vcopy(q2,t2); + vscale(t2,q1[3]); + + vcross(q2,q1,t3); + vadd(t1,t2,tf); + vadd(t3,tf,tf); + tf[3] = q1[3] * q2[3] - vdot(q1,q2); + + dest[0] = tf[0]; + dest[1] = tf[1]; + dest[2] = tf[2]; + dest[3] = tf[3]; + + if (++count > RENORMCOUNT) { + count = 0; + normalize_quat(dest); + } +} + +/* + * Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0 + * If they don't add up to 1.0, dividing by their magnitued will + * renormalize them. + * + * Note: See the following for more information on quaternions: + * + * - Shoemake, K., Animating rotation with quaternion curves, Computer + * Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985. + * - Pletinckx, D., Quaternion calculus as a basic tool in computer + * graphics, The Visual Computer 5, 2-13, 1989. + */ +static void normalize_quat(double q[4]) +{ + int i; + double mag; + + mag = (q[0]*q[0] + q[1]*q[1] + q[2]*q[2] + q[3]*q[3]); + for (i = 0; i < 4; i++) q[i] /= mag; +} + +/* + * Build a rotation matrix, given a quaternion rotation. + * + */ +void build_rotmatrix(GLfloat m[4][4], double q[4]) +{ + m[0][0] = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]); + m[0][1] = 2.0f * (q[0] * q[1] - q[2] * q[3]); + m[0][2] = 2.0f * (q[2] * q[0] + q[1] * q[3]); + m[0][3] = 0.0f; + + m[1][0] = 2.0f * (q[0] * q[1] + q[2] * q[3]); + m[1][1]= 1.0f - 2.0f * (q[2] * q[2] + q[0] * q[0]); + m[1][2] = 2.0f * (q[1] * q[2] - q[0] * q[3]); + m[1][3] = 0.0f; + + m[2][0] = 2.0f * (q[2] * q[0] - q[1] * q[3]); + m[2][1] = 2.0f * (q[1] * q[2] + q[0] * q[3]); + m[2][2] = 1.0f - 2.0f * (q[1] * q[1] + q[0] * q[0]); + m[2][3] = 0.0f; + + m[3][0] = 0.0f; + m[3][1] = 0.0f; + m[3][2] = 0.0f; + m[3][3] = 1.0f; +} + diff --git a/3d-viewer/3d_rendering/trackball.h b/3d-viewer/3d_rendering/trackball.h new file mode 100644 index 0000000000..a860dff673 --- /dev/null +++ b/3d-viewer/3d_rendering/trackball.h @@ -0,0 +1,74 @@ +/* + * (c) Copyright 1993, 1994, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + */ +/* + * trackball.h + * A virtual trackball implementation + * Written by Gavin Bell for Silicon Graphics, November 1988. + */ + +/* + * Pass the x and y coordinates of the last and current positions of + * the mouse, scaled so they are from (-1.0 ... 1.0). + * + * The resulting rotation is returned as a quaternion rotation in the + * first paramater. + */ +void trackball(double q[4], double p1x, double p1y, double p2x, double p2y); + +/* + * Given two quaternions, add them together to get a third quaternion. + * Adding quaternions to get a compound rotation is analagous to adding + * translations to get a compound translation. When incrementally + * adding rotations, the first argument here should be the new + * rotation, the second and third the total rotation (which will be + * over-written with the resulting new total rotation). + */ +void add_quats(double *q1, double *q2, double *dest); + +/* + * A useful function, builds a rotation matrix in Matrix based on + * given quaternion. + */ +void build_rotmatrix(GLfloat m[4][4], double q[4]); + +/* + * This function computes a quaternion based on an axis (defined by + * the given vector) and an angle about which to rotate. The angle is + * expressed in radians. The result is put into the third argument. + */ +void axis_to_quat(double a[3], double phi, double q[4]); + diff --git a/3d-viewer/3d_struct.h b/3d-viewer/3d_struct.h index bd8a9345be..fc855672dc 100644 --- a/3d-viewer/3d_struct.h +++ b/3d-viewer/3d_struct.h @@ -35,7 +35,7 @@ #include #include <3d_material.h> #include <3d_types.h> -#include +#include "3d_rendering/3d_render_raytracing/shapes3D/cbbox.h" class S3D_MASTER; diff --git a/3d-viewer/3d_types.h b/3d-viewer/3d_types.h index 9301cb69d2..d49ab66334 100644 --- a/3d-viewer/3d_types.h +++ b/3d-viewer/3d_types.h @@ -30,7 +30,7 @@ #define _3D_TYPES_H_ #define GLM_FORCE_RADIANS -#include +#include #include // for IU_PER_MILS diff --git a/3d-viewer/3d_xv3d/xv3d_types.h b/3d-viewer/3d_xv3d/xv3d_types.h new file mode 100644 index 0000000000..24325ed7fc --- /dev/null +++ b/3d-viewer/3d_xv3d/xv3d_types.h @@ -0,0 +1,56 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 xv3d_types.h + * @brief + */ + +#ifndef XV3D_TYPES_H +#define XV3D_TYPES_H + +#define GLM_FORCE_RADIANS +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +typedef glm::uvec2 SFVEC2UI; +typedef glm::ivec2 SFVEC2I; +typedef glm::vec2 SFVEC2F; +typedef glm::dvec2 SFVEC2D; +typedef glm::vec3 SFVEC3F; +typedef glm::dvec3 SFVEC3D; +typedef glm::vec4 SFVEC4F; +typedef glm::uvec3 SFVEC3UI; +typedef glm::dvec3 SFVEC3D; + +#define CLASS_ALIGNMENT 16 + +#endif // XV3D_TYPES_H diff --git a/3d-viewer/CBBox.cpp b/3d-viewer/CBBox.cpp deleted file mode 100644 index 23c1856a99..0000000000 --- a/3d-viewer/CBBox.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2015 Mario Luzeiro - * 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 CBBox.cpp - * @brief Bounding Box class implementation - */ - -#include "CBBox.h" - - -// openGL includes used for debug the bounding box -#ifdef __WXMAC__ -# ifdef __DARWIN__ -# include -# else -# include -# endif -#else -# include -#endif - -CBBOX::CBBOX() -{ - Reset(); -} - -CBBOX::CBBOX( const S3D_VERTEX &aPbInit ) -{ - m_min = aPbInit; - m_max = aPbInit; - - m_initialized = true; -} - -CBBOX::CBBOX( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ) -{ - Set( aPbMin, aPbMax ); -} - -CBBOX::~CBBOX() -{ -} - -void CBBOX::Set( const S3D_VERTEX &aPbMin, const S3D_VERTEX &aPbMax ) -{ - m_min.x = glm::min( aPbMin.x, aPbMax.x ); - m_min.y = glm::min( aPbMin.y, aPbMax.y ); - m_min.z = glm::min( aPbMin.z, aPbMax.z ); - - m_max.x = glm::max( aPbMin.x, aPbMax.x ); - m_max.y = glm::max( aPbMin.y, aPbMax.y ); - m_max.z = glm::max( aPbMin.z, aPbMax.z ); - - m_initialized = true; -} - -bool CBBOX::IsInitialized() const -{ - return m_initialized; -} - -void CBBOX::Reset() -{ - m_min = S3D_VERTEX( 0.0f, 0.0f, 0.0f ); - m_max = S3D_VERTEX( 0.0f, 0.0f, 0.0f ); - - m_initialized = false; -} - -void CBBOX::Union( const S3D_VERTEX &aPoint ) -{ - if( !m_initialized ) - { - m_initialized = true; - // Initialize the bounding box with the given point - m_min = aPoint; - m_max = aPoint; - } - else - { - // get the minimun value between the added point and the existent bounding box - m_min.x = glm::min( m_min.x, aPoint.x ); - m_min.y = glm::min( m_min.y, aPoint.y ); - m_min.z = glm::min( m_min.z, aPoint.z ); - - // get the maximun value between the added point and the existent bounding box - m_max.x = glm::max( m_max.x, aPoint.x ); - m_max.y = glm::max( m_max.y, aPoint.y ); - m_max.z = glm::max( m_max.z, aPoint.z ); - } -} - - -void CBBOX::Union( const CBBOX &aBBox ) -{ - if( aBBox.m_initialized == false ) - return; - - if( !m_initialized ) - { - // Initialize the bounding box with the given bounding box - m_initialized = true; - m_min = aBBox.m_min; - m_max = aBBox.m_max; - } - else - { - // get the minimun value between the added bounding box and the existent bounding box - m_min.x = glm::min( m_min.x, aBBox.m_min.x ); - m_min.y = glm::min( m_min.y, aBBox.m_min.y ); - m_min.z = glm::min( m_min.z, aBBox.m_min.z ); - - // get the maximun value between the added bounding box and the existent bounding box - m_max.x = glm::max( m_max.x, aBBox.m_max.x ); - m_max.y = glm::max( m_max.y, aBBox.m_max.y ); - m_max.z = glm::max( m_max.z, aBBox.m_max.z ); - } -} - - -S3D_VERTEX CBBOX::GetCenter() const -{ - return (m_max + m_min) * 0.5f; -} - -S3D_VERTEX CBBOX::Min() const -{ - return m_min; -} - -S3D_VERTEX CBBOX::Max() const -{ - return m_max; -} - -void CBBOX::Scale( float aScale ) -{ - if( m_initialized == false ) - return; - - S3D_VERTEX scaleV = S3D_VERTEX( aScale, aScale, aScale ); - S3D_VERTEX centerV = GetCenter(); - - m_min = (m_min - centerV) * scaleV + centerV; - m_max = (m_max - centerV) * scaleV + centerV; -} - - -bool CBBOX::OverlapsBox( const CBBOX &aBBox ) const -{ - if( aBBox.m_initialized == false ) - return false; - - bool x = ( m_max.x >= aBBox.m_min.x ) && ( m_min.x <= aBBox.m_max.x ); - bool y = ( m_max.y >= aBBox.m_min.y ) && ( m_min.y <= aBBox.m_max.y ); - bool z = ( m_max.z >= aBBox.m_min.z ) && ( m_min.z <= aBBox.m_max.z ); - - return ( x && y && z ); -} - - -bool CBBOX::Inside( const S3D_VERTEX &aPoint ) const -{ - if( m_initialized == false ) - return false; - - return (( aPoint.x >= m_min.x ) && ( aPoint.x <= m_max.x ) && - ( aPoint.y >= m_min.y ) && ( aPoint.y <= m_max.y ) && - ( aPoint.z >= m_min.z ) && ( aPoint.z <= m_max.z )); -} - - -float CBBOX::Volume() const -{ - if( m_initialized == false ) - return 0.0f; - - S3D_VERTEX d = m_max - m_min; - return d.x * d.y * d.z; -} - - -void CBBOX::ApplyTransformation( glm::mat4 aTransformMatrix ) -{ - if( m_initialized == false ) - return; - - S3D_VERTEX v1 = S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ); - S3D_VERTEX v2 = S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ); - - Reset(); - Union( v1 ); - Union( v2 ); -} - - -void CBBOX::ApplyTransformationAA( glm::mat4 aTransformMatrix ) -{ - if( m_initialized == false ) - return; - - // apply the transformation matrix for each of vertices of the bounding box - // and make a union with all vertices - CBBOX tmpBBox = CBBOX( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_min.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_min.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_min.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_min.y, m_max.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_min.x, m_max.y, m_max.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_min.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_min.y, m_max.z, 1.0f ) ) ); - tmpBBox.Union( S3D_VERTEX( aTransformMatrix * glm::vec4( m_max.x, m_max.y, m_max.z, 1.0f ) ) ); - - m_min = tmpBBox.m_min; - m_max = tmpBBox.m_max; -} - - -void CBBOX::GLdebug() const -{ - if( m_initialized == false ) - return; - - glBegin( GL_LINE_LOOP ); - glVertex3f( m_min.x, m_min.y, m_min.z ); - glVertex3f( m_max.x, m_min.y, m_min.z ); - glVertex3f( m_max.x, m_max.y, m_min.z ); - glVertex3f( m_min.x, m_max.y, m_min.z ); - glEnd(); - - glBegin( GL_LINE_LOOP ); - glVertex3f( m_min.x, m_min.y, m_max.z ); - glVertex3f( m_max.x, m_min.y, m_max.z ); - glVertex3f( m_max.x, m_max.y, m_max.z ); - glVertex3f( m_min.x, m_max.y, m_max.z ); - glEnd(); - - glBegin( GL_LINE_STRIP ); - glVertex3f( m_min.x, m_min.y, m_min.z ); - glVertex3f( m_min.x, m_min.y, m_max.z ); - glEnd(); - - glBegin( GL_LINE_STRIP ); - glVertex3f( m_max.x, m_min.y, m_min.z ); - glVertex3f( m_max.x, m_min.y, m_max.z ); - glEnd(); - - glBegin( GL_LINE_STRIP ); - glVertex3f( m_max.x, m_max.y, m_min.z ); - glVertex3f( m_max.x, m_max.y, m_max.z ); - glEnd(); - - glBegin( GL_LINE_STRIP ); - glVertex3f( m_min.x, m_max.y, m_min.z ); - glVertex3f( m_min.x, m_max.y, m_max.z ); - glEnd(); -} diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt index b48e505d67..435995c58c 100644 --- a/3d-viewer/CMakeLists.txt +++ b/3d-viewer/CMakeLists.txt @@ -5,10 +5,23 @@ include_directories( textures ../pcbnew ../polygon + 3d_canvas + 3d_cache + 3d_rendering + 3d_viewer + ${CMAKE_SOURCE_DIR}/include/gal/opengl ${GLEW_INCLUDE_DIR} + ${GLM_INCLUDE_DIR} ${INC_AFTER} ) +# directories +set( DIR_DLG 3d_cache/dialogs ) +set( DIR_RAY 3d_rendering/3d_render_raytracing ) +set( DIR_RAY_ACC ${DIR_RAY}/accelerators ) +set( DIR_RAY_2D ${DIR_RAY}/shapes2D ) +set( DIR_RAY_3D ${DIR_RAY}/shapes3D ) + set(3D-VIEWER_SRCS dialogs/dialog_3D_view_option_base.cpp dialogs/dialog_3D_view_option.cpp @@ -32,8 +45,107 @@ set(3D-VIEWER_SRCS vrml_v2_modelparser.cpp x3dmodelparser.cpp CImage.cpp - CBBox.cpp + 3d_cache/3d_cache_wrapper.cpp + 3d_cache/3d_cache.cpp + 3d_cache/3d_plugin_manager.cpp + 3d_cache/3d_filename_resolver.cpp + 3d_cache/md5.cpp + ${DIR_DLG}/3d_cache_dialogs.cpp + ${DIR_DLG}/dialog_config_3dpath.cpp + ${DIR_DLG}/dialog_select_3dmodel.cpp + ${DIR_DLG}/panel_prev_model.cpp + 3d_model_viewer/c3d_model_viewer.cpp + 3d_rendering/3d_render_ogl_legacy/c_ogl_3dmodel.cpp + 3d_rendering/3d_render_ogl_legacy/ogl_legacy_utils.cpp + 3d_rendering/3d_render_ogl_legacy/c3d_render_createscene_ogl_legacy.cpp + 3d_rendering/3d_render_ogl_legacy/c3d_render_ogl_legacy.cpp + 3d_rendering/3d_render_ogl_legacy/clayer_triangles.cpp + ${DIR_RAY}/ray.cpp + ${DIR_RAY_2D}/cbbox2d.cpp + ${DIR_RAY_2D}/cobject2d.cpp + ${DIR_RAY_2D}/croundsegment2d.cpp + ${DIR_RAY_3D}/cbbox.cpp + ${DIR_RAY_3D}/cbbox_ray.cpp + 3d_rendering/ccamera.cpp + 3d_rendering/cimage.cpp + 3d_rendering/ctrack_ball.cpp + 3d_rendering/trackball.cpp + common_ogl/cogl_att_list.cpp + common_ogl/ogl_utils.cpp ) add_library(3d-viewer STATIC ${3D-VIEWER_SRCS}) add_dependencies( 3d-viewer pcbcommon ) + +option( GLM_ENABLE_SIMD_SSE2 "Enable SSE2 optimizations" OFF ) +option( GLM_ENABLE_SIMD_SSE3 "Enable SSE3 optimizations" OFF ) +option( GLM_ENABLE_SIMD_AVX "Enable AVX optimizations" OFF ) +option( GLM_ENABLE_SIMD_AVX2 "Enable AVX2 optimizations" OFF ) +option( GLM_FORCE_PURE "Force 'pure' instructions" OFF ) + +if(GLM_FORCE_PURE) + add_definitions(-DGLM_FORCE_PURE) + + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-mfpmath=387) + endif() +elseif(GLM_ENABLE_SIMD_AVX2) + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-mavx2) + elseif(GLM_USE_INTEL) + add_definitions(/QxAVX2) + elseif(MSVC) + add_definitions(/arch:AVX2) + endif() +elseif(GLM_ENABLE_SIMD_AVX) + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-mavx) + elseif(GLM_USE_INTEL) + add_definitions(/QxAVX) + elseif(MSVC) + add_definitions(/arch:AVX) + endif() +elseif(GLM_ENABLE_SIMD_SSE3) + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-msse3) + elseif(GLM_USE_INTEL) + add_definitions(/QxSSE3) + elseif(MSVC) + add_definitions(/arch:SSE2) # VC doesn't support /arch:SSE3 + endif() +elseif(GLM_ENABLE_SIMD_SSE2) + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-msse2) + elseif(GLM_USE_INTEL) + add_definitions(/QxSSE2) + elseif(MSVC) + if(NOT CMAKE_CL_64) + add_definitions(/arch:SSE2) + endif() + endif() +endif() + + +option( GLM_ENABLE_FAST_MATH "Enable fast math optimizations" OFF ) + +if(GLM_ENABLE_FAST_MATH) + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-ffast-math) + endif() + + if(MSVC) + add_definitions(/fp:fast) + endif() +elseif(NOT GLM_ENABLE_FAST_MATH) + if(MSVC) + add_definitions(/fp:precise) + endif() +endif() + +if( WIN32 ) + target_link_libraries( 3d-viewer ${Boost_} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} s3d_sg ) +else() + target_link_libraries( 3d-viewer ${Boost_} ${wxWidgets_LIBRARIES} ${OPENGL_LIBRARIES} s3d_sg dl ) +endif() + +add_subdirectory( 3d_cache ) diff --git a/3d-viewer/common_ogl/cogl_att_list.cpp b/3d-viewer/common_ogl/cogl_att_list.cpp new file mode 100644 index 0000000000..abae8ffe35 --- /dev/null +++ b/3d-viewer/common_ogl/cogl_att_list.cpp @@ -0,0 +1,118 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cogl_att_list.cpp + * @brief Implements a attribute list support for openGL + */ + +#include "cogl_att_list.h" + + +/** + * Attributes list to be passed to a wxGLCanvas creation. + * + * This array should be 2*n+1 + * Sadly wxwidgets / glx < 13 allowed + * a thing named "boolean attributes" that don't take a value. + * (See src/unix/glx11.cpp -> wxGLCanvasX11::ConvertWXAttrsToGL() ). + * To avoid problems due to this, just specify those attributes twice. + * Only WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_STEREO are such boolean + * attributes. + */ +const int COGL_ATT_LIST::m_openGL_AttributesList[] = { + // Boolean attributes (using itself at padding): + WX_GL_RGBA, WX_GL_RGBA, + WX_GL_DOUBLEBUFFER, WX_GL_DOUBLEBUFFER, + + // Normal attributes with values: + WX_GL_DEPTH_SIZE, 16, + WX_GL_STENCIL_SIZE, 1, + WX_GL_SAMPLE_BUFFERS, 1, // Enable multisampling support (antialiasing). + WX_GL_SAMPLES, 0, // Disable AA for the start. + 0 // NULL termination +}; + + +int COGL_ATT_LIST::m_openGL_AttributesList_toUse[ + sizeof( COGL_ATT_LIST::m_openGL_AttributesList )] = { 0 }; + + +const int *COGL_ATT_LIST::GetAttributesList( bool aUseAntiAliasing ) +{ + memcpy( m_openGL_AttributesList_toUse, + m_openGL_AttributesList, + sizeof( m_openGL_AttributesList_toUse ) ); + + if( aUseAntiAliasing ) + { + // Check if the canvas supports multisampling. + if( wxGLCanvas::IsDisplaySupported( m_openGL_AttributesList_toUse ) ) + { + // Check for possible sample sizes, start form the top. + int maxSamples = 8; // Any higher doesn't change anything. + int samplesOffset = 0; + + for( unsigned int ii = 0; + ii < DIM( m_openGL_AttributesList_toUse ); + ii += 2 ) + { + if( m_openGL_AttributesList_toUse[ii] == WX_GL_SAMPLES ) + { + samplesOffset = ii + 1; + break; + } + } + + m_openGL_AttributesList_toUse[samplesOffset] = maxSamples; + + for( ; maxSamples > 0 && + !wxGLCanvas::IsDisplaySupported( m_openGL_AttributesList_toUse ); + maxSamples = maxSamples >> 1 ) + { + m_openGL_AttributesList_toUse[samplesOffset] = maxSamples; + } + } + else + aUseAntiAliasing = false; + } + + // Disable antialising if it failed or was not requested + if( !aUseAntiAliasing ) + { + // Disable multisampling + for( unsigned int ii = 0; + ii < DIM( m_openGL_AttributesList_toUse ); + ii += 2 ) + { + if( m_openGL_AttributesList_toUse[ii] == WX_GL_SAMPLE_BUFFERS ) + { + m_openGL_AttributesList_toUse[ii + 1] = 0; + break; + } + } + } + + return m_openGL_AttributesList_toUse; +} diff --git a/3d-viewer/common_ogl/cogl_att_list.h b/3d-viewer/common_ogl/cogl_att_list.h new file mode 100644 index 0000000000..88e97a9a9c --- /dev/null +++ b/3d-viewer/common_ogl/cogl_att_list.h @@ -0,0 +1,74 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 cogl_att_list.h + * @brief Declaration of the cogl_att_list class + */ + +#ifndef _COGL_ATT_LIST_H +#define _COGL_ATT_LIST_H + +//#include <3d_xv3d/xv3d_types.h> +#include +#include + + + +/** + * Class COGL_ATT_LIST + * Helper class to create an attribute list + */ +class COGL_ATT_LIST +{ + +public: + /** + * Get a list of attributes to pass to wxGLCanvas + * @param aUseAntiAliasing = if true try to initialize (if is supported) the list with anti aliasing capabilities + * @return a list of options to be passed in the creation of a EDA_3D_CANVAS class + */ + static const int *GetAttributesList( bool aUseAntiAliasing ); + +private: + /** + * Attributes list to be passed to a wxGLCanvas creation. + * + * This array should be 2*n+1 + * Sadly wxwidgets / glx < 13 allowed + * a thing named "boolean attributes" that don't take a value. + * (See src/unix/glx11.cpp -> wxGLCanvasX11::ConvertWXAttrsToGL() ). + * To avoid problems due to this, just specify those attributes twice. + * Only WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_STEREO are such boolean + * attributes. + */ + static const int m_openGL_AttributesList[]; + + /** + * Attributes list that was (eventualy) changed and are passed to creation + */ + static int m_openGL_AttributesList_toUse[]; +}; + +#endif // _COGL_ATT_LIST_H diff --git a/3d-viewer/common_ogl/ogl_utils.cpp b/3d-viewer/common_ogl/ogl_utils.cpp new file mode 100644 index 0000000000..db20392222 --- /dev/null +++ b/3d-viewer/common_ogl/ogl_utils.cpp @@ -0,0 +1,129 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ogl_utils.cpp + * @brief implements generic openGL functions that are common to any openGL target + */ + + +#include "openGL_includes.h" +#include "ogl_utils.h" + +void OGL_GetScreenshot( wxImage &aDstImage ) +{ + struct viewport_params + { + GLint originX; + GLint originY; + GLint x; + GLint y; + } viewport; + + glGetIntegerv( GL_VIEWPORT, (GLint*) &viewport ); + + unsigned char* pixelbuffer = (unsigned char*) malloc( viewport.x * viewport.y * 3 ); + unsigned char* alphabuffer = (unsigned char*) malloc( viewport.x * viewport.y ); + + glPixelStorei( GL_PACK_ALIGNMENT, 1 ); + glReadBuffer( GL_BACK_LEFT ); + + glReadPixels( viewport.originX, viewport.originY, + viewport.x, viewport.y, + GL_RGB, GL_UNSIGNED_BYTE, pixelbuffer ); + + glReadPixels( viewport.originX, viewport.originY, + viewport.x, viewport.y, + GL_ALPHA, GL_UNSIGNED_BYTE, alphabuffer ); + + // "Sets the image data without performing checks. + // The data given must have the size (width*height*3) + // The data must have been allocated with malloc() + // If static_data is false, after this call the pointer to the data is owned + // by the wxImage object, that will be responsible for deleting it." + aDstImage.SetData( pixelbuffer, viewport.x, viewport.y, false ); + aDstImage.SetAlpha( alphabuffer, false ); + + aDstImage = aDstImage.Mirror( false ); +} + + +GLuint OGL_LoadTexture( const CIMAGE &aImage ) +{ + unsigned char* rgbaBuffer = (unsigned char*) malloc( aImage.GetWidth() * aImage.GetHeight() * 4 ); + + unsigned char* dst = rgbaBuffer; + unsigned char* ori = aImage.GetBuffer(); + for( unsigned int i = 0; i < (aImage.GetWidth() * aImage.GetHeight()); ++i ) + { + unsigned char v = *ori; + ori++; + + dst[0] = v; + dst[1] = v; + dst[2] = v; + dst[3] = v; + dst+= 4; + } + + GLuint texture; + glPixelStorei (GL_UNPACK_ALIGNMENT, 4); + glPixelStorei (GL_PACK_ALIGNMENT, 4); + + glGenTextures( 1, &texture ); + glBindTexture( GL_TEXTURE_2D, texture ); + + //gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, aImage.GetWidth(), aImage.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuffer ); + + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, aImage.GetWidth(), aImage.GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuffer ); + + //glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + glBindTexture( GL_TEXTURE_2D, 0 ); + + free( rgbaBuffer ); + + return texture; +} + + +void OGL_SetMaterial( const SMATERIAL & aMaterial ) +{ + const SFVEC4F ambient = SFVEC4F( aMaterial.m_Ambient, 1.0f ); + const SFVEC4F diffuse = SFVEC4F( aMaterial.m_Diffuse, 1.0f ); + const SFVEC4F specular = SFVEC4F( aMaterial.m_Specular, 1.0f ); + const SFVEC4F emissive = SFVEC4F( aMaterial.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, (aMaterial.m_Shininess > 128.0f)?128.0f:aMaterial.m_Shininess ); +} diff --git a/3d-viewer/common_ogl/ogl_utils.h b/3d-viewer/common_ogl/ogl_utils.h new file mode 100644 index 0000000000..560ddde516 --- /dev/null +++ b/3d-viewer/common_ogl/ogl_utils.h @@ -0,0 +1,44 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 ogl_utils.h + * @brief + */ + +#ifndef OGL_UTILS_H_ +#define OGL_UTILS_H_ + +#include +#include "3d_rendering/cimage.h" +#include "3d_rendering/c3dmodel.h" + +void OGL_SetMaterial(const SMATERIAL & aMaterial); + +GLuint OGL_LoadTexture( const CIMAGE &aImage ); + +void OGL_GetScreenshot( wxImage &aDstImage ); + + +#endif // OGL_UTILS_H_ diff --git a/3d-viewer/common_ogl/openGL_includes.h b/3d-viewer/common_ogl/openGL_includes.h new file mode 100644 index 0000000000..a4810e9f60 --- /dev/null +++ b/3d-viewer/common_ogl/openGL_includes.h @@ -0,0 +1,48 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2015 Mario Luzeiro + * 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 openGL_includes.h + * @brief includes in a proper way the openGL related includes + */ + +#ifndef OPENGL_INCLUDES_H +#define OPENGL_INCLUDES_H + +#include + +#include + +#ifdef __WXMAC__ +# ifdef __DARWIN__ +# include +# else +# include +# endif +#else +# include +#endif + + +#endif // OPENGL_INCLUDES_H diff --git a/3d-viewer/vrml_aux.h b/3d-viewer/vrml_aux.h index 2350a44e17..e3c40ccbdb 100644 --- a/3d-viewer/vrml_aux.h +++ b/3d-viewer/vrml_aux.h @@ -35,7 +35,7 @@ #include #include #define GLM_FORCE_RADIANS -#include +#include #include #include #include diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ff922cae3..fd07c9f104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -448,17 +448,16 @@ check_find_package_result( OPENGL_FOUND "OpenGL" ) # Always defined, empty if no libraries are to be built add_custom_target( lib-dependencies ) -##################### -# Find GLEW library # -##################### +# Find GLEW library if( NOT GLEW_FOUND ) find_package( GLEW ) check_find_package_result( GLEW_FOUND "GLEW" ) endif() -###################### -# Find Cairo library # -###################### +# Find GLM library +find_package( GLM 0.9.5.4 REQUIRED ) + +# Find Cairo library if( NOT CAIRO_FOUND ) find_package( Cairo 1.8.1 QUIET ) check_find_package_result( CAIRO_FOUND "Cairo" ) @@ -813,3 +812,6 @@ if( UNIX AND NOT APPLE ) include( CPack ) endif() + +# 3D plugins +add_subdirectory( plugins ) diff --git a/CMakeModules/FindGLM.cmake b/CMakeModules/FindGLM.cmake new file mode 100644 index 0000000000..6a289ae803 --- /dev/null +++ b/CMakeModules/FindGLM.cmake @@ -0,0 +1,68 @@ +if( ${CMAKE_MAJOR_VERSION} STREQUAL "2" AND ${CMAKE_MINOR_VERSION} STREQUAL "8" + AND ( ${CMAKE_PATCH_VERSION} STREQUAL "2" OR ${CMAKE_PATCH_VERSION} STREQUAL "7" + OR ${CMAKE_PATCH_VERSION} STREQUAL "10" ) ) + + message( FATAL_ERROR "\nThis version of CMake is known to not work\n" + "Known bad versions: 2.8.2, 2.8.7, 2.8.10\n" ) + +endif() + + +find_path( GLM_INCLUDE_DIR glm.hpp PATH_SUFFIXES glm ) + + +if( NOT ${GLM_INCLUDE_DIR} STREQUAL "" ) + + # attempt to extract the GLM Version information from setup.hpp + find_file( GLM_SETUP setup.hpp PATHS ${GLM_INCLUDE_DIR} PATH_SUFFIXES core detail NO_DEFAULT_PATH ) + + if( GLM_SETUP ) + # extract the "#define GLM_VERSION*" lines + file( STRINGS ${GLM_SETUP} _version REGEX "^#define.*GLM_VERSION.*" ) + + foreach( SVAR ${_version} ) + string( REGEX MATCH GLM_VERSION_[M,A,J,O,R,I,N,P,T,C,H,E,V,I,S]* _VARNAME ${SVAR} ) + string( REGEX MATCH [0-9]+ _VALUE ${SVAR} ) + + if( NOT ${_VARNAME} STREQUAL "" AND NOT ${_VALUE} STREQUAL "" ) + set( _${_VARNAME} ${_VALUE} ) + endif() + + endforeach() + + #ensure that NOT GLM_VERSION* will evaluate to '0' + if( NOT _GLM_VERSION_MAJOR ) + set( _GLM_VERSION_MAJOR 0 ) + endif() + + if( NOT _GLM_VERSION_MINOR ) + set( _GLM_VERSION_MINOR 0 ) + endif() + + if( NOT _GLM_VERSION_PATCH ) + set( _GLM_VERSION_PATCH 0 ) + endif() + + if( NOT _GLM_VERSION_REVISION ) + set( _GLM_VERSION_REVISION 0 ) + endif() + + set( GLM_VERSION ${_GLM_VERSION_MAJOR}.${_GLM_VERSION_MINOR}.${_GLM_VERSION_PATCH}.${_GLM_VERSION_REVISION} ) + unset( GLM_SETUP CACHE ) + + endif( GLM_SETUP ) + +endif( NOT ${GLM_INCLUDE_DIR} STREQUAL "" ) + + +include( FindPackageHandleStandardArgs ) +FIND_PACKAGE_HANDLE_STANDARD_ARGS( GLM + REQUIRED_VARS GLM_INCLUDE_DIR + VERSION_VAR GLM_VERSION ) + + +mark_as_advanced( GLM_INCLUDE_DIR ) +set( GLM_VERSION_MAJOR ${_GLM_VERSION_MAJOR} CACHE INTERNAL "" ) +set( GLM_VERSION_MINOR ${_GLM_VERSION_MINOR} CACHE INTERNAL "" ) +set( GLM_VERSION_PATCH ${_GLM_VERSION_PATCH} CACHE INTERNAL "" ) +set( GLM_VERSION_TWEAK ${_GLM_VERSION_REVISION} CACHE INTERNAL "" ) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 46708f7a84..27267186ef 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories( ./dialog_about ${CAIRO_INCLUDE_DIR} ${GLEW_INCLUDE_DIR} + ${GLM_INCLUDE_DIR} ../3d-viewer ../pcbnew ../polygon diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt index 5a00f2c569..3a106825b5 100644 --- a/cvpcb/CMakeLists.txt +++ b/cvpcb/CMakeLists.txt @@ -16,6 +16,7 @@ include_directories( ../pcbnew/dialogs ../polygon ../common + ${GLM_INCLUDE_DIR} ${INC_AFTER} ) diff --git a/include/gal/opengl/glm/core/_detail.hpp b/include/gal/opengl/glm/core/_detail.hpp deleted file mode 100644 index e6b42c26ed..0000000000 --- a/include/gal/opengl/glm/core/_detail.hpp +++ /dev/null @@ -1,482 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/_detail.hpp -/// @date 2008-07-24 / 2011-06-14 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_detail -#define glm_core_detail - -#include "setup.hpp" -#include -#if(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) -#include -#endif - -namespace glm{ -namespace detail -{ - class half; - -#if(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) // C99 detected, 64 bit types available - typedef int64_t sint64; - typedef uint64_t uint64; -#elif(GLM_COMPILER & GLM_COMPILER_VC) - typedef signed __int64 sint64; - typedef unsigned __int64 uint64; -#elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_LLVM_GCC | GLM_COMPILER_CLANG)) - __extension__ typedef signed long long sint64; - __extension__ typedef unsigned long long uint64; -#elif(GLM_COMPILER & GLM_COMPILER_BC) - typedef Int64 sint64; - typedef Uint64 uint64; -#else//unknown compiler - typedef signed long long sint64; - typedef unsigned long long uint64; -#endif//GLM_COMPILER - - template - struct If - { - template - static GLM_FUNC_QUALIFIER T apply(F functor, const T& val) - { - return functor(val); - } - }; - - template<> - struct If - { - template - static GLM_FUNC_QUALIFIER T apply(F, const T& val) - { - return val; - } - }; - - //template - //struct traits - //{ - // static const bool is_signed = false; - // static const bool is_float = false; - // static const bool is_vector = false; - // static const bool is_matrix = false; - // static const bool is_genType = false; - // static const bool is_genIType = false; - // static const bool is_genUType = false; - //}; - - //template <> - //struct traits - //{ - // static const bool is_float = true; - // static const bool is_genType = true; - //}; - - //template <> - //struct traits - //{ - // static const bool is_float = true; - // static const bool is_genType = true; - //}; - - //template <> - //struct traits - //{ - // static const bool is_float = true; - // static const bool is_genType = true; - //}; - - //template - //struct desc - //{ - // typedef genType type; - // typedef genType * pointer; - // typedef genType const* const_pointer; - // typedef genType const *const const_pointer_const; - // typedef genType *const pointer_const; - // typedef genType & reference; - // typedef genType const& const_reference; - // typedef genType const& param_type; - - // typedef typename genType::value_type value_type; - // typedef typename genType::size_type size_type; - // static const typename size_type value_size; - //}; - - //template - //const typename desc::size_type desc::value_size = genType::value_size(); - - union uif32 - { - GLM_FUNC_QUALIFIER uif32() : - i(0) - {} - - GLM_FUNC_QUALIFIER uif32(float f) : - f(f) - {} - - GLM_FUNC_QUALIFIER uif32(unsigned int i) : - i(i) - {} - - float f; - unsigned int i; - }; - - union uif64 - { - GLM_FUNC_QUALIFIER uif64() : - i(0) - {} - - GLM_FUNC_QUALIFIER uif64(double f) : - f(f) - {} - - GLM_FUNC_QUALIFIER uif64(uint64 i) : - i(i) - {} - - double f; - uint64 i; - }; - - typedef uif32 uif; - - ////////////////// - // int - - template - struct is_int - { - enum is_int_enum - { - _YES = 0, - _NO = 1 - }; - }; - -#define GLM_DETAIL_IS_INT(T) \ - template <> \ - struct is_int \ - { \ - enum is_int_enum \ - { \ - _YES = 1, \ - _NO = 0 \ - }; \ - } - - ////////////////// - // uint - - template - struct is_uint - { - enum is_uint_enum - { - _YES = 0, - _NO = 1 - }; - }; - -#define GLM_DETAIL_IS_UINT(T) \ - template <> \ - struct is_uint \ - { \ - enum is_uint_enum \ - { \ - _YES = 1, \ - _NO = 0 \ - }; \ - } - - //GLM_DETAIL_IS_UINT(unsigned long long) - - ////////////////// - // float - - template - struct is_float - { - enum is_float_enum - { - _YES = 0, - _NO = 1 - }; - }; - -#define GLM_DETAIL_IS_FLOAT(T) \ - template <> \ - struct is_float \ - { \ - enum is_float_enum \ - { \ - _YES = 1, \ - _NO = 0 \ - }; \ - } - - GLM_DETAIL_IS_FLOAT(detail::half); - GLM_DETAIL_IS_FLOAT(float); - GLM_DETAIL_IS_FLOAT(double); - GLM_DETAIL_IS_FLOAT(long double); - - ////////////////// - // bool - - template - struct is_bool - { - enum is_bool_enum - { - _YES = 0, - _NO = 1 - }; - }; - - template <> - struct is_bool - { - enum is_bool_enum - { - _YES = 1, - _NO = 0 - }; - }; - - ////////////////// - // vector - - template - struct is_vector - { - enum is_vector_enum - { - _YES = 0, - _NO = 1 - }; - }; - -# define GLM_DETAIL_IS_VECTOR(TYPE) \ - template \ - struct is_vector > \ - { \ - enum is_vector_enum \ - { \ - _YES = 1, \ - _NO = 0 \ - }; \ - } - - ////////////////// - // matrix - - template - struct is_matrix - { - enum is_matrix_enum - { - _YES = 0, - _NO = 1 - }; - }; - -#define GLM_DETAIL_IS_MATRIX(T) \ - template <> \ - struct is_matrix \ - { \ - enum is_matrix_enum \ - { \ - _YES = 1, \ - _NO = 0 \ - }; \ - } - - ////////////////// - // type - - template - struct type - { - enum type_enum - { - is_float = is_float::_YES, - is_int = is_int::_YES, - is_uint = is_uint::_YES, - is_bool = is_bool::_YES - }; - }; - - ////////////////// - // type - - typedef signed char int8; - typedef signed short int16; - typedef signed int int32; - typedef detail::sint64 int64; - - typedef unsigned char uint8; - typedef unsigned short uint16; - typedef unsigned int uint32; - typedef detail::uint64 uint64; - - typedef detail::half float16; - typedef float float32; - typedef double float64; - - ////////////////// - // float_or_int_trait - - struct float_or_int_value - { - enum - { - GLM_ERROR, - GLM_FLOAT, - GLM_INT - }; - }; - - template - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_ERROR}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_INT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_FLOAT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_FLOAT}; - }; - - template <> - struct float_or_int_trait - { - enum{ID = float_or_int_value::GLM_FLOAT}; - }; - -}//namespace detail -}//namespace glm - -#if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2005)) -# define GLM_DEPRECATED __declspec(deprecated) -# define GLM_ALIGN(x) __declspec(align(x)) -# define GLM_ALIGNED_STRUCT(x) __declspec(align(x)) struct -# define GLM_RESTRICT __declspec(restrict) -# define GLM_RESTRICT_VAR __restrict -# define GLM_CONSTEXPR -#elif(GLM_COMPILER & GLM_COMPILER_INTEL) -# define GLM_DEPRECATED -# define GLM_ALIGN(x) __declspec(align(x)) -# define GLM_ALIGNED_STRUCT(x) __declspec(align(x)) struct -# define GLM_RESTRICT -# define GLM_RESTRICT_VAR __restrict -# define GLM_CONSTEXPR -#elif(((GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_LLVM_GCC)) && (GLM_COMPILER >= GLM_COMPILER_GCC31)) || (GLM_COMPILER & GLM_COMPILER_CLANG)) -# define GLM_DEPRECATED __attribute__((__deprecated__)) -# define GLM_ALIGN(x) __attribute__((aligned(x))) -# define GLM_ALIGNED_STRUCT(x) struct __attribute__((aligned(x))) -# if(GLM_COMPILER >= GLM_COMPILER_GCC33) -# define GLM_RESTRICT __restrict__ -# define GLM_RESTRICT_VAR __restrict__ -# else -# define GLM_RESTRICT -# define GLM_RESTRICT_VAR -# endif -# define GLM_RESTRICT __restrict__ -# define GLM_RESTRICT_VAR __restrict__ -# if((GLM_COMPILER >= GLM_COMPILER_GCC47) && ((GLM_LANG & GLM_LANG_CXX0X) == GLM_LANG_CXX0X)) -# define GLM_CONSTEXPR constexpr -# else -# define GLM_CONSTEXPR -# endif -#else -# define GLM_DEPRECATED -# define GLM_ALIGN -# define GLM_ALIGNED_STRUCT(x) -# define GLM_RESTRICT -# define GLM_RESTRICT_VAR -# define GLM_CONSTEXPR -#endif//GLM_COMPILER - -#endif//glm_core_detail diff --git a/include/gal/opengl/glm/core/_fixes.hpp b/include/gal/opengl/glm/core/_fixes.hpp deleted file mode 100644 index b4cec5f259..0000000000 --- a/include/gal/opengl/glm/core/_fixes.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/_fixes.hpp -/// @date 2011-02-21 / 2011-11-22 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#include - -//! Workaround for compatibility with other libraries -#ifdef max -#undef max -#endif - -//! Workaround for compatibility with other libraries -#ifdef min -#undef min -#endif - -//! Workaround for Android -#ifdef isnan -#undef isnan -#endif - -//! Workaround for Android -#ifdef isinf -#undef isinf -#endif - -//! Workaround for Chrone Native Client -#ifdef log2 -#undef log2 -#endif - diff --git a/include/gal/opengl/glm/core/_swizzle.hpp b/include/gal/opengl/glm/core/_swizzle.hpp deleted file mode 100644 index dc069443f7..0000000000 --- a/include/gal/opengl/glm/core/_swizzle.hpp +++ /dev/null @@ -1,861 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/_swizzle.hpp -/// @date 2006-04-20 / 2011-02-16 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_swizzle -#define glm_core_swizzle - -#include "_swizzle_func.hpp" - -namespace glm -{ - enum comp - { - X = 0, - R = 0, - S = 0, - Y = 1, - G = 1, - T = 1, - Z = 2, - B = 2, - P = 2, - W = 3, - A = 3, - Q = 3 - }; -}//namespace glm - -namespace glm{ -namespace detail -{ - // Internal class for implementing swizzle operators - template - struct _swizzle_base0 - { - typedef T value_type; - - protected: - GLM_FUNC_QUALIFIER value_type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } - GLM_FUNC_QUALIFIER const value_type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } - - // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. - // The size 1 buffer is assumed to aligned to the actual members so that the - // elem() - char _buffer[1]; - }; - - template - struct _swizzle_base1 : public _swizzle_base0 - { - }; - - template - struct _swizzle_base1 : public _swizzle_base0 - { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1)); } - }; - - template - struct _swizzle_base1 : public _swizzle_base0 - { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2)); } - }; - - template - struct _swizzle_base1 : public _swizzle_base0 - { - GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } - }; - - // Internal class for implementing swizzle operators - /* - Template parameters: - - ValueType = type of scalar values (e.g. float, double) - VecType = class the swizzle is applies to (e.g. tvec3) - N = number of components in the vector (e.g. 3) - E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec - - DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles - containing duplicate elements so that they cannot be used as r-values). - */ - template - struct _swizzle_base2 : public _swizzle_base1 - { - typedef VecType vec_type; - typedef ValueType value_type; - - GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const ValueType& t) - { - for (int i = 0; i < N; ++i) - (*this)[i] = t; - return *this; - } - - GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const VecType& that) - { - struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e = t; } - }; - _apply_op(that, op()); - return *this; - } - - GLM_FUNC_QUALIFIER void operator -= (const VecType& that) - { - struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e -= t; } - }; - _apply_op(that, op()); - } - - GLM_FUNC_QUALIFIER void operator += (const VecType& that) - { - struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e += t; } - }; - _apply_op(that, op()); - } - - GLM_FUNC_QUALIFIER void operator *= (const VecType& that) - { - struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e *= t; } - }; - _apply_op(that, op()); - } - - GLM_FUNC_QUALIFIER void operator /= (const VecType& that) - { - struct op { - GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e /= t; } - }; - _apply_op(that, op()); - } - - GLM_FUNC_QUALIFIER value_type& operator[] (size_t i) - { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; - return this->elem(offset_dst[i]); - } - GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const - { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; - return this->elem(offset_dst[i]); - } - protected: - template - GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) - { - // Make a copy of the data in this == &that. - // The copier should optimize out the copy in cases where the function is - // properly inlined and the copy is not necessary. - ValueType t[N]; - for (int i = 0; i < N; ++i) - t[i] = that[i]; - for (int i = 0; i < N; ++i) - op( (*this)[i], t[i] ); - } - }; - - // Specialization for swizzles containing duplicate elements. These cannot be modified. - template - struct _swizzle_base2 : public _swizzle_base1 - { - typedef VecType vec_type; - typedef ValueType value_type; - - struct Stub {}; - GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const &) { return *this; } - - GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const - { -#ifndef __CUDA_ARCH__ - static -#endif - const int offset_dst[4] = { E0, E1, E2, E3 }; - return this->elem(offset_dst[i]); - } - }; - - template - struct swizzle : public _swizzle_base2 - { - typedef _swizzle_base2 base_type; - - using base_type::operator=; - - GLM_FUNC_QUALIFIER operator VecType () const { return (*this)(); } - }; - -// -// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros -// -#define _GLM_SWIZZLE_TEMPLATE1 template -#define _GLM_SWIZZLE_TEMPLATE2 template -#define _GLM_SWIZZLE_TYPE1 glm::detail::swizzle -#define _GLM_SWIZZLE_TYPE2 glm::detail::swizzle - -// -// Wrapper for a binary operator (e.g. u.yy + v.zy) -// -#define _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ - _GLM_SWIZZLE_TEMPLATE2 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ - { \ - return a() OPERAND b(); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const V& b) \ - { \ - return a() OPERAND b; \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const V& a, const _GLM_SWIZZLE_TYPE1& b) \ - { \ - return a OPERAND b(); \ - } - -// -// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz) -// -#define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \ - { \ - return a() OPERAND b; \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER V operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \ - { \ - return a OPERAND b(); \ - } - -// -// Macro for wrapping a function taking one argument (e.g. abs()) -// -#define _GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a) \ - { \ - return FUNCTION(a()); \ - } - -// -// Macro for wrapping a function taking two vector arguments (e.g. dot()). -// -#define _GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \ - _GLM_SWIZZLE_TEMPLATE2 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ - { \ - return FUNCTION(a(), b()); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b) \ - { \ - return FUNCTION(a(), b()); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename V& b) \ - { \ - return FUNCTION(a(), b); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const _GLM_SWIZZLE_TYPE1& b) \ - { \ - return FUNCTION(a, b()); \ - } - -// -// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()). -// -#define _GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \ - _GLM_SWIZZLE_TEMPLATE2 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b, const T& c) \ - { \ - return FUNCTION(a(), b(), c); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ - { \ - return FUNCTION(a(), b(), c); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\ - { \ - return FUNCTION(a(), b, c); \ - } \ - _GLM_SWIZZLE_TEMPLATE1 \ - GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ - { \ - return FUNCTION(a, b(), c); \ - } - -}//namespace detail -}//namespace glm - -namespace glm -{ - namespace detail - { - _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-) - _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) - _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+) - _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-) - _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*) - _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/) - } - - // - // Swizzles are distinct types from the unswizzled type. The below macros will - // provide template specializations for the swizzle types for the given functions - // so that the compiler does not have any ambiguity to choosing how to handle - // the function. - // - // The alternative is to use the operator()() when calling the function in order - // to explicitly convert the swizzled type to the unswizzled type. - // - - //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs); - //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos); - //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh); - //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all); - //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any); - - //_GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot); - //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross); - //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step); - //_GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix); -} - -#define _GLM_SWIZZLE2_2_MEMBERS(T,P,E0,E1) \ - struct { glm::detail::swizzle<2,T,P,0,0,-1,-2> E0 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,0,1,-1,-2> E0 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P,1,0,-1,-2> E1 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,1,1,-1,-2> E1 ## E1; }; - -#define _GLM_SWIZZLE2_3_MEMBERS(T,P2,E0,E1) \ - struct { glm::detail::swizzle<3,T,P2,0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P2,0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P2,0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P2,0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P2,1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P2,1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P2,1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P2,1,1,1,-1> E1 ## E1 ## E1; }; - -#define _GLM_SWIZZLE2_4_MEMBERS(T,P2,E0,E1) \ - struct { glm::detail::swizzle<4,T,P2,0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,1,1> E1 ## E1 ## E1 ## E1; }; - -#define _GLM_SWIZZLE3_2_MEMBERS(T,P2,E0,E1,E2) \ - struct { glm::detail::swizzle<2,T,P2,0,0,-1,-2> E0 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P2,0,1,-1,-2> E0 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P2,0,2,-1,-2> E0 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P2,1,0,-1,-2> E1 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P2,1,1,-1,-2> E1 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P2,1,2,-1,-2> E1 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P2,2,0,-1,-2> E2 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P2,2,1,-1,-2> E2 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P2,2,2,-1,-2> E2 ## E2; }; - -#define _GLM_SWIZZLE3_3_MEMBERS(T,P,E0,E1,E2) \ - struct { glm::detail::swizzle<3,T,P,0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,2,-1> E2 ## E2 ## E2; }; - -#define _GLM_SWIZZLE3_4_MEMBERS(T,P2,E0,E1,E2) \ - struct { glm::detail::swizzle<4,T,P2,0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P2,2,2,2,2> E2 ## E2 ## E2 ## E2; }; - -#define _GLM_SWIZZLE4_2_MEMBERS(T,P,E0,E1,E2,E3) \ - struct { glm::detail::swizzle<2,T,P,0,0,-1,-2> E0 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,0,1,-1,-2> E0 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P,0,2,-1,-2> E0 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P,0,3,-1,-2> E0 ## E3; }; \ - struct { glm::detail::swizzle<2,T,P,1,0,-1,-2> E1 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,1,1,-1,-2> E1 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P,1,2,-1,-2> E1 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P,1,3,-1,-2> E1 ## E3; }; \ - struct { glm::detail::swizzle<2,T,P,2,0,-1,-2> E2 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,2,1,-1,-2> E2 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P,2,2,-1,-2> E2 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P,2,3,-1,-2> E2 ## E3; }; \ - struct { glm::detail::swizzle<2,T,P,3,0,-1,-2> E3 ## E0; }; \ - struct { glm::detail::swizzle<2,T,P,3,1,-1,-2> E3 ## E1; }; \ - struct { glm::detail::swizzle<2,T,P,3,2,-1,-2> E3 ## E2; }; \ - struct { glm::detail::swizzle<2,T,P,3,3,-1,-2> E3 ## E3; }; - -#define _GLM_SWIZZLE4_3_MEMBERS(T,P,E0,E1,E2,E3) \ - struct { glm::detail::swizzle<3,T,P,0,0,0,-1> E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,0,1,-1> E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,0,2,-1> E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,0,3,-1> E0 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,0,-1> E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,1,-1> E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,2,-1> E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,1,3,-1> E0 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,0,-1> E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,1,-1> E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,2,-1> E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,2,3,-1> E0 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,0,3,0,-1> E0 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,0,3,1,-1> E0 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,0,3,2,-1> E0 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,0,3,3,-1> E0 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,0,-1> E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,1,-1> E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,2,-1> E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,0,3,-1> E1 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,0,-1> E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,1,-1> E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,2,-1> E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,1,3,-1> E1 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,0,-1> E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,1,-1> E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,2,-1> E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,2,3,-1> E1 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,1,3,0,-1> E1 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,1,3,1,-1> E1 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,1,3,2,-1> E1 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,1,3,3,-1> E1 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,0,-1> E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,1,-1> E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,2,-1> E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,0,3,-1> E2 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,0,-1> E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,1,-1> E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,2,-1> E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,1,3,-1> E2 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,0,-1> E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,1,-1> E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,2,-1> E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,2,3,-1> E2 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,2,3,0,-1> E2 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,2,3,1,-1> E2 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,2,3,2,-1> E2 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,2,3,3,-1> E2 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,3,0,0,-1> E3 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,3,0,1,-1> E3 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,3,0,2,-1> E3 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,3,0,3,-1> E3 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,3,1,0,-1> E3 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,3,1,1,-1> E3 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,3,1,2,-1> E3 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,3,1,3,-1> E3 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,3,2,0,-1> E3 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,3,2,1,-1> E3 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,3,2,2,-1> E3 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,3,2,3,-1> E3 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<3,T,P,3,3,0,-1> E3 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<3,T,P,3,3,1,-1> E3 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<3,T,P,3,3,2,-1> E3 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<3,T,P,3,3,3,-1> E3 ## E3 ## E3; }; - -#define _GLM_SWIZZLE4_4_MEMBERS(T,P,E0,E1,E2,E3) \ - struct { glm::detail::swizzle<4,T,P,0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ - struct { glm::detail::swizzle<4,T,P,3,3,3,3> E3 ## E3 ## E3 ## E3; }; - -#endif//glm_core_swizzle diff --git a/include/gal/opengl/glm/core/_swizzle_func.hpp b/include/gal/opengl/glm/core/_swizzle_func.hpp deleted file mode 100644 index be66784373..0000000000 --- a/include/gal/opengl/glm/core/_swizzle_func.hpp +++ /dev/null @@ -1,787 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/_swizzle_func.hpp -/// @date 2011-10-16 / 2011-10-16 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_swizzle_func -#define glm_core_swizzle_func - -#define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ - SWIZZLED_TYPE A ## B() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B); \ - } - -#define GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ - SWIZZLED_TYPE A ## B ## C() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B, this->C); \ - } - -#define GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ - SWIZZLED_TYPE A ## B ## C ## D() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B, this->C, this->D); \ - } - -#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ - template \ - SWIZZLED_TYPE CLASS_TYPE::A ## B() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B); \ - } - -#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ - template \ - SWIZZLED_TYPE CLASS_TYPE::A ## B ## C() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B, this->C); \ - } - -#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ - template \ - SWIZZLED_TYPE CLASS_TYPE::A ## B ## C ## D() CONST \ - { \ - return SWIZZLED_TYPE(this->A, this->B, this->C, this->D); \ - } - -#define GLM_MUTABLE - -#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) - -#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE) \ - GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, x, y) \ - GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, r, g) \ - GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, s, t) - -//GLM_SWIZZLE_GEN_REF_FROM_VEC2(valType, detail::vec2, detail::ref2) - -#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) - -#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B, A) - -#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) - -#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, x, y, z) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, r, g, b) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, s, t, q) - -//GLM_SWIZZLE_GEN_REF_FROM_VEC3(valType, detail::vec3, detail::ref2, detail::ref3) - -#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, C) - -#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B) - -#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C, A) - -#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) - -#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ - GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, q, p) - -//GLM_SWIZZLE_GEN_REF_FROM_VEC4(valType, detail::vec4, detail::ref2, detail::ref3, detail::ref4) - -#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) - -#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) - -#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B) \ - GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t) - -//GLM_SWIZZLE_GEN_VEC_FROM_VEC2(valType, detail::vec2, detail::vec2, detail::vec3, detail::vec4) - -#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) - -#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) - -#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, C) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, q) - -//GLM_SWIZZLE_GEN_VEC_FROM_VEC3(valType, detail::vec3, detail::vec2, detail::vec3, detail::vec4) - -#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C) \ - GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D) - -#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C) \ - GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D) - -#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, D) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, A) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, B) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, C) \ - GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, D) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ - GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) - -#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ - GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, q, p) - -//GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4) - -#endif//glm_core_swizzle_func diff --git a/include/gal/opengl/glm/core/_vectorize.hpp b/include/gal/opengl/glm/core/_vectorize.hpp deleted file mode 100644 index 9984014fa8..0000000000 --- a/include/gal/opengl/glm/core/_vectorize.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/_vectorize.hpp -/// @date 2011-10-14 / 2011-10-14 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#define VECTORIZE2_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func( \ - detail::tvec2 const & v) \ - { \ - return detail::tvec2( \ - func(v.x), \ - func(v.y)); \ - } - -#define VECTORIZE3_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func( \ - detail::tvec3 const & v) \ - { \ - return detail::tvec3( \ - func(v.x), \ - func(v.y), \ - func(v.z)); \ - } - -#define VECTORIZE4_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func( \ - detail::tvec4 const & v) \ - { \ - return detail::tvec4( \ - func(v.x), \ - func(v.y), \ - func(v.z), \ - func(v.w)); \ - } - -#define VECTORIZE_VEC(func) \ - VECTORIZE2_VEC(func) \ - VECTORIZE3_VEC(func) \ - VECTORIZE4_VEC(func) - -#define VECTORIZE2_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func \ - ( \ - detail::tvec2 const & x, \ - typename detail::tvec2::value_type const & y \ - ) \ - { \ - return detail::tvec2( \ - func(x.x, y), \ - func(x.y, y)); \ - } - -#define VECTORIZE3_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func \ - ( \ - detail::tvec3 const & x, \ - typename detail::tvec3::value_type const & y \ - ) \ - { \ - return detail::tvec3( \ - func(x.x, y), \ - func(x.y, y), \ - func(x.z, y)); \ - } - -#define VECTORIZE4_VEC_SCA(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func \ - ( \ - detail::tvec4 const & x, \ - typename detail::tvec4::value_type const & y \ - ) \ - { \ - return detail::tvec4( \ - func(x.x, y), \ - func(x.y, y), \ - func(x.z, y), \ - func(x.w, y)); \ - } - -#define VECTORIZE_VEC_SCA(func) \ - VECTORIZE2_VEC_SCA(func) \ - VECTORIZE3_VEC_SCA(func) \ - VECTORIZE4_VEC_SCA(func) - -#define VECTORIZE2_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec2 func \ - ( \ - detail::tvec2 const & x, \ - detail::tvec2 const & y \ - ) \ - { \ - return detail::tvec2( \ - func(x.x, y.x), \ - func(x.y, y.y)); \ - } - -#define VECTORIZE3_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec3 func \ - ( \ - detail::tvec3 const & x, \ - detail::tvec3 const & y \ - ) \ - { \ - return detail::tvec3( \ - func(x.x, y.x), \ - func(x.y, y.y), \ - func(x.z, y.z)); \ - } - -#define VECTORIZE4_VEC_VEC(func) \ - template \ - GLM_FUNC_QUALIFIER detail::tvec4 func \ - ( \ - detail::tvec4 const & x, \ - detail::tvec4 const & y \ - ) \ - { \ - return detail::tvec4( \ - func(x.x, y.x), \ - func(x.y, y.y), \ - func(x.z, y.z), \ - func(x.w, y.w)); \ - } - -#define VECTORIZE_VEC_VEC(func) \ - VECTORIZE2_VEC_VEC(func) \ - VECTORIZE3_VEC_VEC(func) \ - VECTORIZE4_VEC_VEC(func) diff --git a/include/gal/opengl/glm/core/dummy.cpp b/include/gal/opengl/glm/core/dummy.cpp deleted file mode 100644 index 38fcca0206..0000000000 --- a/include/gal/opengl/glm/core/dummy.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/dummy.cpp -/// @date 2011-01-19 / 2011-06-15 -/// @author Christophe Riccio -/// -/// GLM is a header only library. There is nothing to compile. -/// dummy.cpp exist only a wordaround for CMake file. -/////////////////////////////////////////////////////////////////////////////////// - -#define GLM_MESSAGES -#include "../glm.hpp" - -//#error "GLM is a header only library" - -int main() -{ - -} diff --git a/include/gal/opengl/glm/core/func_common.hpp b/include/gal/opengl/glm/core/func_common.hpp deleted file mode 100644 index fcf7eb7619..0000000000 --- a/include/gal/opengl/glm/core/func_common.hpp +++ /dev/null @@ -1,430 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_common.hpp -/// @date 2008-03-08 / 2010-01-26 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.3 Common Functions -/// -/// @defgroup core_func_common Common functions -/// @ingroup core -/// -/// These all operate component-wise. The description is per component. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef GLM_CORE_func_common -#define GLM_CORE_func_common GLM_VERSION - -#include "_fixes.hpp" - -namespace glm -{ - /// @addtogroup core_func_common - /// @{ - - /// Returns x if x >= 0; otherwise, it returns -x. - /// - /// @tparam genType floating-point or signed integer; scalar or vector types. - /// - /// @see GLSL abs man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType abs(genType const & x); - - /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. - /// - /// @tparam genType Floating-point or signed integer; scalar or vector types. - /// - /// @see GLSL sign man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType sign(genType const & x); - - /// Returns a value equal to the nearest integer that is less then or equal to x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL floor man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType floor(genType const & x); - - /// Returns a value equal to the nearest integer to x - /// whose absolute value is not larger than the absolute value of x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL trunc man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType trunc(genType const & x); - - /// Returns a value equal to the nearest integer to x. - /// The fraction 0.5 will round in a direction chosen by the - /// implementation, presumably the direction that is fastest. - /// This includes the possibility that round(x) returns the - /// same value as roundEven(x) for all values of x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL round man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType round(genType const & x); - - /// Returns a value equal to the nearest integer to x. - /// A fractional part of 0.5 will round toward the nearest even - /// integer. (Both 3.5 and 4.5 for x will return 4.0.) - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL roundEven man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - /// @see New round to even technique - template - GLM_FUNC_DECL genType roundEven(genType const & x); - - /// Returns a value equal to the nearest integer - /// that is greater than or equal to x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL ceil man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType ceil(genType const & x); - - /// Return x - floor(x). - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL fract man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType fract(genType const & x); - - /// Modulus. Returns x - y * floor(x / y) - /// for each component in x using the floating point value y. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL mod man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType mod( - genType const & x, - genType const & y); - - /// Modulus. Returns x - y * floor(x / y) - /// for each component in x using the floating point value y. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL mod man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType mod( - genType const & x, - typename genType::value_type const & y); - - /// Returns the fractional part of x and sets i to the integer - /// part (as a whole number floating point value). Both the - /// return value and the output parameter will have the same - /// sign as x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL modf man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType modf( - genType const & x, - genType & i); - - /// Returns y if y < x; otherwise, it returns x. - /// - /// @tparam genType Floating-point or integer; scalar or vector types. - /// - /// @see GLSL min man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType min( - genType const & x, - genType const & y); - - template - GLM_FUNC_DECL genType min( - genType const & x, - typename genType::value_type const & y); - - /// Returns y if x < y; otherwise, it returns x. - /// - /// @tparam genType Floating-point or integer; scalar or vector types. - /// - /// @see GLSL max man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType max( - genType const & x, - genType const & y); - - template - GLM_FUNC_DECL genType max( - genType const & x, - typename genType::value_type const & y); - - /// Returns min(max(x, minVal), maxVal) for each component in x - /// using the floating-point values minVal and maxVal. - /// - /// @tparam genType Floating-point or integer; scalar or vector types. - /// - /// @see GLSL clamp man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType clamp( - genType const & x, - genType const & minVal, - genType const & maxVal); - - template - GLM_FUNC_DECL genType clamp( - genType const & x, - typename genType::value_type const & minVal, - typename genType::value_type const & maxVal); - - /// If genTypeU is a floating scalar or vector: - /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of - /// x and y using the floating-point value a. - /// The value for a is not restricted to the range [0, 1]. - /// - /// If genTypeU is a boolean scalar or vector: - /// Selects which vector each returned component comes - /// from. For a component of that is false, the - /// corresponding component of x is returned. For a - /// component of a that is true, the corresponding - /// component of y is returned. Components of x and y that - /// are not selected are allowed to be invalid floating point - /// values and will have no effect on the results. Thus, this - /// provides different functionality than - /// genType mix(genType x, genType y, genType(a)) - /// where a is a Boolean vector. - /// - /// @see GLSL mix man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - /// - /// @param[in] x Value to interpolate. - /// @param[in] y Value to interpolate. - /// @param[in] a Interpolant. - /// - /// @tparam genTypeT Floating point scalar or vector. - /// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT. - /// - /// @code - /// #include - /// ... - /// float a; - /// bool b; - /// glm::dvec3 e; - /// glm::dvec3 f; - /// glm::vec4 g; - /// glm::vec4 h; - /// ... - /// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors. - /// glm::vec4 s = glm::mix(g, h, b); // Teturns g or h; - /// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second. - /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. - /// @endcode - template - GLM_FUNC_DECL genTypeT mix(genTypeT const & x, genTypeT const & y, genTypeU const & a); - - //! Returns 0.0 if x < edge, otherwise it returns 1.0. - //! - /// @see GLSL step man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType step( - genType const & edge, - genType const & x); - - template - GLM_FUNC_DECL genType step( - typename genType::value_type const & edge, - genType const & x); - - /// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and - /// performs smooth Hermite interpolation between 0 and 1 - /// when edge0 < x < edge1. This is useful in cases where - /// you would want a threshold function with a smooth - /// transition. This is equivalent to: - /// genType t; - /// t = clamp ((x - edge0) / (edge1 - edge0), 0, 1); - /// return t * t * (3 - 2 * t); - /// Results are undefined if edge0 >= edge1. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL smoothstep man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType smoothstep( - genType const & edge0, - genType const & edge1, - genType const & x); - - template - GLM_FUNC_DECL genType smoothstep( - typename genType::value_type const & edge0, - typename genType::value_type const & edge1, - genType const & x); - - /// Returns true if x holds a NaN (not a number) - /// representation in the underlying implementation's set of - /// floating point representations. Returns false otherwise, - /// including for implementations with no NaN - /// representations. - /// - /// /!\ When using compiler fast math, this function may fail. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL isnan man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL typename genType::bool_type isnan(genType const & x); - - /// Returns true if x holds a positive infinity or negative - /// infinity representation in the underlying implementation's - /// set of floating point representations. Returns false - /// otherwise, including for implementations with no infinity - /// representations. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL isinf man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL typename genType::bool_type isinf(genType const & x); - - /// Returns a signed integer value representing - /// the encoding of a floating-point value. The floatingpoint - /// value's bit-level representation is preserved. - /// - /// @tparam genType Single-precision floating-point scalar or vector types. - /// @tparam genIType Signed integer scalar or vector types. - /// - /// @see GLSL floatBitsToInt man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genIType floatBitsToInt(genType const & value); - - /// Returns a unsigned integer value representing - /// the encoding of a floating-point value. The floatingpoint - /// value's bit-level representation is preserved. - /// - /// @tparam genType Single-precision floating-point scalar or vector types. - /// @tparam genUType Unsigned integer scalar or vector types. - /// - /// @see GLSL floatBitsToUint man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genUType floatBitsToUint(genType const & value); - - /// Returns a floating-point value corresponding to a signed - /// integer encoding of a floating-point value. - /// If an inf or NaN is passed in, it will not signal, and the - /// resulting floating point value is unspecified. Otherwise, - /// the bit-level representation is preserved. - /// - /// @tparam genType Single-precision floating-point scalar or vector types. - /// @tparam genIType Signed integer scalar or vector types. - /// - /// @see GLSL intBitsToFloat man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - /// - /// @todo Clarify this declaration, we don't need to actually specify the return type - template - GLM_FUNC_DECL genType intBitsToFloat(genIType const & value); - - /// Returns a floating-point value corresponding to a - /// unsigned integer encoding of a floating-point value. - /// If an inf or NaN is passed in, it will not signal, and the - /// resulting floating point value is unspecified. Otherwise, - /// the bit-level representation is preserved. - /// - /// @tparam genType Single-precision floating-point scalar or vector types. - /// @tparam genUType Unsigned integer scalar or vector types. - /// - /// @see GLSL uintBitsToFloat man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - /// - /// @todo Clarify this declaration, we don't need to actually specify the return type - template - GLM_FUNC_DECL genType uintBitsToFloat(genUType const & value); - - /// Computes and returns a * b + c. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL fma man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType fma(genType const & a, genType const & b, genType const & c); - - /// Splits x into a floating-point significand in the range - /// [0.5, 1.0) and an integral exponent of two, such that: - /// x = significand * exp(2, exponent) - /// - /// The significand is returned by the function and the - /// exponent is returned in the parameter exp. For a - /// floating-point value of zero, the significant and exponent - /// are both zero. For a floating-point value that is an - /// infinity or is not a number, the results are undefined. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL frexp man page - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType frexp(genType const & x, genIType & exp); - - /// Builds a floating-point number from x and the - /// corresponding integral exponent of two in exp, returning: - /// significand * exp(2, exponent) - /// - /// If this product is too large to be represented in the - /// floating-point type, the result is undefined. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL ldexp man page; - /// @see GLSL 4.20.8 specification, section 8.3 Common Functions - template - GLM_FUNC_DECL genType ldexp(genType const & x, genIType const & exp); - - /// @} -}//namespace glm - -#include "func_common.inl" - -#endif//GLM_CORE_func_common diff --git a/include/gal/opengl/glm/core/func_common.inl b/include/gal/opengl/glm/core/func_common.inl deleted file mode 100644 index 1c0d9df979..0000000000 --- a/include/gal/opengl/glm/core/func_common.inl +++ /dev/null @@ -1,1226 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_common.inl -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm{ -namespace detail -{ - template - struct Abs_ - {}; - - template - struct Abs_ - { - GLM_FUNC_QUALIFIER static genFIType get(genFIType const & x) - { - GLM_STATIC_ASSERT( - detail::type::is_float || - detail::type::is_int, "'abs' only accept floating-point and integer inputs"); - return x >= genFIType(0) ? x : -x; - // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; - } - }; - - template - struct Abs_ - { - GLM_FUNC_QUALIFIER static genFIType get(genFIType const & x) - { - GLM_STATIC_ASSERT( - detail::type::is_uint, "'abs' only accept floating-point and integer inputs"); - return x; - } - }; -}//namespace detail - - // abs - template - GLM_FUNC_QUALIFIER genFIType abs - ( - genFIType const & x - ) - { - return detail::Abs_::is_signed>::get(x); - } - - VECTORIZE_VEC(abs) - - // sign - //Try something like based on x >> 31 to get the sign bit - template - GLM_FUNC_QUALIFIER genFIType sign - ( - genFIType const & x - ) - { - GLM_STATIC_ASSERT( - detail::type::is_float || - detail::type::is_int, "'sign' only accept signed inputs"); - - genFIType result; - if(x > genFIType(0)) - result = genFIType(1); - else if(x < genFIType(0)) - result = genFIType(-1); - else - result = genFIType(0); - return result; - } - - VECTORIZE_VEC(sign) - - // floor - template <> - GLM_FUNC_QUALIFIER detail::half floor(detail::half const & x) - { - return detail::half(::std::floor(float(x))); - } - - template - GLM_FUNC_QUALIFIER genType floor(genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'floor' only accept floating-point inputs"); - - return ::std::floor(x); - } - - VECTORIZE_VEC(floor) - - // trunc - template - GLM_FUNC_QUALIFIER genType trunc(genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'trunc' only accept floating-point inputs"); - return x < 0 ? -floor(-x) : floor(x); - } - - VECTORIZE_VEC(trunc) - - // round - template - GLM_FUNC_QUALIFIER genType round(genType const& x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'round' only accept floating-point inputs"); - - if(x < 0) - return genType(int(x - genType(0.5))); - return genType(int(x + genType(0.5))); - } - - VECTORIZE_VEC(round) - -/* - // roundEven - template - GLM_FUNC_QUALIFIER genType roundEven(genType const& x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'roundEven' only accept floating-point inputs"); - - return genType(int(x + genType(int(x) % 2))); - } -*/ - - // roundEven - template - GLM_FUNC_QUALIFIER genType roundEven(genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'roundEven' only accept floating-point inputs"); - - int Integer = int(x); - genType IntegerPart = genType(Integer); - genType FractionalPart = fract(x); - - if(FractionalPart > genType(0.5) || FractionalPart < genType(0.5)) - { - return round(x); - } - else if((Integer % 2) == 0) - { - return IntegerPart; - } - else if(x <= genType(0)) // Work around... - { - return IntegerPart - 1; - } - else - { - return IntegerPart + 1; - } - //else // Bug on MinGW 4.5.2 - //{ - // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); - //} - } - - VECTORIZE_VEC(roundEven) - - // ceil - template - GLM_FUNC_QUALIFIER genType ceil(genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'ceil' only accept floating-point inputs"); - - return ::std::ceil(x); - } - - VECTORIZE_VEC(ceil) - - // fract - template - GLM_FUNC_QUALIFIER genType fract - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'fract' only accept floating-point inputs"); - - return x - ::std::floor(x); - } - - VECTORIZE_VEC(fract) - - // mod - template - GLM_FUNC_QUALIFIER genType mod - ( - genType const & x, - genType const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mod' only accept floating-point inputs"); - - return x - y * floor(x / y); - } - - VECTORIZE_VEC_SCA(mod) - VECTORIZE_VEC_VEC(mod) - - // modf - template - GLM_FUNC_QUALIFIER genType modf - ( - genType const & x, - genType & i - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'modf' only accept floating-point inputs"); - - return std::modf(x, &i); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 modf - ( - detail::tvec2 const & x, - detail::tvec2 & i - ) - { - return detail::tvec2( - modf(x.x, i.x), - modf(x.y, i.y)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 modf - ( - detail::tvec3 const & x, - detail::tvec3 & i - ) - { - return detail::tvec3( - modf(x.x, i.x), - modf(x.y, i.y), - modf(x.z, i.z)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 modf - ( - detail::tvec4 const & x, - detail::tvec4 & i - ) - { - return detail::tvec4( - modf(x.x, i.x), - modf(x.y, i.y), - modf(x.z, i.z), - modf(x.w, i.w)); - } - - //// Only valid if (INT_MIN <= x-y <= INT_MAX) - //// min(x,y) - //r = y + ((x - y) & ((x - y) >> (sizeof(int) * - //CHAR_BIT - 1))); - //// max(x,y) - //r = x - ((x - y) & ((x - y) >> (sizeof(int) * - //CHAR_BIT - 1))); - - // min - template - GLM_FUNC_QUALIFIER genType min - ( - genType const & x, - genType const & y - ) - { - GLM_STATIC_ASSERT( - detail::type::is_float || - detail::type::is_int || - detail::type::is_uint, "'min' only accept numbers"); - - return x < y ? x : y; - } - - VECTORIZE_VEC_SCA(min) - VECTORIZE_VEC_VEC(min) - - // max - template - GLM_FUNC_QUALIFIER genType max - ( - genType const & x, - genType const & y - ) - { - GLM_STATIC_ASSERT( - detail::type::is_float || - detail::type::is_int || - detail::type::is_uint, "'max' only accept numbers"); - - return x > y ? x : y; - } - - VECTORIZE_VEC_SCA(max) - VECTORIZE_VEC_VEC(max) - - // clamp - template - GLM_FUNC_QUALIFIER valType clamp - ( - valType const & x, - valType const & minVal, - valType const & maxVal - ) - { - GLM_STATIC_ASSERT( - detail::type::is_float || - detail::type::is_int || - detail::type::is_uint, "'clamp' only accept numbers"); - - return min(maxVal, max(minVal, x)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 clamp - ( - detail::tvec2 const & x, - typename detail::tvec2::value_type const & minVal, - typename detail::tvec2::value_type const & maxVal - ) - { - return detail::tvec2( - clamp(x.x, minVal, maxVal), - clamp(x.y, minVal, maxVal)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 clamp - ( - detail::tvec3 const & x, - typename detail::tvec3::value_type const & minVal, - typename detail::tvec3::value_type const & maxVal - ) - { - return detail::tvec3( - clamp(x.x, minVal, maxVal), - clamp(x.y, minVal, maxVal), - clamp(x.z, minVal, maxVal)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 clamp - ( - detail::tvec4 const & x, - typename detail::tvec4::value_type const & minVal, - typename detail::tvec4::value_type const & maxVal - ) - { - return detail::tvec4( - clamp(x.x, minVal, maxVal), - clamp(x.y, minVal, maxVal), - clamp(x.z, minVal, maxVal), - clamp(x.w, minVal, maxVal)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 clamp - ( - detail::tvec2 const & x, - detail::tvec2 const & minVal, - detail::tvec2 const & maxVal - ) - { - return detail::tvec2( - clamp(x.x, minVal.x, maxVal.x), - clamp(x.y, minVal.y, maxVal.y)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 clamp - ( - detail::tvec3 const & x, - detail::tvec3 const & minVal, - detail::tvec3 const & maxVal - ) - { - return detail::tvec3( - clamp(x.x, minVal.x, maxVal.x), - clamp(x.y, minVal.y, maxVal.y), - clamp(x.z, minVal.z, maxVal.z)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 clamp - ( - detail::tvec4 const & x, - detail::tvec4 const & minVal, - detail::tvec4 const & maxVal - ) - { - return detail::tvec4( - clamp(x.x, minVal.x, maxVal.x), - clamp(x.y, minVal.y, maxVal.y), - clamp(x.z, minVal.z, maxVal.z), - clamp(x.w, minVal.w, maxVal.w)); - } - - // mix - template - GLM_FUNC_QUALIFIER genType mix - ( - genType const & x, - genType const & y, - genType const & a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float , "'genType' is not floating-point type"); - - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 mix - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - valType const & a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float , "'genType' is not floating-point type"); - - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 mix - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - valType const & a - ) - { - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 mix - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - valType const & a - ) - { - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 mix - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - detail::tvec2 const & a - ) - { - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 mix - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - detail::tvec3 const & a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float , "'genType' is not floating-point type"); - - return x + a * (y - x); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 mix - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - detail::tvec4 const & a - ) - { - return x + a * (y - x); - } - - //template - //GLM_FUNC_QUALIFIER genTypeT mix - //( - // genTypeT const & x, - // genTypeT const & y, - // float const & a - //) - //{ - // // It could be a vector too - // //GLM_STATIC_ASSERT( - // // detail::type::is_float && - // // detail::type::is_float); - - // return x + a * (y - x); - //} - - template <> - GLM_FUNC_QUALIFIER float mix - ( - float const & x, - float const & y, - bool const & a - ) - { - return a ? y : x; - } - - template <> - GLM_FUNC_QUALIFIER double mix - ( - double const & x, - double const & y, - bool const & a - ) - { - return a ? y : x; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 mix - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - bool a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - return a ? y : x; - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 mix - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - bool a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - return a ? y : x; - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 mix - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - bool a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - return a ? y : x; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 mix - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - typename detail::tvec2::bool_type a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - detail::tvec2 result; - for - ( - typename detail::tvec2::size_type i = 0; - i < x.length(); ++i - ) - { - result[i] = a[i] ? y[i] : x[i]; - } - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 mix - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - typename detail::tvec3::bool_type a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - detail::tvec3 result; - for - ( - typename detail::tvec3::size_type i = 0; - i < x.length(); ++i - ) - { - result[i] = a[i] ? y[i] : x[i]; - } - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 mix - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - typename detail::tvec4::bool_type a - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'mix' only accept floating-point inputs"); - - detail::tvec4 result; - for - ( - typename detail::tvec4::size_type i = 0; - i < x.length(); ++i - ) - { - result[i] = a[i] ? y[i] : x[i]; - } - return result; - } - - // step - template - GLM_FUNC_QUALIFIER genType step - ( - genType const & edge, - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'step' only accept floating-point inputs"); - - return x < edge ? genType(0) : genType(1); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 step - ( - typename detail::tvec2::value_type const & edge, - detail::tvec2 const & x - ) - { - return detail::tvec2( - x.x < edge ? T(0) : T(1), - x.y < edge ? T(0) : T(1)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 step - ( - typename detail::tvec3::value_type const & edge, - detail::tvec3 const & x - ) - { - return detail::tvec3( - x.x < edge ? T(0) : T(1), - x.y < edge ? T(0) : T(1), - x.z < edge ? T(0) : T(1)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 step - ( - typename detail::tvec4::value_type const & edge, - detail::tvec4 const & x - ) - { - return detail::tvec4( - x.x < edge ? T(0) : T(1), - x.y < edge ? T(0) : T(1), - x.z < edge ? T(0) : T(1), - x.w < edge ? T(0) : T(1)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 step - ( - detail::tvec2 const & edge, - detail::tvec2 const & x - ) - { - return detail::tvec2( - x.x < edge.x ? T(0) : T(1), - x.y < edge.y ? T(0) : T(1)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 step - ( - detail::tvec3 const & edge, - detail::tvec3 const & x - ) - { - return detail::tvec3( - x.x < edge.x ? T(0) : T(1), - x.y < edge.y ? T(0) : T(1), - x.z < edge.z ? T(0) : T(1)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 step - ( - detail::tvec4 const & edge, - detail::tvec4 const & x - ) - { - return detail::tvec4( - x.x < edge.x ? T(0) : T(1), - x.y < edge.y ? T(0) : T(1), - x.z < edge.z ? T(0) : T(1), - x.w < edge.w ? T(0) : T(1)); - } - - // smoothstep - template - GLM_FUNC_QUALIFIER genType smoothstep - ( - genType const & edge0, - genType const & edge1, - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'smoothstep' only accept floating-point inputs"); - - genType tmp = clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)); - return tmp * tmp * (genType(3) - genType(2) * tmp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 smoothstep - ( - typename detail::tvec2::value_type const & edge0, - typename detail::tvec2::value_type const & edge1, - detail::tvec2 const & x - ) - { - return detail::tvec2( - smoothstep(edge0, edge1, x.x), - smoothstep(edge0, edge1, x.y)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 smoothstep - ( - typename detail::tvec3::value_type const & edge0, - typename detail::tvec3::value_type const & edge1, - detail::tvec3 const & x - ) - { - return detail::tvec3( - smoothstep(edge0, edge1, x.x), - smoothstep(edge0, edge1, x.y), - smoothstep(edge0, edge1, x.z)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 smoothstep - ( - typename detail::tvec4::value_type const & edge0, - typename detail::tvec4::value_type const & edge1, - detail::tvec4 const & x - ) - { - return detail::tvec4( - smoothstep(edge0, edge1, x.x), - smoothstep(edge0, edge1, x.y), - smoothstep(edge0, edge1, x.z), - smoothstep(edge0, edge1, x.w)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 smoothstep - ( - detail::tvec2 const & edge0, - detail::tvec2 const & edge1, - detail::tvec2 const & x - ) - { - return detail::tvec2( - smoothstep(edge0.x, edge1.x, x.x), - smoothstep(edge0.y, edge1.y, x.y)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 smoothstep - ( - detail::tvec3 const & edge0, - detail::tvec3 const & edge1, - detail::tvec3 const & x - ) - { - return detail::tvec3( - smoothstep(edge0.x, edge1.x, x.x), - smoothstep(edge0.y, edge1.y, x.y), - smoothstep(edge0.z, edge1.z, x.z)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 smoothstep - ( - detail::tvec4 const & edge0, - detail::tvec4 const & edge1, - detail::tvec4 const & x - ) - { - return detail::tvec4( - smoothstep(edge0.x, edge1.x, x.x), - smoothstep(edge0.y, edge1.y, x.y), - smoothstep(edge0.z, edge1.z, x.z), - smoothstep(edge0.w, edge1.w, x.w)); - } - - // TODO: Not working on MinGW... - template - GLM_FUNC_QUALIFIER bool isnan(genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'isnan' only accept floating-point inputs"); - -# if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_INTEL)) - return _isnan(x) != 0; -# elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) -# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) - return _isnan(x) != 0; -# else - return std::isnan(x); -# endif -# elif(GLM_COMPILER & GLM_COMPILER_CUDA) - return isnan(x) != 0; -# else - return std::isnan(x); -# endif - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec2::bool_type isnan - ( - detail::tvec2 const & x - ) - { - return typename detail::tvec2::bool_type( - isnan(x.x), - isnan(x.y)); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec3::bool_type isnan - ( - detail::tvec3 const & x - ) - { - return typename detail::tvec3::bool_type( - isnan(x.x), - isnan(x.y), - isnan(x.z)); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec4::bool_type isnan - ( - detail::tvec4 const & x - ) - { - return typename detail::tvec4::bool_type( - isnan(x.x), - isnan(x.y), - isnan(x.z), - isnan(x.w)); - } - - template - GLM_FUNC_QUALIFIER bool isinf( - genType const & x) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'isinf' only accept floating-point inputs"); - -# if(GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC)) - return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; -# elif(GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) -# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) - return _isinf(x) != 0; -# else - return std::isinf(x); -# endif -# elif(GLM_COMPILER & GLM_COMPILER_CUDA) - // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab - return isinf(double(x)) != 0; -# else - return std::isinf(x); -# endif - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec2::bool_type isinf - ( - detail::tvec2 const & x - ) - { - return typename detail::tvec2::bool_type( - isinf(x.x), - isinf(x.y)); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec3::bool_type isinf - ( - detail::tvec3 const & x - ) - { - return typename detail::tvec3::bool_type( - isinf(x.x), - isinf(x.y), - isinf(x.z)); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec4::bool_type isinf - ( - detail::tvec4 const & x - ) - { - return typename detail::tvec4::bool_type( - isinf(x.x), - isinf(x.y), - isinf(x.z), - isinf(x.w)); - } - - GLM_FUNC_QUALIFIER int floatBitsToInt(float const & value) - { - union - { - float f; - int i; - } fi; - - fi.f = value; - return fi.i; - } - - GLM_FUNC_QUALIFIER detail::tvec2 floatBitsToInt - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - floatBitsToInt(value.x), - floatBitsToInt(value.y)); - } - - GLM_FUNC_QUALIFIER detail::tvec3 floatBitsToInt - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - floatBitsToInt(value.x), - floatBitsToInt(value.y), - floatBitsToInt(value.z)); - } - - GLM_FUNC_QUALIFIER detail::tvec4 floatBitsToInt - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - floatBitsToInt(value.x), - floatBitsToInt(value.y), - floatBitsToInt(value.z), - floatBitsToInt(value.w)); - } - - GLM_FUNC_QUALIFIER uint floatBitsToUint(float const & value) - { - union - { - float f; - uint u; - } fu; - - fu.f = value; - return fu.u; - } - - GLM_FUNC_QUALIFIER detail::tvec2 floatBitsToUint - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - floatBitsToUint(value.x), - floatBitsToUint(value.y)); - } - - GLM_FUNC_QUALIFIER detail::tvec3 floatBitsToUint - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - floatBitsToUint(value.x), - floatBitsToUint(value.y), - floatBitsToUint(value.z)); - } - - GLM_FUNC_QUALIFIER detail::tvec4 floatBitsToUint - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - floatBitsToUint(value.x), - floatBitsToUint(value.y), - floatBitsToUint(value.z), - floatBitsToUint(value.w)); - } - - GLM_FUNC_QUALIFIER float intBitsToFloat(int const & value) - { - union - { - float f; - int i; - } fi; - - fi.i = value; - return fi.f; - } - - GLM_FUNC_QUALIFIER detail::tvec2 intBitsToFloat - - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - intBitsToFloat(value.x), - intBitsToFloat(value.y)); - } - - GLM_FUNC_QUALIFIER detail::tvec3 intBitsToFloat - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - intBitsToFloat(value.x), - intBitsToFloat(value.y), - intBitsToFloat(value.z)); - } - - GLM_FUNC_QUALIFIER detail::tvec4 intBitsToFloat - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - intBitsToFloat(value.x), - intBitsToFloat(value.y), - intBitsToFloat(value.z), - intBitsToFloat(value.w)); - } - - GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const & value) - { - union - { - float f; - uint u; - } fu; - - fu.u = value; - return fu.f; - } - - GLM_FUNC_QUALIFIER detail::tvec2 uintBitsToFloat - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - uintBitsToFloat(value.x), - uintBitsToFloat(value.y)); - } - - GLM_FUNC_QUALIFIER detail::tvec3 uintBitsToFloat - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - uintBitsToFloat(value.x), - uintBitsToFloat(value.y), - uintBitsToFloat(value.z)); - } - - GLM_FUNC_QUALIFIER detail::tvec4 uintBitsToFloat - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - uintBitsToFloat(value.x), - uintBitsToFloat(value.y), - uintBitsToFloat(value.z), - uintBitsToFloat(value.w)); - } - - template - GLM_FUNC_QUALIFIER genType fma - ( - genType const & a, - genType const & b, - genType const & c - ) - { - return a * b + c; - } - - template - GLM_FUNC_QUALIFIER genType frexp - ( - genType const & x, - int & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 frexp - ( - detail::tvec2 const & x, - detail::tvec2 & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 frexp - ( - detail::tvec3 const & x, - detail::tvec3 & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 frexp - ( - detail::tvec4 const & x, - detail::tvec4 & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER genType ldexp - ( - genType const & x, - int const & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 ldexp - ( - detail::tvec2 const & x, - detail::tvec2 const & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 ldexp - ( - detail::tvec3 const & x, - detail::tvec3 const & exp - ) - { - return std::frexp(x, exp); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 ldexp - ( - detail::tvec4 const & x, - detail::tvec4 const & exp - ) - { - return std::frexp(x, exp); - } - -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_exponential.hpp b/include/gal/opengl/glm/core/func_exponential.hpp deleted file mode 100644 index dc76fcbb93..0000000000 --- a/include/gal/opengl/glm/core/func_exponential.hpp +++ /dev/null @@ -1,123 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_exponential.hpp -/// @date 2008-08-08 / 2011-06-14 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions -/// -/// @defgroup core_func_exponential Exponential functions -/// @ingroup core -/// -/// These all operate component-wise. The description is per component. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_func_exponential -#define glm_core_func_exponential GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_exponential - /// @{ - - /// Returns 'base' raised to the power 'exponent'. - /// - /// @param base Floating point value. pow function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. - /// @param exponent Floating point value representing the 'exponent'. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL pow man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType pow(genType const & base, genType const & exponent); - - /// Returns the natural exponentiation of x, i.e., e^x. - /// - /// @param x exp function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL exp man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType exp(genType const & x); - - /// Returns the natural logarithm of x, i.e., - /// returns the value y which satisfies the equation x = e^y. - /// Results are undefined if x <= 0. - /// - /// @param x log function is defined for input values of x defined in the range (0, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL log man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType log(genType const & x); - - /// Returns 2 raised to the x power. - /// - /// @param x exp2 function is defined for input values of x defined in the range (inf-, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL exp2 man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType exp2(genType const & x); - - /// Returns the base 2 log of x, i.e., returns the value y, - /// which satisfies the equation x = 2 ^ y. - /// - /// @param x log2 function is defined for input values of x defined in the range (0, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL log2 man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType log2(genType const & x); - - /// Returns the positive square root of x. - /// - /// @param x sqrt function is defined for input values of x defined in the range [0, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL sqrt man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType sqrt(genType const & x); - - /// Returns the reciprocal of the positive square root of x. - /// - /// @param x inversesqrt function is defined for input values of x defined in the range [0, inf+) in the limit of the type precision. - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL inversesqrt man page - /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions - template - GLM_FUNC_DECL genType inversesqrt(genType const & x); - - /// @} -}//namespace glm - -#include "func_exponential.inl" - -#endif//glm_core_func_exponential diff --git a/include/gal/opengl/glm/core/func_exponential.inl b/include/gal/opengl/glm/core/func_exponential.inl deleted file mode 100644 index 1b08786df6..0000000000 --- a/include/gal/opengl/glm/core/func_exponential.inl +++ /dev/null @@ -1,156 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_exponential.inl -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - // pow - template - GLM_FUNC_QUALIFIER genType pow - ( - genType const & x, - genType const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'pow' only accept floating-point input"); - - return genType(::std::pow(x, y)); - } - - VECTORIZE_VEC_VEC(pow) - - // exp - template - GLM_FUNC_QUALIFIER genType exp - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'exp' only accept floating-point input"); - - return genType(::std::exp(x)); - } - - VECTORIZE_VEC(exp) - - // log - template - GLM_FUNC_QUALIFIER genType log - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'log' only accept floating-point input"); - - return genType(::std::log(x)); - } - - VECTORIZE_VEC(log) - - //exp2, ln2 = 0.69314718055994530941723212145818f - template - GLM_FUNC_QUALIFIER genType exp2 - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'exp2' only accept floating-point input"); - - return genType(::std::exp(genType(0.69314718055994530941723212145818) * x)); - } - - VECTORIZE_VEC(exp2) - -namespace _detail -{ - template - struct _compute_log2 - { - template - T operator() (T const & Value) const; -/* - { - GLM_STATIC_ASSERT(0, "'log2' parameter has an invalid template parameter type. GLM core features only supports floating-point types, include for integer types support. Others types are not supported."); - return Value; - } -*/ - }; - - template <> - struct _compute_log2 - { - template - T operator() (T const & Value) const - { - return T(::std::log(Value)) / T(0.69314718055994530941723212145818); - } - }; - -}//namespace _detail - - // log2, ln2 = 0.69314718055994530941723212145818f - template - GLM_FUNC_QUALIFIER genType log2 - ( - genType const & x - ) - { - assert(x > genType(0)); // log2 is only defined on the range (0, inf] - return _detail::_compute_log2::ID>()(x); - } - - VECTORIZE_VEC(log2) - - // sqrt - template - GLM_FUNC_QUALIFIER genType sqrt - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'sqrt' only accept floating-point input"); - - return genType(::std::sqrt(x)); - } - - VECTORIZE_VEC(sqrt) - - template - GLM_FUNC_QUALIFIER genType inversesqrt - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'inversesqrt' only accept floating-point input"); - assert(x > genType(0)); - - return genType(1) / ::std::sqrt(x); - } - - VECTORIZE_VEC(inversesqrt) - -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_geometric.hpp b/include/gal/opengl/glm/core/func_geometric.hpp deleted file mode 100644 index c221084f14..0000000000 --- a/include/gal/opengl/glm/core/func_geometric.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_geometric.hpp -/// @date 2008-08-03 / 2011-06-14 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions -/// -/// @defgroup core_func_geometric Geometric functions -/// @ingroup core -/// -/// These operate on vectors as vectors, not component-wise. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_func_geometric -#define glm_core_func_geometric GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_geometric - /// @{ - - /// Returns the length of x, i.e., sqrt(x * x). - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL length man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL typename genType::value_type length( - genType const & x); - - /// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL distance man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL typename genType::value_type distance( - genType const & p0, - genType const & p1); - - /// Returns the dot product of x and y, i.e., result = x * y. - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL dot man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL typename genType::value_type dot( - genType const & x, - genType const & y); - - /// Returns the cross product of x and y. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL cross man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL detail::tvec3 cross( - detail::tvec3 const & x, - detail::tvec3 const & y); - - /// Returns a vector in the same direction as x but with length of 1. - /// - /// @see GLSL normalize man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL genType normalize( - genType const & x); - - /// If dot(Nref, I) < 0.0, return N, otherwise, return -N. - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL faceforward man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL genType faceforward( - genType const & N, - genType const & I, - genType const & Nref); - - /// For the incident vector I and surface orientation N, - /// returns the reflection direction : result = I - 2.0 * dot(N, I) * N. - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL reflect man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL genType reflect( - genType const & I, - genType const & N); - - /// For the incident vector I and surface normal N, - /// and the ratio of indices of refraction eta, - /// return the refraction vector. - /// - /// @tparam genType Floating-point vector types. - /// - /// @see GLSL refract man page - /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions - template - GLM_FUNC_DECL genType refract( - genType const & I, - genType const & N, - typename genType::value_type const & eta); - - /// @} -}//namespace glm - -#include "func_geometric.inl" - -#endif//glm_core_func_geometric diff --git a/include/gal/opengl/glm/core/func_geometric.inl b/include/gal/opengl/glm/core/func_geometric.inl deleted file mode 100644 index 259a0ffdf9..0000000000 --- a/include/gal/opengl/glm/core/func_geometric.inl +++ /dev/null @@ -1,321 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_geometric.inl -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - // length - template - GLM_FUNC_QUALIFIER genType length - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'length' only accept floating-point inputs"); - - genType sqr = x * x; - return sqrt(sqr); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec2::value_type length - ( - detail::tvec2 const & v - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'length' only accept floating-point inputs"); - - typename detail::tvec2::value_type sqr = v.x * v.x + v.y * v.y; - return sqrt(sqr); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec3::value_type length - ( - detail::tvec3 const & v - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'length' only accept floating-point inputs"); - - typename detail::tvec3::value_type sqr = v.x * v.x + v.y * v.y + v.z * v.z; - return sqrt(sqr); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec4::value_type length - ( - detail::tvec4 const & v - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'length' only accept floating-point inputs"); - - typename detail::tvec4::value_type sqr = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; - return sqrt(sqr); - } - - // distance - template - GLM_FUNC_QUALIFIER genType distance - ( - genType const & p0, - genType const & p1 - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'distance' only accept floating-point inputs"); - - return length(p1 - p0); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec2::value_type distance - ( - detail::tvec2 const & p0, - detail::tvec2 const & p1 - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'distance' only accept floating-point inputs"); - - return length(p1 - p0); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec3::value_type distance - ( - detail::tvec3 const & p0, - detail::tvec3 const & p1 - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'distance' only accept floating-point inputs"); - - return length(p1 - p0); - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec4::value_type distance - ( - detail::tvec4 const & p0, - detail::tvec4 const & p1 - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'distance' only accept floating-point inputs"); - - return length(p1 - p0); - } - - // dot - template - GLM_FUNC_QUALIFIER genType dot - ( - genType const & x, - genType const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'dot' only accept floating-point inputs"); - - return x * y; - } - - template - GLM_FUNC_QUALIFIER typename detail::tvec2::value_type dot - ( - detail::tvec2 const & x, - detail::tvec2 const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'dot' only accept floating-point inputs"); - - return x.x * y.x + x.y * y.y; - } - - template - GLM_FUNC_QUALIFIER T dot - ( - detail::tvec3 const & x, - detail::tvec3 const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'dot' only accept floating-point inputs"); - - return x.x * y.x + x.y * y.y + x.z * y.z; - } -/* // SSE3 - GLM_FUNC_QUALIFIER float dot(const tvec4& x, const tvec4& y) - { - float Result; - __asm - { - mov esi, x - mov edi, y - movaps xmm0, [esi] - mulps xmm0, [edi] - haddps( _xmm0, _xmm0 ) - haddps( _xmm0, _xmm0 ) - movss Result, xmm0 - } - return Result; - } -*/ - template - GLM_FUNC_QUALIFIER T dot - ( - detail::tvec4 const & x, - detail::tvec4 const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'dot' only accept floating-point inputs"); - - return x.x * y.x + x.y * y.y + x.z * y.z + x.w * y.w; - } - - // cross - template - GLM_FUNC_QUALIFIER detail::tvec3 cross - ( - detail::tvec3 const & x, - detail::tvec3 const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'cross' only accept floating-point inputs"); - - return detail::tvec3( - x.y * y.z - y.y * x.z, - x.z * y.x - y.z * x.x, - x.x * y.y - y.x * x.y); - } - - // normalize - template - GLM_FUNC_QUALIFIER genType normalize - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'normalize' only accept floating-point inputs"); - - return x < genType(0) ? genType(-1) : genType(1); - } - - // According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefine and generate an error - template - GLM_FUNC_QUALIFIER detail::tvec2 normalize - ( - detail::tvec2 const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'normalize' only accept floating-point inputs"); - - typename detail::tvec2::value_type sqr = x.x * x.x + x.y * x.y; - return x * inversesqrt(sqr); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 normalize - ( - detail::tvec3 const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'normalize' only accept floating-point inputs"); - - typename detail::tvec3::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z; - return x * inversesqrt(sqr); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 normalize - ( - detail::tvec4 const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'normalize' only accept floating-point inputs"); - - typename detail::tvec4::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w; - return x * inversesqrt(sqr); - } - - // faceforward - template - GLM_FUNC_QUALIFIER genType faceforward - ( - genType const & N, - genType const & I, - genType const & Nref - ) - { - return dot(Nref, I) < 0 ? N : -N; - } - - // reflect - template - GLM_FUNC_QUALIFIER genType reflect - ( - genType const & I, - genType const & N - ) - { - return I - N * dot(N, I) * genType(2); - } - - // refract - template - GLM_FUNC_QUALIFIER genType refract - ( - genType const & I, - genType const & N, - genType const & eta - ) - { - //It could be a vector - //GLM_STATIC_ASSERT(detail::type::is_float); - - genType dotValue = dot(N, I); - genType k = genType(1) - eta * eta * (genType(1) - dotValue * dotValue); - if(k < genType(0)) - return genType(0); - else - return eta * I - (eta * dotValue + sqrt(k)) * N; - } - - template - GLM_FUNC_QUALIFIER genType refract - ( - genType const & I, - genType const & N, - typename genType::value_type const & eta - ) - { - //It could be a vector - //GLM_STATIC_ASSERT(detail::type::is_float); - - typename genType::value_type dotValue = dot(N, I); - typename genType::value_type k = typename genType::value_type(1) - eta * eta * (typename genType::value_type(1) - dotValue * dotValue); - if(k < typename genType::value_type(0)) - return genType(0); - else - return eta * I - (eta * dotValue + sqrt(k)) * N; - } - -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_integer.hpp b/include/gal/opengl/glm/core/func_integer.hpp deleted file mode 100644 index df9a401591..0000000000 --- a/include/gal/opengl/glm/core/func_integer.hpp +++ /dev/null @@ -1,201 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_integer.hpp -/// @date 2010-03-17 / 2011-06-18 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.8 Integer Functions -/// -/// @defgroup core_func_integer Integer functions -/// @ingroup core -/// -/// These all operate component-wise. The description is per component. -/// The notation [a, b] means the set of bits from bit-number a through bit-number -/// b, inclusive. The lowest-order bit is bit 0. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_func_integer -#define glm_core_func_integer GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_integer - /// @{ - - /// Adds 32-bit unsigned integer x and y, returning the sum - /// modulo pow(2, 32). The value carry is set to 0 if the sum was - /// less than pow(2, 32), or to 1 otherwise. - /// - /// @tparam genUType Unsigned integer scalar or vector types. - /// - /// @see GLSL uaddCarry man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL genUType uaddCarry( - genUType const & x, - genUType const & y, - genUType & carry); - - /// Subtracts the 32-bit unsigned integer y from x, returning - /// the difference if non-negative, or pow(2, 32) plus the difference - /// otherwise. The value borrow is set to 0 if x >= y, or to 1 otherwise. - /// - /// @tparam genUType Unsigned integer scalar or vector types. - /// - /// @see GLSL usubBorrow man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL genUType usubBorrow( - genUType const & x, - genUType const & y, - genUType & borrow); - - /// Multiplies 32-bit integers x and y, producing a 64-bit - /// result. The 32 least-significant bits are returned in lsb. - /// The 32 most-significant bits are returned in msb. - /// - /// @tparam genUType Unsigned integer scalar or vector types. - /// - /// @see GLSL umulExtended man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL void umulExtended( - genUType const & x, - genUType const & y, - genUType & msb, - genUType & lsb); - - /// Multiplies 32-bit integers x and y, producing a 64-bit - /// result. The 32 least-significant bits are returned in lsb. - /// The 32 most-significant bits are returned in msb. - /// - /// @tparam genIType Signed integer scalar or vector types. - /// - /// @see GLSL imulExtended man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL void imulExtended( - genIType const & x, - genIType const & y, - genIType & msb, - genIType & lsb); - - /// Extracts bits [offset, offset + bits - 1] from value, - /// returning them in the least significant bits of the result. - /// For unsigned data types, the most significant bits of the - /// result will be set to zero. For signed data types, the - /// most significant bits will be set to the value of bit offset + base - 1. - /// - /// If bits is zero, the result will be zero. The result will be - /// undefined if offset or bits is negative, or if the sum of - /// offset and bits is greater than the number of bits used - /// to store the operand. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL bitfieldExtract man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL genIUType bitfieldExtract( - genIUType const & Value, - int const & Offset, - int const & Bits); - - /// Returns the insertion the bits least-significant bits of insert into base. - /// - /// The result will have bits [offset, offset + bits - 1] taken - /// from bits [0, bits - 1] of insert, and all other bits taken - /// directly from the corresponding bits of base. If bits is - /// zero, the result will simply be base. The result will be - /// undefined if offset or bits is negative, or if the sum of - /// offset and bits is greater than the number of bits used to - /// store the operand. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL bitfieldInsert man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL genIUType bitfieldInsert( - genIUType const & Base, - genIUType const & Insert, - int const & Offset, - int const & Bits); - - /// Returns the reversal of the bits of value. - /// The bit numbered n of the result will be taken from bit (bits - 1) - n of value, - /// where bits is the total number of bits used to represent value. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL bitfieldReverse man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - template - GLM_FUNC_DECL genIUType bitfieldReverse(genIUType const & Value); - - /// Returns the number of bits set to 1 in the binary representation of value. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL bitCount man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - /// - /// @todo Clarify the declaration to specify that scalars are suported. - template class genIUType> - GLM_FUNC_DECL typename genIUType::signed_type bitCount(genIUType const & Value); - - /// Returns the bit number of the least significant bit set to - /// 1 in the binary representation of value. - /// If value is zero, -1 will be returned. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL findLSB man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - /// - /// @todo Clarify the declaration to specify that scalars are suported. - template class genIUType> - GLM_FUNC_DECL typename genIUType::signed_type findLSB(genIUType const & Value); - - /// Returns the bit number of the most significant bit in the binary representation of value. - /// For positive integers, the result will be the bit number of the most significant bit set to 1. - /// For negative integers, the result will be the bit number of the most significant - /// bit set to 0. For a value of zero or negative one, -1 will be returned. - /// - /// @tparam genIUType Signed or unsigned integer scalar or vector types. - /// - /// @see GLSL findMSB man page - /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions - /// - /// @todo Clarify the declaration to specify that scalars are suported. - template class genIUType> - GLM_FUNC_DECL typename genIUType::signed_type findMSB(genIUType const & Value); - - /// @} -}//namespace glm - -#include "func_integer.inl" - -#endif//glm_core_func_integer - diff --git a/include/gal/opengl/glm/core/func_integer.inl b/include/gal/opengl/glm/core/func_integer.inl deleted file mode 100644 index ad8b1fe83c..0000000000 --- a/include/gal/opengl/glm/core/func_integer.inl +++ /dev/null @@ -1,648 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_integer.inl -/// @date 2010-03-17 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -#if(GLM_ARCH != GLM_ARCH_PURE) -#if(GLM_COMPILER & GLM_COMPILER_VC) -# include -# pragma intrinsic(_BitScanReverse) -#endif//(GLM_COMPILER & GLM_COMPILER_VC) -#endif//(GLM_ARCH != GLM_ARCH_PURE) - -namespace glm -{ - // uaddCarry - template - GLM_FUNC_QUALIFIER genUType uaddCarry - ( - genUType const & x, - genUType const & y, - genUType & Carry - ) - { - detail::highp_uint_t Value64 = detail::highp_uint_t(x) + detail::highp_uint_t(y); - genUType Result = genUType(Value64 % (detail::highp_uint_t(1) << detail::highp_uint_t(32))); - Carry = (Value64 % (detail::highp_uint_t(1) << detail::highp_uint_t(32))) > 1 ? 1 : 0; - return Result; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 uaddCarry - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - detail::tvec2 & Carry - ) - { - return detail::tvec2( - uaddCarry(x[0], y[0], Carry[0]), - uaddCarry(x[1], y[1], Carry[1])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 uaddCarry - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - detail::tvec3 & Carry - ) - { - return detail::tvec3( - uaddCarry(x[0], y[0], Carry[0]), - uaddCarry(x[1], y[1], Carry[1]), - uaddCarry(x[2], y[2], Carry[2])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 uaddCarry - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - detail::tvec4 & Carry - ) - { - return detail::tvec4( - uaddCarry(x[0], y[0], Carry[0]), - uaddCarry(x[1], y[1], Carry[1]), - uaddCarry(x[2], y[2], Carry[2]), - uaddCarry(x[3], y[3], Carry[3])); - } - - // usubBorrow - template - GLM_FUNC_QUALIFIER genUType usubBorrow - ( - genUType const & x, - genUType const & y, - genUType & Borrow - ) - { - Borrow = x >= y ? 0 : 1; - if(x > y) - return genUType(detail::highp_int_t(x) - detail::highp_int_t(y)); - else - return genUType((detail::highp_int_t(1) << detail::highp_int_t(32)) + detail::highp_int_t(x) - detail::highp_int_t(y)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 usubBorrow - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - detail::tvec2 & Borrow - ) - { - return detail::tvec2( - usubBorrow(x[0], y[0], Borrow[0]), - usubBorrow(x[1], y[1], Borrow[1])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 usubBorrow - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - detail::tvec3 & Borrow - ) - { - return detail::tvec3( - usubBorrow(x[0], y[0], Borrow[0]), - usubBorrow(x[1], y[1], Borrow[1]), - usubBorrow(x[2], y[2], Borrow[2])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 usubBorrow - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - detail::tvec4 & Borrow - ) - { - return detail::tvec4( - usubBorrow(x[0], y[0], Borrow[0]), - usubBorrow(x[1], y[1], Borrow[1]), - usubBorrow(x[2], y[2], Borrow[2]), - usubBorrow(x[3], y[3], Borrow[3])); - } - - // umulExtended - template - GLM_FUNC_QUALIFIER void umulExtended - ( - genUType const & x, - genUType const & y, - genUType & msb, - genUType & lsb - ) - { - detail::highp_uint_t ValueX64 = x; - detail::highp_uint_t ValueY64 = y; - detail::highp_uint_t Value64 = ValueX64 * ValueY64; - msb = *(genUType*)&genUType(Value64 & ((detail::highp_uint_t(1) << detail::highp_uint_t(32)) - detail::highp_uint_t(1))); - lsb = *(genUType*)&genUType(Value64 >> detail::highp_uint_t(32)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 umulExtended - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - detail::tvec2 & msb, - detail::tvec2 & lsb - ) - { - return detail::tvec2( - umulExtended(x[0], y[0], msb, lsb), - umulExtended(x[1], y[1], msb, lsb)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 umulExtended - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - detail::tvec3 & msb, - detail::tvec3 & lsb - ) - { - return detail::tvec3( - umulExtended(x[0], y[0], msb, lsb), - umulExtended(x[1], y[1], msb, lsb), - umulExtended(x[2], y[2], msb, lsb)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 umulExtended - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - detail::tvec4 & msb, - detail::tvec4 & lsb - ) - { - return detail::tvec4( - umulExtended(x[0], y[0], msb, lsb), - umulExtended(x[1], y[1], msb, lsb), - umulExtended(x[2], y[2], msb, lsb), - umulExtended(x[3], y[3], msb, lsb)); - } - - // imulExtended - template - GLM_FUNC_QUALIFIER void imulExtended - ( - genIType const & x, - genIType const & y, - genIType & msb, - genIType & lsb - ) - { - detail::highp_int_t ValueX64 = x; - detail::highp_int_t ValueY64 = y; - detail::highp_int_t Value64 = ValueX64 * ValueY64; - msb = *(genIType*)&genIType(Value64 & ((detail::highp_uint_t(1) << detail::highp_uint_t(32)) - detail::highp_uint_t(1))); - lsb = *(genIType*)&genIType(Value64 >> detail::highp_uint_t(32)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 imulExtended - ( - detail::tvec2 const & x, - detail::tvec2 const & y, - detail::tvec2 & msb, - detail::tvec2 & lsb - ) - { - return detail::tvec2( - imulExtended(x[0], y[0], msb, lsb), - imulExtended(x[1], y[1], msb, lsb)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 imulExtended - ( - detail::tvec3 const & x, - detail::tvec3 const & y, - detail::tvec3 & msb, - detail::tvec3 & lsb - ) - { - return detail::tvec3( - imulExtended(x[0], y[0], msb, lsb), - imulExtended(x[1], y[1], msb, lsb), - imulExtended(x[2], y[2], msb, lsb)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 imulExtended - ( - detail::tvec4 const & x, - detail::tvec4 const & y, - detail::tvec4 & msb, - detail::tvec4 & lsb - ) - { - return detail::tvec4( - imulExtended(x[0], y[0], msb, lsb), - imulExtended(x[1], y[1], msb, lsb), - imulExtended(x[2], y[2], msb, lsb), - imulExtended(x[3], y[3], msb, lsb)); - } - - // bitfieldExtract - template - GLM_FUNC_QUALIFIER genIUType bitfieldExtract - ( - genIUType const & Value, - int const & Offset, - int const & Bits - ) - { - int GenSize = int(sizeof(genIUType)) << int(3); - - assert(Offset + Bits <= GenSize); - - genIUType ShiftLeft = Bits ? Value << (GenSize - (Bits + Offset)) : genIUType(0); - genIUType ShiftBack = ShiftLeft >> genIUType(GenSize - Bits); - - return ShiftBack; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 bitfieldExtract - ( - detail::tvec2 const & Value, - int const & Offset, - int const & Bits - ) - { - return detail::tvec2( - bitfieldExtract(Value[0], Offset, Bits), - bitfieldExtract(Value[1], Offset, Bits)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 bitfieldExtract - ( - detail::tvec3 const & Value, - int const & Offset, - int const & Bits - ) - { - return detail::tvec3( - bitfieldExtract(Value[0], Offset, Bits), - bitfieldExtract(Value[1], Offset, Bits), - bitfieldExtract(Value[2], Offset, Bits)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 bitfieldExtract - ( - detail::tvec4 const & Value, - int const & Offset, - int const & Bits - ) - { - return detail::tvec4( - bitfieldExtract(Value[0], Offset, Bits), - bitfieldExtract(Value[1], Offset, Bits), - bitfieldExtract(Value[2], Offset, Bits), - bitfieldExtract(Value[3], Offset, Bits)); - } - - // bitfieldInsert - template - GLM_FUNC_QUALIFIER genIUType bitfieldInsert - ( - genIUType const & Base, - genIUType const & Insert, - int const & Offset, - int const & Bits - ) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldInsert' only accept integer values"); - assert(Offset + Bits <= sizeof(genIUType)); - - if(Bits == 0) - return Base; - - genIUType Mask = 0; - for(int Bit = Offset; Bit < Offset + Bits; ++Bit) - Mask |= (1 << Bit); - - return (Base & ~Mask) | (Insert & Mask); - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 bitfieldInsert - ( - detail::tvec2 const & Base, - detail::tvec2 const & Insert, - int const & Offset, - int const & Bits - ) - { - return detail::tvec2( - bitfieldInsert(Base[0], Insert[0], Offset, Bits), - bitfieldInsert(Base[1], Insert[1], Offset, Bits)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 bitfieldInsert - ( - detail::tvec3 const & Base, - detail::tvec3 const & Insert, - int const & Offset, - int const & Bits - ) - { - return detail::tvec3( - bitfieldInsert(Base[0], Insert[0], Offset, Bits), - bitfieldInsert(Base[1], Insert[1], Offset, Bits), - bitfieldInsert(Base[2], Insert[2], Offset, Bits)); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 bitfieldInsert - ( - detail::tvec4 const & Base, - detail::tvec4 const & Insert, - int const & Offset, - int const & Bits - ) - { - return detail::tvec4( - bitfieldInsert(Base[0], Insert[0], Offset, Bits), - bitfieldInsert(Base[1], Insert[1], Offset, Bits), - bitfieldInsert(Base[2], Insert[2], Offset, Bits), - bitfieldInsert(Base[3], Insert[3], Offset, Bits)); - } - - // bitfieldReverse - template - GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType const & Value) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); - - genIUType Out = 0; - std::size_t BitSize = sizeof(genIUType) * 8; - for(std::size_t i = 0; i < BitSize; ++i) - if(Value & (genIUType(1) << i)) - Out |= genIUType(1) << (BitSize - 1 - i); - return Out; - } - - VECTORIZE_VEC(bitfieldReverse) - - // bitCount - template - GLM_FUNC_QUALIFIER int bitCount(genIUType const & Value) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); - - int Count = 0; - for(std::size_t i = 0; i < sizeof(genIUType) * std::size_t(8); ++i) - { - if(Value & (1 << i)) - ++Count; - } - return Count; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 bitCount - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - bitCount(value[0]), - bitCount(value[1])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 bitCount - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - bitCount(value[0]), - bitCount(value[1]), - bitCount(value[2])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 bitCount - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - bitCount(value[0]), - bitCount(value[1]), - bitCount(value[2]), - bitCount(value[3])); - } - - // findLSB - template - GLM_FUNC_QUALIFIER int findLSB - ( - genIUType const & Value - ) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); - if(Value == 0) - return -1; - - genIUType Bit; - for(Bit = genIUType(0); !(Value & (1 << Bit)); ++Bit){} - return Bit; - } - - template - GLM_FUNC_QUALIFIER detail::tvec2 findLSB - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - findLSB(value[0]), - findLSB(value[1])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 findLSB - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - findLSB(value[0]), - findLSB(value[1]), - findLSB(value[2])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 findLSB - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - findLSB(value[0]), - findLSB(value[1]), - findLSB(value[2]), - findLSB(value[3])); - } - - // findMSB -#if((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_VC)) - - template - GLM_FUNC_QUALIFIER int findMSB - ( - genIUType const & Value - ) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); - if(Value == 0) - return -1; - - unsigned long Result(0); - _BitScanReverse(&Result, Value); - return int(Result); - } -/* -// __builtin_clz seems to be buggy as it crasks for some values, from 0x00200000 to 80000000 -#elif((GLM_ARCH != GLM_ARCH_PURE) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC40)) - - template - GLM_FUNC_QUALIFIER int findMSB - ( - genIUType const & Value - ) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); - if(Value == 0) - return -1; - - // clz returns the number or trailing 0-bits; see - // http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Other-Builtins.html - // - // NoteBecause __builtin_clz only works for unsigned ints, this - // implementation will not work for 64-bit integers. - // - return 31 - __builtin_clzl(Value); - } -*/ -#else - -/* SSE implementation idea - - __m128i const Zero = _mm_set_epi32( 0, 0, 0, 0); - __m128i const One = _mm_set_epi32( 1, 1, 1, 1); - __m128i Bit = _mm_set_epi32(-1, -1, -1, -1); - __m128i Tmp = _mm_set_epi32(Value, Value, Value, Value); - __m128i Mmi = Zero; - for(int i = 0; i < 32; ++i) - { - __m128i Shilt = _mm_and_si128(_mm_cmpgt_epi32(Tmp, One), One); - Tmp = _mm_srai_epi32(Tmp, One); - Bit = _mm_add_epi32(Bit, _mm_and_si128(Shilt, i)); - Mmi = _mm_and_si128(Mmi, One); - } - return Bit; - -*/ - - template - GLM_FUNC_QUALIFIER int findMSB - ( - genIUType const & Value - ) - { - GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); - - if(Value == genIUType(0) || Value == genIUType(-1)) - return -1; - else if(Value > 0) - { - genIUType Bit = genIUType(-1); - for(genIUType tmp = Value; tmp > 0; tmp >>= 1, ++Bit){} - return Bit; - } - else //if(Value < 0) - { - int const BitCount(sizeof(genIUType) * 8); - int MostSignificantBit(-1); - for(int BitIndex(0); BitIndex < BitCount; ++BitIndex) - MostSignificantBit = (Value & (1 << BitIndex)) ? MostSignificantBit : BitIndex; - assert(MostSignificantBit >= 0); - return MostSignificantBit; - } - } -#endif//(GLM_COMPILER) - - template - GLM_FUNC_QUALIFIER detail::tvec2 findMSB - ( - detail::tvec2 const & value - ) - { - return detail::tvec2( - findMSB(value[0]), - findMSB(value[1])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec3 findMSB - ( - detail::tvec3 const & value - ) - { - return detail::tvec3( - findMSB(value[0]), - findMSB(value[1]), - findMSB(value[2])); - } - - template - GLM_FUNC_QUALIFIER detail::tvec4 findMSB - ( - detail::tvec4 const & value - ) - { - return detail::tvec4( - findMSB(value[0]), - findMSB(value[1]), - findMSB(value[2]), - findMSB(value[3])); - } -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_matrix.hpp b/include/gal/opengl/glm/core/func_matrix.hpp deleted file mode 100644 index 3c92cbbaba..0000000000 --- a/include/gal/opengl/glm/core/func_matrix.hpp +++ /dev/null @@ -1,150 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_matrix.hpp -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions -/// -/// @defgroup core_func_matrix Matrix functions -/// @ingroup core -/// -/// For each of the following built-in matrix functions, there is both a -/// single-precision floating point version, where all arguments and return values -/// are single precision, and a double-precision floating version, where all -/// arguments and return values are double precision. Only the single-precision -/// floating point version is shown. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef GLM_CORE_func_matrix -#define GLM_CORE_func_matrix GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_matrix - /// @{ - - /// Multiply matrix x by matrix y component-wise, i.e., - /// result[i][j] is the scalar product of x[i][j] and y[i][j]. - /// - /// @tparam matType Floating-point matrix types. - /// - /// @see GLSL matrixCompMult man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL matType matrixCompMult( - matType const & x, - matType const & y); - - /// Treats the first parameter c as a column vector - /// and the second parameter r as a row vector - /// and does a linear algebraic matrix multiply c * r. - /// - /// @tparam matType Floating-point matrix types. - /// - /// @see GLSL outerProduct man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - /// - /// @todo Clarify the declaration to specify that matType doesn't have to be provided when used. - template - GLM_FUNC_DECL matType outerProduct( - vecType const & c, - vecType const & r); - - /// Returns the transposed matrix of x - /// - /// @tparam matType Floating-point matrix types. - /// - /// @see GLSL transpose man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL typename matType::transpose_type transpose( - matType const & x); - - /// Return the determinant of a mat2 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL determinant man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL typename detail::tmat2x2::value_type determinant( - detail::tmat2x2 const & m); - - /// Return the determinant of a mat3 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL determinant man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL typename detail::tmat3x3::value_type determinant( - detail::tmat3x3 const & m); - - /// Return the determinant of a mat4 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL determinant man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL typename detail::tmat4x4::value_type determinant( - detail::tmat4x4 const & m); - - /// Return the inverse of a mat2 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL inverse man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL detail::tmat2x2 inverse( - detail::tmat2x2 const & m); - - /// Return the inverse of a mat3 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL inverse man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL detail::tmat3x3 inverse( - detail::tmat3x3 const & m); - - /// Return the inverse of a mat4 matrix. - /// - /// @tparam valType Floating-point scalar types. - /// - /// @see GLSL inverse man page - /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions - template - GLM_FUNC_DECL detail::tmat4x4 inverse( - detail::tmat4x4 const & m); - - /// @} -}//namespace glm - -#include "func_matrix.inl" - -#endif//GLM_CORE_func_matrix diff --git a/include/gal/opengl/glm/core/func_matrix.inl b/include/gal/opengl/glm/core/func_matrix.inl deleted file mode 100644 index d89d5d4b16..0000000000 --- a/include/gal/opengl/glm/core/func_matrix.inl +++ /dev/null @@ -1,582 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_matrix.inl -/// @date 2008-03-08 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - // matrixCompMult - template - GLM_FUNC_QUALIFIER matType matrixCompMult - ( - matType const & x, - matType const & y - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'matrixCompMult' only accept floating-point inputs"); - - matType result(matType::null); - for(typename matType::size_type i = 0; i < matType::row_size(); ++i) - result[i] = x[i] * y[i]; - return result; - } - - // outerProduct - template - GLM_FUNC_QUALIFIER detail::tmat2x2 outerProduct - ( - detail::tvec2 const & c, - detail::tvec2 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat2x2 m(detail::tmat2x2::null); - m[0][0] = c[0] * r[0]; - m[0][1] = c[1] * r[0]; - m[1][0] = c[0] * r[1]; - m[1][1] = c[1] * r[1]; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x3 outerProduct - ( - detail::tvec3 const & c, - detail::tvec3 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat3x3 m(detail::tmat3x3::null); - for(typename detail::tmat3x3::size_type i(0); i < m.length(); ++i) - m[i] = c * r[i]; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x4 outerProduct - ( - detail::tvec4 const & c, - detail::tvec4 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat4x4 m(detail::tmat4x4::null); - for(typename detail::tmat4x4::size_type i(0); i < m.length(); ++i) - m[i] = c * r[i]; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x3 outerProduct - ( - detail::tvec3 const & c, - detail::tvec2 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat2x3 m(detail::tmat2x3::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[0][2] = c.z * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[1][2] = c.z * r.y; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x2 outerProduct - ( - detail::tvec2 const & c, - detail::tvec3 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat3x2 m(detail::tmat3x2::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[2][0] = c.x * r.z; - m[2][1] = c.y * r.z; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x4 outerProduct - ( - detail::tvec4 const & c, - detail::tvec2 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat2x4 m(detail::tmat2x4::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[0][2] = c.z * r.x; - m[0][3] = c.w * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[1][2] = c.z * r.y; - m[1][3] = c.w * r.y; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x2 outerProduct - ( - detail::tvec2 const & c, - detail::tvec4 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat4x2 m(detail::tmat4x2::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[2][0] = c.x * r.z; - m[2][1] = c.y * r.z; - m[3][0] = c.x * r.w; - m[3][1] = c.y * r.w; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x4 outerProduct - ( - detail::tvec4 const & c, - detail::tvec3 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat3x4 m(detail::tmat3x4::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[0][2] = c.z * r.x; - m[0][3] = c.w * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[1][2] = c.z * r.y; - m[1][3] = c.w * r.y; - m[2][0] = c.x * r.z; - m[2][1] = c.y * r.z; - m[2][2] = c.z * r.z; - m[2][3] = c.w * r.z; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x3 outerProduct - ( - detail::tvec3 const & c, - detail::tvec4 const & r - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'outerProduct' only accept floating-point inputs"); - - detail::tmat4x3 m(detail::tmat4x3::null); - m[0][0] = c.x * r.x; - m[0][1] = c.y * r.x; - m[0][2] = c.z * r.x; - m[1][0] = c.x * r.y; - m[1][1] = c.y * r.y; - m[1][2] = c.z * r.y; - m[2][0] = c.x * r.z; - m[2][1] = c.y * r.z; - m[2][2] = c.z * r.z; - m[3][0] = c.x * r.w; - m[3][1] = c.y * r.w; - m[3][2] = c.z * r.w; - return m; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x2 transpose - ( - detail::tmat2x2 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat2x2 result(detail::tmat2x2::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x3 transpose - ( - detail::tmat3x3 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat3x3 result(detail::tmat3x3::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - result[2][2] = m[2][2]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x4 transpose - ( - detail::tmat4x4 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat4x4 result(detail::tmat4x4::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - result[0][3] = m[3][0]; - - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - result[1][3] = m[3][1]; - - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - result[2][2] = m[2][2]; - result[2][3] = m[3][2]; - - result[3][0] = m[0][3]; - result[3][1] = m[1][3]; - result[3][2] = m[2][3]; - result[3][3] = m[3][3]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x3 transpose - ( - detail::tmat3x2 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat2x3 result(detail::tmat2x3::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x2 transpose - ( - detail::tmat2x3 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat3x2 result(detail::tmat3x2::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x4 transpose - ( - detail::tmat4x2 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat2x4 result(detail::tmat2x4::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - result[0][3] = m[3][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - result[1][3] = m[3][1]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x2 transpose - ( - detail::tmat2x4 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat4x2 result(detail::tmat4x2::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - result[3][0] = m[0][3]; - result[3][1] = m[1][3]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x4 transpose - ( - detail::tmat4x3 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat3x4 result(detail::tmat3x4::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - result[0][3] = m[3][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - result[1][3] = m[3][1]; - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - result[2][2] = m[2][2]; - result[2][3] = m[3][2]; - return result; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x3 transpose - ( - detail::tmat3x4 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'transpose' only accept floating-point inputs"); - - detail::tmat4x3 result(detail::tmat4x3::null); - result[0][0] = m[0][0]; - result[0][1] = m[1][0]; - result[0][2] = m[2][0]; - result[1][0] = m[0][1]; - result[1][1] = m[1][1]; - result[1][2] = m[2][1]; - result[2][0] = m[0][2]; - result[2][1] = m[1][2]; - result[2][2] = m[2][2]; - result[3][0] = m[0][3]; - result[3][1] = m[1][3]; - result[3][2] = m[2][3]; - return result; - } - - template - GLM_FUNC_QUALIFIER typename detail::tmat2x2::value_type determinant - ( - detail::tmat2x2 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'determinant' only accept floating-point inputs"); - - return m[0][0] * m[1][1] - m[1][0] * m[0][1]; - } - - template - GLM_FUNC_QUALIFIER typename detail::tmat3x3::value_type determinant - ( - detail::tmat3x3 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'determinant' only accept floating-point inputs"); - - return - + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) - + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - } - - template - GLM_FUNC_QUALIFIER typename detail::tmat4x4::value_type determinant - ( - detail::tmat4x4 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'determinant' only accept floating-point inputs"); - - T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; - T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; - T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; - T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; - T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; - T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; - - detail::tvec4 DetCof( - + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), - - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), - + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), - - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); - - return m[0][0] * DetCof[0] - + m[0][1] * DetCof[1] - + m[0][2] * DetCof[2] - + m[0][3] * DetCof[3]; - } - - template - GLM_FUNC_QUALIFIER detail::tmat2x2 inverse - ( - detail::tmat2x2 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'inverse' only accept floating-point inputs"); - - //valType Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1]; - T Determinant = determinant(m); - - detail::tmat2x2 Inverse( - + m[1][1] / Determinant, - - m[0][1] / Determinant, - - m[1][0] / Determinant, - + m[0][0] / Determinant); - - return Inverse; - } - - template - GLM_FUNC_QUALIFIER detail::tmat3x3 inverse - ( - detail::tmat3x3 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'inverse' only accept floating-point inputs"); - - //valType Determinant = m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) - // - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) - // + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - - T Determinant = determinant(m); - - detail::tmat3x3 Inverse(detail::tmat3x3::null); - Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]); - Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]); - Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]); - Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]); - Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]); - Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]); - Inverse /= Determinant; - - return Inverse; - } - - template - GLM_FUNC_QUALIFIER detail::tmat4x4 inverse - ( - detail::tmat4x4 const & m - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'inverse' only accept floating-point inputs"); - - T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; - T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; - T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; - - T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; - T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; - T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; - - T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; - T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; - T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; - - T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; - T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; - T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; - - T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; - T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; - T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; - - T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; - T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; - T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; - - detail::tvec4 const SignA(+1, -1, +1, -1); - detail::tvec4 const SignB(-1, +1, -1, +1); - - detail::tvec4 Fac0(Coef00, Coef00, Coef02, Coef03); - detail::tvec4 Fac1(Coef04, Coef04, Coef06, Coef07); - detail::tvec4 Fac2(Coef08, Coef08, Coef10, Coef11); - detail::tvec4 Fac3(Coef12, Coef12, Coef14, Coef15); - detail::tvec4 Fac4(Coef16, Coef16, Coef18, Coef19); - detail::tvec4 Fac5(Coef20, Coef20, Coef22, Coef23); - - detail::tvec4 Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); - detail::tvec4 Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); - detail::tvec4 Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); - detail::tvec4 Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); - - detail::tvec4 Inv0 = SignA * (Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); - detail::tvec4 Inv1 = SignB * (Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); - detail::tvec4 Inv2 = SignA * (Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); - detail::tvec4 Inv3 = SignB * (Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); - - detail::tmat4x4 Inverse(Inv0, Inv1, Inv2, Inv3); - - detail::tvec4 Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); - - T Determinant = glm::dot(m[0], Row0); - - Inverse /= Determinant; - - return Inverse; - } -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_noise.hpp b/include/gal/opengl/glm/core/func_noise.hpp deleted file mode 100644 index 3e5f874187..0000000000 --- a/include/gal/opengl/glm/core/func_noise.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_noise.hpp -/// @date 2008-08-01 / 2011-06-18 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.13 Noise Functions -/// -/// @defgroup core_func_noise Noise functions -/// @ingroup core -/// -/// Noise functions are stochastic functions that can be used to increase visual -/// complexity. Values returned by the following noise functions give the -/// appearance of randomness, but are not truly random. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef glm_core_func_noise -#define glm_core_func_noise GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_noise - /// @{ - - /// Returns a 1D noise value based on the input value x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL noise1 man page - /// @see GLSL 4.20.8 specification, section 8.13 Noise Functions - template - GLM_FUNC_DECL typename genType::value_type noise1(genType const & x); - - /// Returns a 2D noise value based on the input value x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL noise2 man page - /// @see GLSL 4.20.8 specification, section 8.13 Noise Functions - template - GLM_FUNC_DECL detail::tvec2 noise2(genType const & x); - - /// Returns a 3D noise value based on the input value x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL noise3 man page - /// @see GLSL 4.20.8 specification, section 8.13 Noise Functions - template - GLM_FUNC_DECL detail::tvec3 noise3(genType const & x); - - /// Returns a 4D noise value based on the input value x. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL noise4 man page - /// @see GLSL 4.20.8 specification, section 8.13 Noise Functions - template - GLM_FUNC_DECL detail::tvec4 noise4(genType const & x); - - /// @} -}//namespace glm - -#include "func_noise.inl" - -#endif//glm_core_func_noise diff --git a/include/gal/opengl/glm/core/func_noise.inl b/include/gal/opengl/glm/core/func_noise.inl deleted file mode 100644 index 68a19333f1..0000000000 --- a/include/gal/opengl/glm/core/func_noise.inl +++ /dev/null @@ -1,364 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_noise.inl -/// @date 2008-08-01 / 2011-09-27 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - template - GLM_FUNC_QUALIFIER T noise1(T const & x) - { - return noise1(glm::detail::tvec2(x, T(0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec2 noise2(T const & x) - { - return glm::detail::tvec2( - noise1(x + T(0.0)), - noise1(x + T(1.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec3 noise3(T const & x) - { - return glm::detail::tvec3( - noise1(x - T(1.0)), - noise1(x + T(0.0)), - noise1(x + T(1.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec4 noise4(T const & x) - { - return glm::detail::tvec4( - noise1(x - T(1.0)), - noise1(x + T(0.0)), - noise1(x + T(1.0)), - noise1(x + T(2.0))); - } - - template - GLM_FUNC_QUALIFIER T noise1(glm::detail::tvec2 const & v) - { - detail::tvec4 const C = detail::tvec4( - T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 - T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) - T(-0.577350269189626), // -1.0 + 2.0 * C.x - T( 0.024390243902439)); // 1.0 / 41.0 - - // First corner - detail::tvec2 i = floor(v + dot(v, detail::tvec2(C[1]))); - detail::tvec2 x0 = v - i + dot(i, detail::tvec2(C[0])); - - // Other corners - //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 - //i1.y = 1.0 - i1.x; - detail::tvec2 i1 = (x0.x > x0.y) ? detail::tvec2(1, 0) : detail::tvec2(0, 1); - // x0 = x0 - 0.0 + 0.0 * C.xx ; - // x1 = x0 - i1 + 1.0 * C.xx ; - // x2 = x0 - 1.0 + 2.0 * C.xx ; - detail::tvec4 x12 = detail::tvec4(x0.x, x0.y, x0.x, x0.y) + detail::tvec4(C.x, C.x, C.z, C.z); - x12 = detail::tvec4(detail::tvec2(x12) - i1, x12.z, x12.w); - - // Permutations - i = mod(i, T(289)); // Avoid truncation effects in permutation - detail::tvec3 p = permute( - permute(i.y + detail::tvec3(T(0), i1.y, T(1))) - + i.x + detail::tvec3(T(0), i1.x, T(1))); - - detail::tvec3 m = max(T(0.5) - detail::tvec3( - dot(x0, x0), - dot(detail::tvec2(x12.x, x12.y), detail::tvec2(x12.x, x12.y)), - dot(detail::tvec2(x12.z, x12.w), detail::tvec2(x12.z, x12.w))), T(0)); - m = m * m ; - m = m * m ; - - // Gradients: 41 points uniformly over a line, mapped onto a diamond. - // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) - - detail::tvec3 x = T(2) * fract(p * C.w) - T(1); - detail::tvec3 h = abs(x) - T(0.5); - detail::tvec3 ox = floor(x + T(0.5)); - detail::tvec3 a0 = x - ox; - - // Normalise gradients implicitly by scaling m - // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); - m *= T(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); - - // Compute final noise value at P - detail::tvec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - //g.yz = a0.yz * x12.xz + h.yz * x12.yw; - g.y = a0.y * x12.x + h.y * x12.y; - g.z = a0.z * x12.z + h.z * x12.w; - return T(130) * dot(m, g); - } - - template - GLM_FUNC_QUALIFIER T noise1(detail::tvec3 const & v) - { - detail::tvec2 const C(1.0 / 6.0, 1.0 / 3.0); - detail::tvec4 const D(0.0, 0.5, 1.0, 2.0); - - // First corner - detail::tvec3 i(floor(v + dot(v, detail::tvec3(C.y)))); - detail::tvec3 x0(v - i + dot(i, detail::tvec3(C.x))); - - // Other corners - detail::tvec3 g(step(detail::tvec3(x0.y, x0.z, x0.x), x0)); - detail::tvec3 l(T(1) - g); - detail::tvec3 i1(min(g, detail::tvec3(l.z, l.x, l.y))); - detail::tvec3 i2(max(g, detail::tvec3(l.z, l.x, l.y))); - - // x0 = x0 - 0.0 + 0.0 * C.xxx; - // x1 = x0 - i1 + 1.0 * C.xxx; - // x2 = x0 - i2 + 2.0 * C.xxx; - // x3 = x0 - 1.0 + 3.0 * C.xxx; - detail::tvec3 x1(x0 - i1 + C.x); - detail::tvec3 x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y - detail::tvec3 x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y - - // Permutations - i = mod289(i); - detail::tvec4 p(permute(permute(permute( - i.z + detail::tvec4(T(0), i1.z, i2.z, T(1))) + - i.y + detail::tvec4(T(0), i1.y, i2.y, T(1))) + - i.x + detail::tvec4(T(0), i1.x, i2.x, T(1)))); - - // Gradients: 7x7 points over a square, mapped onto an octahedron. - // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) - T n_ = T(0.142857142857); // 1.0/7.0 - detail::tvec3 ns(n_ * detail::tvec3(D.w, D.y, D.z) - detail::tvec3(D.x, D.z, D.x)); - - detail::tvec4 j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) - - detail::tvec4 x_(floor(j * ns.z)); - detail::tvec4 y_(floor(j - T(7) * x_)); // mod(j,N) - - detail::tvec4 x(x_ * ns.x + ns.y); - detail::tvec4 y(y_ * ns.x + ns.y); - detail::tvec4 h(T(1) - abs(x) - abs(y)); - - detail::tvec4 b0(x.x, x.y, y.x, y.y); - detail::tvec4 b1(x.z, x.w, y.z, y.w); - - // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; - // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; - detail::tvec4 s0(floor(b0) * T(2) + T(1)); - detail::tvec4 s1(floor(b1) * T(2) + T(1)); - detail::tvec4 sh(-step(h, detail::tvec4(0.0))); - - detail::tvec4 a0 = detail::tvec4(b0.x, b0.z, b0.y, b0.w) + detail::tvec4(s0.x, s0.z, s0.y, s0.w) * detail::tvec4(sh.x, sh.x, sh.y, sh.y); - detail::tvec4 a1 = detail::tvec4(b1.x, b1.z, b1.y, b1.w) + detail::tvec4(s1.x, s1.z, s1.y, s1.w) * detail::tvec4(sh.z, sh.z, sh.w, sh.w); - - detail::tvec3 p0(a0.x, a0.y, h.x); - detail::tvec3 p1(a0.z, a0.w, h.y); - detail::tvec3 p2(a1.x, a1.y, h.z); - detail::tvec3 p3(a1.z, a1.w, h.w); - - // Normalise gradients - detail::tvec4 norm = taylorInvSqrt(detail::tvec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - - // Mix final noise value - detail::tvec4 m = max(T(0.6) - detail::tvec4(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0)); - m = m * m; - return T(42) * dot(m * m, detail::tvec4(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); - } - - template - GLM_FUNC_QUALIFIER T noise1(detail::tvec4 const & v) - { - detail::tvec4 const C( - 0.138196601125011, // (5 - sqrt(5))/20 G4 - 0.276393202250021, // 2 * G4 - 0.414589803375032, // 3 * G4 - -0.447213595499958); // -1 + 4 * G4 - - // (sqrt(5) - 1)/4 = F4, used once below - T const F4 = T(0.309016994374947451); - - // First corner - detail::tvec4 i = floor(v + dot(v, vec4(F4))); - detail::tvec4 x0 = v - i + dot(i, vec4(C.x)); - - // Other corners - - // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) - detail::tvec4 i0; - detail::tvec3 isX = step(detail::tvec3(x0.y, x0.z, x0.w), detail::tvec3(x0.x)); - detail::tvec3 isYZ = step(detail::tvec3(x0.z, x0.w, x0.w), detail::tvec3(x0.y, x0.y, x0.z)); - // i0.x = dot(isX, vec3(1.0)); - //i0.x = isX.x + isX.y + isX.z; - //i0.yzw = T(1) - isX; - i0 = detail::tvec4(isX.x + isX.y + isX.z, T(1) - isX); - // i0.y += dot(isYZ.xy, vec2(1.0)); - i0.y += isYZ.x + isYZ.y; - //i0.zw += 1.0 - detail::tvec2(isYZ.x, isYZ.y); - i0.z += T(1) - isYZ.x; - i0.w += T(1) - isYZ.y; - i0.z += isYZ.z; - i0.w += T(1) - isYZ.z; - - // i0 now contains the unique values 0,1,2,3 in each channel - detail::tvec4 i3 = clamp(i0, 0.0, 1.0); - detail::tvec4 i2 = clamp(i0 - 1.0, 0.0, 1.0); - detail::tvec4 i1 = clamp(i0 - 2.0, 0.0, 1.0); - - // x0 = x0 - 0.0 + 0.0 * C.xxxx - // x1 = x0 - i1 + 0.0 * C.xxxx - // x2 = x0 - i2 + 0.0 * C.xxxx - // x3 = x0 - i3 + 0.0 * C.xxxx - // x4 = x0 - 1.0 + 4.0 * C.xxxx - detail::tvec4 x1 = x0 - i1 + C.x; - detail::tvec4 x2 = x0 - i2 + C.y; - detail::tvec4 x3 = x0 - i3 + C.z; - detail::tvec4 x4 = x0 + C.w; - - // Permutations - i = mod(i, T(289)); - T j0 = permute(permute(permute(permute(i.w) + i.z) + i.y) + i.x); - detail::tvec4 j1 = permute(permute(permute(permute( - i.w + detail::tvec4(i1.w, i2.w, i3.w, T(1))) - + i.z + detail::tvec4(i1.z, i2.z, i3.z, T(1))) - + i.y + detail::tvec4(i1.y, i2.y, i3.y, T(1))) - + i.x + detail::tvec4(i1.x, i2.x, i3.x, T(1))); - - // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope - // 7*7*6 = 294, which is close to the ring size 17*17 = 289. - detail::tvec4 ip = detail::tvec4(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); - - detail::tvec4 p0 = grad4(j0, ip); - detail::tvec4 p1 = grad4(j1.x, ip); - detail::tvec4 p2 = grad4(j1.y, ip); - detail::tvec4 p3 = grad4(j1.z, ip); - detail::tvec4 p4 = grad4(j1.w, ip); - - // Normalise gradients - detail::tvec4 norm = taylorInvSqrt(detail::tvec4(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); - p0 *= norm.x; - p1 *= norm.y; - p2 *= norm.z; - p3 *= norm.w; - p4 *= taylorInvSqrt(dot(p4, p4)); - - // Mix contributions from the five corners - detail::tvec3 m0 = max(T(0.6) - detail::tvec3(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0)); - detail::tvec2 m1 = max(T(0.6) - detail::tvec2(dot(x3, x3), dot(x4, x4) ), T(0)); - m0 = m0 * m0; - m1 = m1 * m1; - return T(49) * - (dot(m0 * m0, detail::tvec3(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + - dot(m1 * m1, detail::tvec2(dot(p3, x3), dot(p4, x4)))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec2 noise2(glm::detail::tvec2 const & x) - { - return glm::detail::tvec2( - noise1(x + glm::detail::tvec2(0.0)), - noise1(glm::detail::tvec2(0.0) - x)); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec2 noise2(glm::detail::tvec3 const & x) - { - return glm::detail::tvec2( - noise1(x + glm::detail::tvec3(0.0)), - noise1(glm::detail::tvec3(0.0) - x)); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec2 noise2(glm::detail::tvec4 const & x) - { - return glm::detail::tvec2( - noise1(x + glm::detail::tvec4(0.0)), - noise1(glm::detail::tvec4(0.0) - x)); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec3 noise3(glm::detail::tvec2 const & x) - { - return glm::detail::tvec3( - noise1(x - glm::detail::tvec2(1.0)), - noise1(x + glm::detail::tvec2(0.0)), - noise1(x + glm::detail::tvec2(1.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec3 noise3(glm::detail::tvec3 const & x) - { - return glm::detail::tvec3( - noise1(x - glm::detail::tvec3(1.0)), - noise1(x + glm::detail::tvec3(0.0)), - noise1(x + glm::detail::tvec3(1.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec3 noise3(glm::detail::tvec4 const & x) - { - return glm::detail::tvec3( - noise1(x - glm::detail::tvec4(1.0)), - noise1(x + glm::detail::tvec4(0.0)), - noise1(x + glm::detail::tvec4(1.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec4 noise4(glm::detail::tvec2 const & x) - { - return glm::detail::tvec4( - noise1(x - glm::detail::tvec2(1.0)), - noise1(x + glm::detail::tvec2(0.0)), - noise1(x + glm::detail::tvec2(1.0)), - noise1(x + glm::detail::tvec2(2.0))); - } - - - template - GLM_FUNC_QUALIFIER glm::detail::tvec4 noise4(glm::detail::tvec3 const & x) - { - return glm::detail::tvec4( - noise1(x - glm::detail::tvec3(1.0)), - noise1(x + glm::detail::tvec3(0.0)), - noise1(x + glm::detail::tvec3(1.0)), - noise1(x + glm::detail::tvec3(2.0))); - } - - template - GLM_FUNC_QUALIFIER glm::detail::tvec4 noise4(glm::detail::tvec4 const & x) - { - return glm::detail::tvec4( - noise1(x - glm::detail::tvec4(1.0)), - noise1(x + glm::detail::tvec4(0.0)), - noise1(x + glm::detail::tvec4(1.0)), - noise1(x + glm::detail::tvec4(2.0))); - } - -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_packing.hpp b/include/gal/opengl/glm/core/func_packing.hpp deleted file mode 100644 index b4312e12b4..0000000000 --- a/include/gal/opengl/glm/core/func_packing.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_packing.hpp -/// @date 2010-03-17 / 2011-06-15 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions -/// -/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions -/// @ingroup core -/// -/// These functions do not operate component-wise, rather as described in each case. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef GLM_CORE_func_packing -#define GLM_CORE_func_packing GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_packing - /// @{ - - //! First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. - //! Then, the results are packed into the returned 32-bit unsigned integer. - //! - //! The conversion for component c of v to fixed point is done as follows: - //! packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) - //! - //! The first component of the vector will be written to the least significant bits of the output; - //! the last component will be written to the most significant bits. - //! - /// @see GLSL packUnorm2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::uint32 packUnorm2x16(detail::tvec2 const & v); - - //! First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. - //! Then, the results are packed into the returned 32-bit unsigned integer. - //! - //! The conversion for component c of v to fixed point is done as follows: - //! packSnorm2x16: round(clamp(v, -1, +1) * 32767.0) - //! - //! The first component of the vector will be written to the least significant bits of the output; - //! the last component will be written to the most significant bits. - //! - /// @see GLSL packSnorm2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::uint32 packSnorm2x16(detail::tvec2 const & v); - - //! First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. - //! Then, the results are packed into the returned 32-bit unsigned integer. - //! - //! The conversion for component c of v to fixed point is done as follows: - //! packUnorm4x8: round(clamp(c, 0, +1) * 255.0) - //! - //! The first component of the vector will be written to the least significant bits of the output; - //! the last component will be written to the most significant bits. - //! - /// @see GLSL packUnorm4x8 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::uint32 packUnorm4x8(detail::tvec4 const & v); - - //! First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. - //! Then, the results are packed into the returned 32-bit unsigned integer. - //! - //! The conversion for component c of v to fixed point is done as follows: - //! packSnorm4x8: round(clamp(c, -1, +1) * 127.0) - //! - //! The first component of the vector will be written to the least significant bits of the output; - //! the last component will be written to the most significant bits. - //! - /// @see GLSL packSnorm4x8 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::uint32 packSnorm4x8(detail::tvec4 const & v); - - //! First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. - //! Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. - //! - //! The conversion for unpacked fixed-point value f to floating point is done as follows: - //! unpackUnorm2x16: f / 65535.0 - //! - //! The first component of the returned vector will be extracted from the least significant bits of the input; - //! the last component will be extracted from the most significant bits. - //! - /// @see GLSL unpackUnorm2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::tvec2 unpackUnorm2x16(detail::uint32 const & p); - - //! First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. - //! Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. - //! - //! The conversion for unpacked fixed-point value f to floating point is done as follows: - //! unpackSnorm2x16: clamp(f / 32767.0, -1, +1) - //! - //! The first component of the returned vector will be extracted from the least significant bits of the input; - //! the last component will be extracted from the most significant bits. - //! - /// @see GLSL unpackSnorm2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::tvec2 unpackSnorm2x16(detail::uint32 const & p); - - /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. - /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. - /// - /// The conversion for unpacked fixed-point value f to floating point is done as follows: - /// unpackUnorm4x8: f / 255.0 - /// - /// The first component of the returned vector will be extracted from the least significant bits of the input; - /// the last component will be extracted from the most significant bits. - /// - /// @see GLSL unpackUnorm4x8 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::tvec4 unpackUnorm4x8(detail::uint32 const & p); - - /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. - /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. - /// - /// The conversion for unpacked fixed-point value f to floating point is done as follows: - /// unpackSnorm4x8: clamp(f / 127.0, -1, +1) - /// - /// The first component of the returned vector will be extracted from the least significant bits of the input; - /// the last component will be extracted from the most significant bits. - /// - /// @see GLSL unpackSnorm4x8 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::tvec4 unpackSnorm4x8(detail::uint32 const & p); - - /// Returns a double-precision value obtained by packing the components of v into a 64-bit value. - /// If an IEEE 754 Inf or NaN is created, it will not signal, and the resulting floating point value is unspecified. - /// Otherwise, the bit- level representation of v is preserved. - /// The first vector component specifies the 32 least significant bits; - /// the second component specifies the 32 most significant bits. - /// - /// @see GLSL packDouble2x32 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL double packDouble2x32(detail::tvec2 const & v); - - /// Returns a two-component unsigned integer vector representation of v. - /// The bit-level representation of v is preserved. - /// The first component of the vector contains the 32 least significant bits of the double; - /// the second component consists the 32 most significant bits. - /// - /// @see GLSL unpackDouble2x32 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL detail::tvec2 unpackDouble2x32(double const & v); - - /// Returns an unsigned integer obtained by converting the components of a two-component floating-point vector - /// to the 16-bit floating-point representation found in the OpenGL Specification, - /// and then packing these two 16- bit integers into a 32-bit unsigned integer. - /// The first vector component specifies the 16 least-significant bits of the result; - /// the second component specifies the 16 most-significant bits. - /// - /// @see GLSL packHalf2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL uint packHalf2x16(vec2 const & v); - - /// Returns a two-component floating-point vector with components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values, - /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, - /// and converting them to 32-bit floating-point values. - /// The first component of the vector is obtained from the 16 least-significant bits of v; - /// the second component is obtained from the 16 most-significant bits of v. - /// - /// @see GLSL unpackHalf2x16 man page - /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions - GLM_FUNC_DECL vec2 unpackHalf2x16(uint const & v); - - /// @} -}//namespace glm - -#include "func_packing.inl" - -#endif//GLM_CORE_func_packing - diff --git a/include/gal/opengl/glm/core/func_packing.inl b/include/gal/opengl/glm/core/func_packing.inl deleted file mode 100644 index e10e161840..0000000000 --- a/include/gal/opengl/glm/core/func_packing.inl +++ /dev/null @@ -1,208 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_packing.inl -/// @date 2010-03-17 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - GLM_FUNC_QUALIFIER detail::uint32 packUnorm2x16(detail::tvec2 const & v) - { - detail::uint16 A(detail::uint16(round(clamp(v.x, 0.0f, 1.0f) * 65535.0f))); - detail::uint16 B(detail::uint16(round(clamp(v.y, 0.0f, 1.0f) * 65535.0f))); - return detail::uint32((B << 16) | A); - } - - GLM_FUNC_QUALIFIER detail::tvec2 unpackUnorm2x16(detail::uint32 const & p) - { - detail::uint32 Mask16((1 << 16) - 1); - detail::uint32 A((p >> 0) & Mask16); - detail::uint32 B((p >> 16) & Mask16); - return detail::tvec2( - A * 1.0f / 65535.0f, - B * 1.0f / 65535.0f); - } - - GLM_FUNC_QUALIFIER detail::uint32 packSnorm2x16(detail::tvec2 const & v) - { - union iu - { - detail::int16 i; - detail::uint16 u; - } A, B; - - detail::tvec2 Unpack = clamp(v ,-1.0f, 1.0f) * 32767.0f; - A.i = detail::int16(round(Unpack.x)); - B.i = detail::int16(round(Unpack.y)); - detail::uint32 Pack = (detail::uint32(B.u) << 16) | (detail::uint32(A.u) << 0); - return Pack; - } - - GLM_FUNC_QUALIFIER detail::tvec2 unpackSnorm2x16(detail::uint32 const & p) - { - union iu - { - detail::int16 i; - detail::uint16 u; - } A, B; - - detail::uint32 Mask16((1 << 16) - 1); - A.u = detail::uint16((p >> 0) & Mask16); - B.u = detail::uint16((p >> 16) & Mask16); - detail::tvec2 Pack(A.i, B.i); - - return clamp(Pack * 1.0f / 32767.0f, -1.0f, 1.0f); - } - - GLM_FUNC_QUALIFIER detail::uint32 packUnorm4x8(detail::tvec4 const & v) - { - detail::uint8 A((detail::uint8)round(clamp(v.x, 0.0f, 1.0f) * 255.0f)); - detail::uint8 B((detail::uint8)round(clamp(v.y, 0.0f, 1.0f) * 255.0f)); - detail::uint8 C((detail::uint8)round(clamp(v.z, 0.0f, 1.0f) * 255.0f)); - detail::uint8 D((detail::uint8)round(clamp(v.w, 0.0f, 1.0f) * 255.0f)); - return detail::uint32((D << 24) | (C << 16) | (B << 8) | A); - } - - GLM_FUNC_QUALIFIER detail::tvec4 unpackUnorm4x8(detail::uint32 const & p) - { - detail::uint32 Mask8((1 << 8) - 1); - detail::uint32 A((p >> 0) & Mask8); - detail::uint32 B((p >> 8) & Mask8); - detail::uint32 C((p >> 16) & Mask8); - detail::uint32 D((p >> 24) & Mask8); - return detail::tvec4( - A * 1.0f / 255.0f, - B * 1.0f / 255.0f, - C * 1.0f / 255.0f, - D * 1.0f / 255.0f); - } - - GLM_FUNC_QUALIFIER detail::uint32 packSnorm4x8(detail::tvec4 const & v) - { - union iu - { - detail::int8 i; - detail::uint8 u; - } A, B, C, D; - - detail::tvec4 Unpack = clamp(v ,-1.0f, 1.0f) * 127.0f; - A.i = detail::int8(round(Unpack.x)); - B.i = detail::int8(round(Unpack.y)); - C.i = detail::int8(round(Unpack.z)); - D.i = detail::int8(round(Unpack.w)); - detail::uint32 Pack = (detail::uint32(D.u) << 24) | (detail::uint32(C.u) << 16) | (detail::uint32(B.u) << 8) | (detail::uint32(A.u) << 0); - return Pack; - } - - GLM_FUNC_QUALIFIER detail::tvec4 unpackSnorm4x8(detail::uint32 const & p) - { - union iu - { - detail::int8 i; - detail::uint8 u; - } A, B, C, D; - - detail::uint32 Mask8((1 << 8) - 1); - A.u = detail::uint8((p >> 0) & Mask8); - B.u = detail::uint8((p >> 8) & Mask8); - C.u = detail::uint8((p >> 16) & Mask8); - D.u = detail::uint8((p >> 24) & Mask8); - detail::tvec4 Pack(A.i, B.i, C.i, D.i); - - return clamp(Pack * 1.0f / 127.0f, -1.0f, 1.0f); - } - - GLM_FUNC_QUALIFIER double packDouble2x32(detail::tvec2 const & v) - { - struct uint32_pair - { - detail::uint32 x; - detail::uint32 y; - }; - - union helper - { - uint32_pair input; - double output; - } Helper; - - Helper.input.x = v.x; - Helper.input.y = v.y; - - return Helper.output; - //return *(double*)&v; - } - - GLM_FUNC_QUALIFIER detail::tvec2 unpackDouble2x32(double const & v) - { - struct uint32_pair - { - detail::uint32 x; - detail::uint32 y; - }; - - union helper - { - double input; - uint32_pair output; - } Helper; - - Helper.input = v; - - return detail::tvec2(Helper.output.x, Helper.output.y); - } - - GLM_FUNC_QUALIFIER uint packHalf2x16(detail::tvec2 const & v) - { - union helper - { - uint other; - struct - { - detail::hdata a, b; - } orig; - } Pack; - - Pack.orig.a = detail::toFloat16(v.x); - Pack.orig.b = detail::toFloat16(v.y); - return Pack.other; - } - - GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint const & v) - { - union helper - { - uint other; - struct - { - detail::hdata a, b; - } orig; - } Unpack; - Unpack.other = v; - - return vec2(detail::toFloat32(Unpack.orig.a), detail::toFloat32(Unpack.orig.b)); - } -}//namespace glm - diff --git a/include/gal/opengl/glm/core/func_trigonometric.hpp b/include/gal/opengl/glm/core/func_trigonometric.hpp deleted file mode 100644 index 9954d9cea6..0000000000 --- a/include/gal/opengl/glm/core/func_trigonometric.hpp +++ /dev/null @@ -1,203 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_trigonometric.hpp -/// @date 2008-08-01 / 2011-06-15 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions -/// -/// @defgroup core_func_trigonometric Angle and Trigonometry Functions -/// @ingroup core -/// -/// Function parameters specified as angle are assumed to be in units of radians. -/// In no case will any of these functions result in a divide by zero error. If -/// the divisor of a ratio is 0, then results will be undefined. -/// -/// These all operate component-wise. The description is per component. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef GLM_CORE_func_trigonometric -#define GLM_CORE_func_trigonometric GLM_VERSION - -namespace glm -{ - /// @addtogroup core_func_trigonometric - /// @{ - - /// Converts degrees to radians and returns the result. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL radians man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType radians(genType const & degrees); - - /// Converts radians to degrees and returns the result. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL degrees man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType degrees(genType const & radians); - - /// The standard trigonometric sine function. - /// The values returned by this function will range from [-1, 1]. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL sin man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType sin(genType const & angle); - - /// The standard trigonometric cosine function. - /// The values returned by this function will range from [-1, 1]. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL cos man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType cos(genType const & angle); - - /// The standard trigonometric tangent function. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL tan man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType tan(genType const & angle); - - /// Arc sine. Returns an angle whose sine is x. - /// The range of values returned by this function is [-PI/2, PI/2]. - /// Results are undefined if |x| > 1. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL asin man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType asin(genType const & x); - - /// Arc cosine. Returns an angle whose sine is x. - /// The range of values returned by this function is [0, PI]. - /// Results are undefined if |x| > 1. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL acos man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType acos(genType const & x); - - /// Arc tangent. Returns an angle whose tangent is y/x. - /// The signs of x and y are used to determine what - /// quadrant the angle is in. The range of values returned - /// by this function is [-PI, PI]. Results are undefined - /// if x and y are both 0. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL atan man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType atan(genType const & y, genType const & x); - - /// Arc tangent. Returns an angle whose tangent is y_over_x. - /// The range of values returned by this function is [-PI/2, PI/2]. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL atan man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType atan(genType const & y_over_x); - - /// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2 - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL sinh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType sinh(genType const & angle); - - /// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2 - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL cosh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType cosh(genType const & angle); - - /// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle) - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL tanh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType tanh(genType const & angle); - - /// Arc hyperbolic sine; returns the inverse of sinh. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL asinh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType asinh(genType const & x); - - /// Arc hyperbolic cosine; returns the non-negative inverse - /// of cosh. Results are undefined if x < 1. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL acosh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType acosh(genType const & x); - - /// Arc hyperbolic tangent; returns the inverse of tanh. - /// Results are undefined if abs(x) >= 1. - /// - /// @tparam genType Floating-point scalar or vector types. - /// - /// @see GLSL atanh man page - /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions - template - GLM_FUNC_DECL genType atanh(genType const & x); - - /// @} -}//namespace glm - -#include "func_trigonometric.inl" - -#endif//GLM_CORE_func_trigonometric - - diff --git a/include/gal/opengl/glm/core/func_trigonometric.inl b/include/gal/opengl/glm/core/func_trigonometric.inl deleted file mode 100644 index bd59cd73d4..0000000000 --- a/include/gal/opengl/glm/core/func_trigonometric.inl +++ /dev/null @@ -1,244 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_trigonometric.inl -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/////////////////////////////////////////////////////////////////////////////////// - -namespace glm -{ - // radians - template - GLM_FUNC_QUALIFIER genType radians - ( - genType const & degrees - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'radians' only accept floating-point input"); - - genType const pi = genType(3.1415926535897932384626433832795); - return degrees * (pi / genType(180)); - } - - VECTORIZE_VEC(radians) - - // degrees - template - GLM_FUNC_QUALIFIER genType degrees - ( - genType const & radians - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'degrees' only accept floating-point input"); - - const genType pi = genType(3.1415926535897932384626433832795); - return radians * (genType(180) / pi); - } - - VECTORIZE_VEC(degrees) - - // sin - template - GLM_FUNC_QUALIFIER genType sin - ( - genType const & angle - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'sin' only accept floating-point input"); - - return genType(::std::sin(angle)); - } - - VECTORIZE_VEC(sin) - - // cos - template - GLM_FUNC_QUALIFIER genType cos(genType const & angle) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'cos' only accept floating-point input"); - - return genType(::std::cos(angle)); - } - - VECTORIZE_VEC(cos) - - // tan - template - GLM_FUNC_QUALIFIER genType tan - ( - genType const & angle - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'tan' only accept floating-point input"); - - return genType(::std::tan(angle)); - } - - VECTORIZE_VEC(tan) - - // asin - template - GLM_FUNC_QUALIFIER genType asin - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'asin' only accept floating-point input"); - - return genType(::std::asin(x)); - } - - VECTORIZE_VEC(asin) - - // acos - template - GLM_FUNC_QUALIFIER genType acos - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'acos' only accept floating-point input"); - - return genType(::std::acos(x)); - } - - VECTORIZE_VEC(acos) - - // atan - template - GLM_FUNC_QUALIFIER genType atan - ( - genType const & y, - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'atan' only accept floating-point input"); - - return genType(::std::atan2(y, x)); - } - - VECTORIZE_VEC_VEC(atan) - - template - GLM_FUNC_QUALIFIER genType atan - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'atan' only accept floating-point input"); - - return genType(::std::atan(x)); - } - - VECTORIZE_VEC(atan) - - // sinh - template - GLM_FUNC_QUALIFIER genType sinh - ( - genType const & angle - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'sinh' only accept floating-point input"); - - return genType(std::sinh(angle)); - } - - VECTORIZE_VEC(sinh) - - // cosh - template - GLM_FUNC_QUALIFIER genType cosh - ( - genType const & angle - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'cosh' only accept floating-point input"); - - return genType(std::cosh(angle)); - } - - VECTORIZE_VEC(cosh) - - // tanh - template - GLM_FUNC_QUALIFIER genType tanh - ( - genType const & angle - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'tanh' only accept floating-point input"); - - return genType(std::tanh(angle)); - } - - VECTORIZE_VEC(tanh) - - // asinh - template - GLM_FUNC_QUALIFIER genType asinh - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'asinh' only accept floating-point input"); - - return (x < genType(0) ? genType(-1) : (x > genType(0) ? genType(1) : genType(0))) * log(abs(x) + sqrt(genType(1) + x * x)); - } - - VECTORIZE_VEC(asinh) - - // acosh - template - GLM_FUNC_QUALIFIER genType acosh - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'acosh' only accept floating-point input"); - - if(x < genType(1)) - return genType(0); - return log(x + sqrt(x * x - genType(1))); - } - - VECTORIZE_VEC(acosh) - - // atanh - template - GLM_FUNC_QUALIFIER genType atanh - ( - genType const & x - ) - { - GLM_STATIC_ASSERT(detail::type::is_float, "'atanh' only accept floating-point input"); - - if(abs(x) >= genType(1)) - return 0; - return genType(0.5) * log((genType(1) + x) / (genType(1) - x)); - } - - VECTORIZE_VEC(atanh) - -}//namespace glm diff --git a/include/gal/opengl/glm/core/func_vector_relational.hpp b/include/gal/opengl/glm/core/func_vector_relational.hpp deleted file mode 100644 index 4ffe14eab7..0000000000 --- a/include/gal/opengl/glm/core/func_vector_relational.hpp +++ /dev/null @@ -1,138 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////// -/// OpenGL Mathematics (glm.g-truc.net) -/// -/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) -/// Permission is hereby granted, free of charge, to any person obtaining a copy -/// of this software and associated documentation files (the "Software"), to deal -/// in the Software without restriction, including without limitation the rights -/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -/// copies of the Software, and to permit persons to whom the Software is -/// furnished to do so, subject to the following conditions: -/// -/// The above copyright notice and this permission notice shall be included in -/// all copies or substantial portions of the Software. -/// -/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -/// THE SOFTWARE. -/// -/// @ref core -/// @file glm/core/func_vector_relational.hpp -/// @date 2008-08-03 / 2011-06-15 -/// @author Christophe Riccio -/// -/// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions -/// -/// @defgroup core_func_vector_relational Vector Relational Functions -/// @ingroup core -/// -/// Relational and equality operators (<, <=, >, >=, ==, !=) are defined to -/// operate on scalars and produce scalar Boolean results. For vector results, -/// use the following built-in functions. -/// -/// In all cases, the sizes of all the input and return vectors for any particular -/// call must match. -/////////////////////////////////////////////////////////////////////////////////// - -#ifndef GLM_CORE_func_vector_relational -#define GLM_CORE_func_vector_relational GLM_VERSION - -#include "_detail.hpp" - -namespace glm -{ - /// @addtogroup core_func_vector_relational - /// @{ - - /// Returns the component-wise comparison result of x < y. - /// - /// @tparam vecType Floating-point or integer vector types. - /// - /// @see GLSL lessThan man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type lessThan(vecType const & x, vecType const & y); - - /// Returns the component-wise comparison of result x <= y. - /// - /// @tparam vecType Floating-point or integer vector types. - /// - /// @see GLSL lessThanEqual man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type lessThanEqual(vecType const & x, vecType const & y); - - /// Returns the component-wise comparison of result x > y. - /// - /// @tparam vecType Floating-point or integer vector types. - /// - /// @see GLSL greaterThan man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type greaterThan(vecType const & x, vecType const & y); - - /// Returns the component-wise comparison of result x >= y. - /// - /// @tparam vecType Floating-point or integer vector types. - /// - /// @see GLSL greaterThanEqual man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type greaterThanEqual(vecType const & x, vecType const & y); - - /// Returns the component-wise comparison of result x == y. - /// - /// @tparam vecType Floating-point, integer or boolean vector types. - /// - /// @see GLSL equal man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type equal(vecType const & x, vecType const & y); - - /// Returns the component-wise comparison of result x != y. - /// - /// @tparam vecType Floating-point, integer or boolean vector types. - /// - /// @see GLSL notEqual man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template - GLM_FUNC_DECL typename vecType::bool_type notEqual(vecType const & x, vecType const & y); - - /// Returns true if any component of x is true. - /// - /// @tparam vecType Boolean vector types. - /// - /// @see GLSL any man page - /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions - template