KiCad PCB EDA Suite
Loading...
Searching...
No Matches
3d_cache.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Cirilo Bernardo <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * Copyright (C) 2022 CERN
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#define GLM_FORCE_RADIANS
27
28#include <mutex>
29#include <utility>
30
31#include <wx/datetime.h>
32#include <wx/dir.h>
33#include <wx/log.h>
34#include <wx/stdpaths.h>
35
36#include "3d_cache.h"
37#include "3d_info.h"
38#include "3d_plugin_manager.h"
40#include "sg/scenegraph.h"
42
43#include <advanced_config.h>
44#include <common.h> // For ExpandEnvVarSubstitutions
45#include <filename_resolver.h>
46#include <mmh3_hash.h>
47#include <paths.h>
48#include <pgm_base.h>
49#include <project.h>
52#include <wx_filename.h>
53
54
55#define MASK_3D_CACHE "3D_CACHE"
56
57static std::mutex mutex3D_cache;
58
59
60static bool checkTag( const char* aTag, void* aPluginMgrPtr )
61{
62 if( nullptr == aTag || nullptr == aPluginMgrPtr )
63 return false;
64
65 S3D_PLUGIN_MANAGER *pp = (S3D_PLUGIN_MANAGER*) aPluginMgrPtr;
66
67 return pp->CheckTag( aTag );
68}
69
70
72{
73public:
76
77 void SetHash( const HASH_128& aHash );
78 const wxString GetCacheBaseName();
79
80 wxDateTime modTime; // file modification time
82 std::string pluginInfo; // PluginName:Version string
85
86private:
87 // prohibit assignment and default copy constructor
90
91 wxString m_CacheBaseName; // base name of cache file
92};
93
94
96{
97 sceneData = nullptr;
98 renderData = nullptr;
99 m_hash.Clear();
100}
101
102
104{
105 delete sceneData;
106
107 if( nullptr != renderData )
109}
110
111
113{
114 m_hash = aHash;
115}
116
117
119{
120 if( m_CacheBaseName.empty() )
121 m_CacheBaseName = m_hash.ToString();
122
123 return m_CacheBaseName;
124}
125
126
133
134
136{
137 FlushCache();
138
139 delete m_FNResolver;
140 delete m_Plugins;
141}
142
143
144SCENEGRAPH* S3D_CACHE::load( const wxString& aModelFile, const wxString& aBasePath,
145 S3D_CACHE_ENTRY** aCachePtr,
146 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
147{
148 if( aCachePtr )
149 *aCachePtr = nullptr;
150
151 wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, std::move( aEmbeddedFilesStack ) );
152
153 if( full3Dpath.empty() )
154 {
155 // In CLI / scripting contexts, transparently substitute a matching
156 // STEP model for a missing WRL reference so renders and exports
157 // don't silently lose geometry. The GUI handles this via the
158 // DIALOG_MIGRATE_3D_MODELS load-time auto-migration, so we skip the
159 // fallback there to avoid masking user-visible "missing" state.
160 if( !Pgm().IsGUI() && MODEL_SUBSTITUTION::IsWrlExtension( aModelFile ) )
161 {
162 std::lock_guard<std::mutex> catLock( m_substCatalogMutex );
163
165 {
166 const wxString projectPath =
167 m_project ? m_project->GetProjectPath() : wxString();
168 m_substCatalog.Build( projectPath, m_FNResolver );
169 m_substCatalogBuilt = true;
170 }
171
172 const wxString subst = m_substCatalog.FindMatchFor( aModelFile );
173
174 if( !subst.IsEmpty() )
175 {
176 wxLogTrace( MASK_3D_CACHE,
177 wxT( "%s:%s:%d\n * [3D model] substituting '%s' -> '%s'\n" ),
178 __FILE__, __FUNCTION__, __LINE__, aModelFile, subst );
179 full3Dpath = subst;
180 }
181 }
182
183 if( full3Dpath.empty() )
184 {
185 // the model cannot be found; we cannot proceed
186 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
187 __FILE__, __FUNCTION__, __LINE__, aModelFile );
188 return nullptr;
189 }
190 }
191
192 // check cache if file is already loaded
193 std::lock_guard<std::mutex> lock( mutex3D_cache );
194
195 std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
196 mi = m_CacheMap.find( full3Dpath );
197
198 if( mi != m_CacheMap.end() )
199 {
200 wxFileName fname( full3Dpath );
201
202 if( fname.FileExists() ) // Only check if file exists. If not, it will
203 { // use the same model in cache.
205 wxDateTime fmdate = fname.GetModificationTime();
206
207 if( fmdate != mi->second->modTime )
208 {
209 HASH_128 hashSum;
210 getHash( full3Dpath, hashSum );
211 mi->second->modTime = fmdate;
212
213 if( hashSum != mi->second->m_hash )
214 {
215 mi->second->SetHash( hashSum );
216 reload = true;
217 }
218 }
219
220 if( reload )
221 {
222 if( nullptr != mi->second->sceneData )
223 {
224 S3D::DestroyNode( mi->second->sceneData );
225 mi->second->sceneData = nullptr;
226 }
227
228 if( nullptr != mi->second->renderData )
229 S3D::Destroy3DModel( &mi->second->renderData );
230
231 mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
232 mi->second->pluginInfo );
233 }
234 }
235
236 if( nullptr != aCachePtr )
237 *aCachePtr = mi->second;
238
239 return mi->second->sceneData;
240 }
241
242 // a cache item does not exist; search the Filename->Cachename map
243 return checkCache( full3Dpath, aCachePtr );
244}
245
246
247SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
248 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
249{
250 return load( aModelFile, aBasePath, nullptr, std::move( aEmbeddedFilesStack ) );
251}
252
253
254SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
255{
256 if( aCachePtr )
257 *aCachePtr = nullptr;
258
259 HASH_128 hashSum;
261 m_CacheList.push_back( ep );
262 wxFileName fname( aFileName );
263 ep->modTime = fname.GetModificationTime();
264
265 if( !getHash( aFileName, hashSum ) || m_CacheDir.empty() )
266 {
267 // just in case we can't get a hash digest (for example, on access issues)
268 // or we do not have a configured cache file directory, we create an
269 // entry to prevent further attempts at loading the file
270
271 if( m_CacheMap.emplace( aFileName, ep ).second == false )
272 {
273 wxLogTrace( MASK_3D_CACHE,
274 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
275 __FILE__, __FUNCTION__, __LINE__, aFileName );
276
277 m_CacheList.pop_back();
278 delete ep;
279 }
280 else
281 {
282 if( aCachePtr )
283 *aCachePtr = ep;
284 }
285
286 return nullptr;
287 }
288
289 if( m_CacheMap.emplace( aFileName, ep ).second == false )
290 {
291 wxLogTrace( MASK_3D_CACHE,
292 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
293 __FILE__, __FUNCTION__, __LINE__, aFileName );
294
295 m_CacheList.pop_back();
296 delete ep;
297 return nullptr;
298 }
299
300 if( aCachePtr )
301 *aCachePtr = ep;
302
303 ep->SetHash( hashSum );
304
305 wxString bname = ep->GetCacheBaseName();
306 wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
307
308 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
309 && loadCacheData( ep ) )
310 return ep->sceneData;
311
312 ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
313
314 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
315 saveCacheData( ep );
316
317 return ep->sceneData;
318}
319
320
321bool S3D_CACHE::getHash( const wxString& aFileName, HASH_128& aHash )
322{
323 if( aFileName.empty() )
324 {
325 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
326 __FILE__, __FUNCTION__, __LINE__ );
327
328 return false;
329 }
330
331#ifdef _WIN32
332 FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
333#else
334 FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
335#endif
336
337 if( nullptr == fp )
338 return false;
339
340 MMH3_HASH dblock( 0xA1B2C3D4 );
341 std::vector<char> block( 4096 );
342 size_t bsize = 0;
343
344 while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
345 dblock.add( block );
346
347 fclose( fp );
348 aHash = dblock.digest();
349 return true;
350}
351
352
354{
355 wxString bname = aCacheItem->GetCacheBaseName();
356
357 if( bname.empty() )
358 {
359 wxLogTrace( MASK_3D_CACHE,
360 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
361
362 return false;
363 }
364
365 if( m_CacheDir.empty() )
366 {
367 wxLogTrace( MASK_3D_CACHE,
368 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
369
370 return false;
371 }
372
373 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
374
375 if( !wxFileName::FileExists( fname ) )
376 {
377 wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
378 return false;
379 }
380
381 if( nullptr != aCacheItem->sceneData )
382 S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
383
384 aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
385
386 if( nullptr == aCacheItem->sceneData )
387 return false;
388
389 return true;
390}
391
392
394{
395 if( nullptr == aCacheItem )
396 {
397 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
398 __FILE__, __FUNCTION__, __LINE__ );
399
400 return false;
401 }
402
403 if( nullptr == aCacheItem->sceneData )
404 {
405 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
406 __FILE__, __FUNCTION__, __LINE__ );
407
408 return false;
409 }
410
411 wxString bname = aCacheItem->GetCacheBaseName();
412
413 if( bname.empty() )
414 {
415 wxLogTrace( MASK_3D_CACHE,
416 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
417
418 return false;
419 }
420
421 if( m_CacheDir.empty() )
422 {
423 wxLogTrace( MASK_3D_CACHE,
424 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
425
426 return false;
427 }
428
429 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
430
431 if( wxFileName::Exists( fname ) )
432 {
433 if( !wxFileName::FileExists( fname ) )
434 {
435 wxLogTrace( MASK_3D_CACHE,
436 wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
437
438 return false;
439 }
440 }
441
442 return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
443 aCacheItem->pluginInfo.c_str() );
444}
445
446
447bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
448{
449 if( !m_ConfigDir.empty() )
450 return false;
451
452 wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
453
454 cfgdir.Normalize( FN_NORMALIZE_FLAGS );
455
456 if( !cfgdir.DirExists() )
457 {
458 cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
459
460 if( !cfgdir.DirExists() )
461 {
462 wxLogTrace( MASK_3D_CACHE,
463 wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
464 __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
465
466 return false;
467 }
468 }
469
470 m_ConfigDir = cfgdir.GetPath();
471
472 // inform the file resolver of the config directory
473 if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
474 {
475 wxLogTrace( MASK_3D_CACHE,
476 wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
477 " * config directory: '%s'" ),
478 __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
479 }
480
481 // 3D cache data must go to a user's cache directory;
482 // unfortunately wxWidgets doesn't seem to provide
483 // functions to retrieve such a directory.
484 //
485 // 1. OSX: ~/Library/Caches/kicad/3d/
486 // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
487 // 3. MSWin: AppData\Local\kicad\3d
488 wxFileName cacheDir;
489 cacheDir.AssignDir( PATHS::GetUserCachePath() );
490 cacheDir.AppendDir( wxT( "3d" ) );
491
492 if( !cacheDir.DirExists() )
493 {
494 cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
495
496 if( !cacheDir.DirExists() )
497 {
498 wxLogTrace( MASK_3D_CACHE,
499 wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
500 __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
501
502 return false;
503 }
504 }
505
506 m_CacheDir = cacheDir.GetPathWithSep();
507 return true;
508}
509
510
512{
513 m_project = aProject;
514
515 bool hasChanged = false;
516
517 if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
518 {
519 m_CacheMap.clear();
520
521 std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
522 std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
523
524 while( sL != eL )
525 {
526 delete *sL;
527 ++sL;
528 }
529
530 m_CacheList.clear();
531
532 return true;
533 }
534
535 return false;
536}
537
538
540{
541 m_FNResolver->SetProgramBase( aBase );
542}
543
544
546{
547 return m_FNResolver;
548}
549
550
551std::list< wxString > const* S3D_CACHE::GetFileFilters() const
552{
553 return m_Plugins->GetFileFilters();
554}
555
556
557void S3D_CACHE::FlushCache( bool closePlugins )
558{
559 std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
560 std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
561
562 while( sCL != eCL )
563 {
564 delete *sCL;
565 ++sCL;
566 }
567
568 m_CacheList.clear();
569 m_CacheMap.clear();
570
571 if( closePlugins )
572 ClosePlugins();
573}
574
575
577{
578 if( m_Plugins )
579 m_Plugins->ClosePlugins();
580}
581
582
583S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
584 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
585{
586 S3D_CACHE_ENTRY* cp = nullptr;
587 SCENEGRAPH* sp = load( aModelFileName, aBasePath, &cp, std::move( aEmbeddedFilesStack ) );
588
589 if( !sp )
590 return nullptr;
591
592 if( !cp )
593 {
594 wxLogTrace( MASK_3D_CACHE,
595 wxT( "%s:%s:%d\n * [BUG] model loaded with no associated S3D_CACHE_ENTRY" ),
596 __FILE__, __FUNCTION__, __LINE__ );
597
598 return nullptr;
599 }
600
601 if( cp->renderData )
602 return cp->renderData;
603
604 S3DMODEL* mp = S3D::GetModel( sp );
605 cp->renderData = mp;
606
607 return mp;
608}
609
610void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
611{
612 wxDir dir;
613 wxString fileSpec = wxT( "*.3dc" );
614 wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
615 size_t numFilesFound = 0;
616
617 wxFileName thisFile;
618 wxDateTime lastAccess, thresholdDate;
619 wxDateSpan durationInDays;
620
621 // Calc the threshold date above which we delete cache files
622 durationInDays.SetDays( aNumDaysOld );
623 thresholdDate = wxDateTime::Now() - durationInDays;
624
625 // If the cache directory can be found and opened, then we'll try and clean it up
626 if( dir.Open( m_CacheDir ) )
627 {
628 thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
629
630 // Get a list of all the ".3dc" files in the cache directory
631 numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
632
633 for( unsigned int i = 0; i < numFilesFound; i++ )
634 {
635 // Completes path to specific file so we can get its "last access" date
636 thisFile.SetFullName( fileList[i] );
637
638 // Only get "last access" time to compare against. Don't need the other 2 timestamps.
639 if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
640 {
641 if( lastAccess.IsEarlierThan( thresholdDate ) )
642 {
643 // This file is older than the threshold so delete it
644 wxRemoveFile( thisFile.GetFullPath() );
645 }
646 }
647 }
648 }
649}
#define MASK_3D_CACHE
Definition 3d_cache.cpp:55
static std::mutex mutex3D_cache
Definition 3d_cache.cpp:57
static bool checkTag(const char *aTag, void *aPluginMgrPtr)
Definition 3d_cache.cpp:60
defines the basic data associated with a single 3D model.
manages 3D model plugins
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Provide an extensible class to resolve 3D model paths.
A streaming C++ equivalent for MurmurHash3_x64_128.
Definition mmh3_hash.h:60
FORCE_INLINE void add(const std::string &input)
Definition mmh3_hash.h:121
FORCE_INLINE HASH_128 digest()
Definition mmh3_hash.h:140
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
Definition paths.cpp:460
Container for data for KiCad programs.
Definition pgm_base.h:108
Container for project specific data.
Definition project.h:66
Definition 3d_cache.cpp:72
S3D_CACHE_ENTRY & operator=(const S3D_CACHE_ENTRY &source)
HASH_128 m_hash
Definition 3d_cache.cpp:81
S3DMODEL * renderData
Definition 3d_cache.cpp:84
~S3D_CACHE_ENTRY()
Definition 3d_cache.cpp:103
SCENEGRAPH * sceneData
Definition 3d_cache.cpp:83
S3D_CACHE_ENTRY(const S3D_CACHE_ENTRY &source)
void SetHash(const HASH_128 &aHash)
Definition 3d_cache.cpp:112
const wxString GetCacheBaseName()
Definition 3d_cache.cpp:118
std::string pluginInfo
Definition 3d_cache.cpp:82
wxString m_CacheBaseName
Definition 3d_cache.cpp:91
wxDateTime modTime
Definition 3d_cache.cpp:80
S3D_CACHE_ENTRY()
Definition 3d_cache.cpp:95
void SetProgramBase(PGM_BASE *aBase)
Set the filename resolver's pointer to the application's PGM_BASE instance.
Definition 3d_cache.cpp:539
wxString m_CacheDir
Definition 3d_cache.h:194
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition 3d_cache.cpp:353
virtual ~S3D_CACHE()
Definition 3d_cache.cpp:135
void FlushCache(bool closePlugins=true)
Free all data in the cache and by default closes all plugins.
Definition 3d_cache.cpp:557
bool Set3DConfigDir(const wxString &aConfigDir)
Set the configuration directory to be used by the model manager for storing 3D model manager configur...
Definition 3d_cache.cpp:447
S3DMODEL * GetModel(const wxString &aModelFileName, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model and to translate it into an S3D_MODEL structure for displa...
Definition 3d_cache.cpp:583
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Find or create cache entry for file name.
Definition 3d_cache.cpp:254
MODEL_SUBSTITUTION::STEP_CATALOG m_substCatalog
Definition 3d_cache.h:202
PROJECT * m_project
Definition 3d_cache.h:193
S3D_PLUGIN_MANAGER * m_Plugins
Definition 3d_cache.h:191
bool saveCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition 3d_cache.cpp:393
SCENEGRAPH * load(const wxString &aModelFile, const wxString &aBasePath, S3D_CACHE_ENTRY **aCachePtr=nullptr, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack={})
Definition 3d_cache.cpp:144
wxString m_ConfigDir
base configuration path for 3D items.
Definition 3d_cache.h:195
std::mutex m_substCatalogMutex
Lazy STEP-catalog used by the headless resolver fallback in load().
Definition 3d_cache.h:200
bool m_substCatalogBuilt
Definition 3d_cache.h:201
std::list< wxString > const * GetFileFilters() const
Return the list of file filters retrieved from the plugins.
Definition 3d_cache.cpp:551
FILENAME_RESOLVER * GetResolver() noexcept
Definition 3d_cache.cpp:545
std::list< S3D_CACHE_ENTRY * > m_CacheList
Cache entries.
Definition 3d_cache.h:184
bool SetProject(PROJECT *aProject)
Set the current project's working directory; this affects the model search path.
Definition 3d_cache.cpp:511
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
Definition 3d_cache.cpp:610
std::map< wxString, S3D_CACHE_ENTRY *, rsort_wxString > m_CacheMap
Mapping of file names to cache names and data.
Definition 3d_cache.h:187
SCENEGRAPH * Load(const wxString &aModelFile, const wxString &aBasePath, std::vector< const EMBEDDED_FILES * > aEmbeddedFilesStack)
Attempt to load the scene data for a model.
Definition 3d_cache.cpp:247
void ClosePlugins()
Unload plugins to free memory.
Definition 3d_cache.cpp:576
bool getHash(const wxString &aFileName, HASH_128 &aHash)
Calculate the SHA1 hash of the given file.
Definition 3d_cache.cpp:321
FILENAME_RESOLVER * m_FNResolver
Definition 3d_cache.h:189
bool CheckTag(const char *aTag)
Check the given tag and returns true if the plugin named in the tag is not loaded or the plugin is lo...
Define the basic data set required to represent a 3D model.
Definition scenegraph.h:45
The base class of all Scene Graph nodes.
Definition sg_node.h:75
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
Definition common.cpp:707
The common library.
bool m_Skip3DModelMemoryCache
Skip reading/writing 3D model memory caches.
defines the API calls for the manipulation of SG* classes
bool IsWrlExtension(const wxString &aFilename)
True iff aFilename ends in .wrl or .wrz (case-insensitive).
SGLIB_API SGNODE * ReadCache(const char *aFileName, void *aPluginMgr, bool(*aTagCheck)(const char *, void *))
Read a binary cache file and creates an SGNODE tree.
Definition ifsg_api.cpp:221
SGLIB_API bool WriteCache(const char *aFileName, bool overwrite, SGNODE *aNode, const char *aPluginInfo)
Write the SGNODE tree to a binary cache file.
Definition ifsg_api.cpp:157
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Delete the given SG* class node.
Definition ifsg_api.cpp:149
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Create an S3DMODEL representation of aNode (raw data, no transforms).
Definition ifsg_api.cpp:338
SGLIB_API void Destroy3DModel(S3DMODEL **aModel)
Free memory used by an S3DMODEL structure and sets the pointer to the structure to NULL.
Definition ifsg_api.cpp:403
PGM_BASE & Pgm()
The global program "get" accessor.
see class PGM_BASE
A storage class for 128-bit hash value.
Definition hash_128.h:36
Store the a model based on meshes and materials.
Definition c3dmodel.h:95
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:39