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