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
84 S3D_CACHE_ENTRY( const S3D_CACHE_ENTRY& source ) = delete;
85 S3D_CACHE_ENTRY& operator=( const S3D_CACHE_ENTRY& source ) = delete;
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,
141 S3D_CACHE_ENTRY** aCachePtr,
142 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack,
143 S3DMODEL** aRenderModel )
144{
145 if( aCachePtr )
146 *aCachePtr = nullptr;
147
148 if( aRenderModel )
149 *aRenderModel = nullptr;
150
151 wxString full3Dpath = m_FNResolver->ResolvePath( aModelFile, aBasePath, std::move( aEmbeddedFilesStack ) );
152
153 // In CLI / scripting contexts, transparently substitute a matching
154 // STEP model for a missing WRL reference so renders and exports
155 // don't silently lose geometry. The GUI handles this via the
156 // DIALOG_MIGRATE_3D_MODELS load-time auto-migration, so we skip the
157 // fallback there to avoid masking user-visible "missing" state.
158 if( full3Dpath.empty() && !Pgm().IsGUI() && MODEL_SUBSTITUTION::IsWrlExtension( aModelFile ) )
159 {
160 std::lock_guard<std::mutex> catLock( m_substCatalogMutex );
161
163 {
164 const wxString projectPath =
165 m_project ? m_project->GetProjectPath() : wxString();
166 m_substCatalog.Build( projectPath, m_FNResolver );
167 m_substCatalogBuilt = true;
168 }
169
170 const wxString subst = m_substCatalog.FindMatchFor( aModelFile );
171
172 if( !subst.IsEmpty() )
173 {
174 wxLogTrace( MASK_3D_CACHE,
175 wxT( "%s:%s:%d\n * [3D model] substituting '%s' -> '%s'\n" ),
176 __FILE__, __FUNCTION__, __LINE__, aModelFile, subst );
177 full3Dpath = subst;
178 }
179 }
180
181 if( full3Dpath.empty() )
182 {
183 // the model cannot be found; we cannot proceed
184 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [3D model] could not find model '%s'\n" ),
185 __FILE__, __FUNCTION__, __LINE__, aModelFile );
186 return nullptr;
187 }
188
189 // check cache if file is already loaded
190 std::lock_guard<std::mutex> lock( mutex3D_cache );
191
192 auto finishEntry = [&]( S3D_CACHE_ENTRY* ep ) -> SCENEGRAPH*
193 {
194 if( !ep )
195 return nullptr;
196
197 if( aCachePtr )
198 *aCachePtr = ep;
199
200 // Lazy renderData conversion under the same lock that owns the entry.
201 if( aRenderModel )
202 {
203 if( !ep->renderData && ep->sceneData )
204 ep->renderData = S3D::GetModel( ep->sceneData );
205
206 *aRenderModel = ep->renderData;
207 }
208
209 return ep->sceneData;
210 };
211
212 std::map< wxString, S3D_CACHE_ENTRY*, rsort_wxString >::iterator mi;
213 mi = m_CacheMap.find( full3Dpath );
214
215 if( mi != m_CacheMap.end() )
216 {
217 wxFileName fname( full3Dpath );
218
219 if( fname.FileExists() ) // Only check if file exists. If not, it will
220 { // use the same model in cache.
222 wxDateTime fmdate = fname.GetModificationTime();
223
224 if( fmdate != mi->second->modTime )
225 {
226 HASH_128 hashSum;
227 getHash( full3Dpath, hashSum );
228 mi->second->modTime = fmdate;
229
230 if( hashSum != mi->second->m_hash )
231 {
232 mi->second->SetHash( hashSum );
233 reload = true;
234 }
235 }
236
237 if( reload )
238 {
239 if( nullptr != mi->second->sceneData )
240 {
241 S3D::DestroyNode( mi->second->sceneData );
242 mi->second->sceneData = nullptr;
243 }
244
245 if( nullptr != mi->second->renderData )
246 S3D::Destroy3DModel( &mi->second->renderData );
247
248 mi->second->sceneData = m_Plugins->Load3DModel( full3Dpath,
249 mi->second->pluginInfo );
250 }
251 }
252
253 return finishEntry( mi->second );
254 }
255
256 // a cache item does not exist; search the Filename->Cachename map
257 S3D_CACHE_ENTRY* ep = nullptr;
258 checkCache( full3Dpath, &ep );
259 return finishEntry( ep );
260}
261
262
263SCENEGRAPH* S3D_CACHE::Load( const wxString& aModelFile, const wxString& aBasePath,
264 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
265{
266 return load( aModelFile, aBasePath, nullptr, std::move( aEmbeddedFilesStack ) );
267}
268
269
270SCENEGRAPH* S3D_CACHE::checkCache( const wxString& aFileName, S3D_CACHE_ENTRY** aCachePtr )
271{
272 if( aCachePtr )
273 *aCachePtr = nullptr;
274
275 HASH_128 hashSum;
277 m_CacheList.push_back( ep );
278 wxFileName fname( aFileName );
279 ep->modTime = fname.GetModificationTime();
280
281 if( !getHash( aFileName, hashSum ) || m_CacheDir.empty() )
282 {
283 // just in case we can't get a hash digest (for example, on access issues)
284 // or we do not have a configured cache file directory, we create an
285 // entry to prevent further attempts at loading the file
286
287 if( m_CacheMap.emplace( aFileName, ep ).second == false )
288 {
289 wxLogTrace( MASK_3D_CACHE,
290 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
291 __FILE__, __FUNCTION__, __LINE__, aFileName );
292
293 m_CacheList.pop_back();
294 delete ep;
295 }
296 else
297 {
298 if( aCachePtr )
299 *aCachePtr = ep;
300 }
301
302 return nullptr;
303 }
304
305 if( m_CacheMap.emplace( aFileName, ep ).second == false )
306 {
307 wxLogTrace( MASK_3D_CACHE,
308 wxT( "%s:%s:%d\n * [BUG] duplicate entry in map file; key = '%s'" ),
309 __FILE__, __FUNCTION__, __LINE__, aFileName );
310
311 m_CacheList.pop_back();
312 delete ep;
313 return nullptr;
314 }
315
316 if( aCachePtr )
317 *aCachePtr = ep;
318
319 ep->SetHash( hashSum );
320
321 wxString bname = ep->GetCacheBaseName();
322 wxString cachename = m_CacheDir + bname + wxT( ".3dc" );
323
324 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && wxFileName::FileExists( cachename )
325 && loadCacheData( ep ) )
326 return ep->sceneData;
327
328 ep->sceneData = m_Plugins->Load3DModel( aFileName, ep->pluginInfo );
329
330 if( !ADVANCED_CFG::GetCfg().m_Skip3DModelFileCache && nullptr != ep->sceneData )
331 saveCacheData( ep );
332
333 return ep->sceneData;
334}
335
336
337bool S3D_CACHE::getHash( const wxString& aFileName, HASH_128& aHash )
338{
339 if( aFileName.empty() )
340 {
341 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * [BUG] empty filename" ),
342 __FILE__, __FUNCTION__, __LINE__ );
343
344 return false;
345 }
346
347#ifdef _WIN32
348 FILE* fp = _wfopen( aFileName.wc_str(), L"rb" );
349#else
350 FILE* fp = fopen( aFileName.ToUTF8(), "rb" );
351#endif
352
353 if( nullptr == fp )
354 return false;
355
356 MMH3_HASH dblock( 0xA1B2C3D4 );
357 std::vector<char> block( 4096 );
358 size_t bsize = 0;
359
360 while( ( bsize = fread( block.data(), 1, 4096, fp ) ) > 0 )
361 dblock.add( block );
362
363 fclose( fp );
364 aHash = dblock.digest();
365 return true;
366}
367
368
370{
371 wxString bname = aCacheItem->GetCacheBaseName();
372
373 if( bname.empty() )
374 {
375 wxLogTrace( MASK_3D_CACHE,
376 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
377
378 return false;
379 }
380
381 if( m_CacheDir.empty() )
382 {
383 wxLogTrace( MASK_3D_CACHE,
384 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
385
386 return false;
387 }
388
389 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
390
391 if( !wxFileName::FileExists( fname ) )
392 {
393 wxLogTrace( MASK_3D_CACHE, wxT( " * [3D model] cannot open file '%s'" ), fname.GetData() );
394 return false;
395 }
396
397 if( nullptr != aCacheItem->sceneData )
398 S3D::DestroyNode( (SGNODE*) aCacheItem->sceneData );
399
400 aCacheItem->sceneData = (SCENEGRAPH*)S3D::ReadCache( fname.ToUTF8(), m_Plugins, checkTag );
401
402 if( nullptr == aCacheItem->sceneData )
403 return false;
404
405 return true;
406}
407
408
410{
411 if( nullptr == aCacheItem )
412 {
413 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * NULL passed for aCacheItem" ),
414 __FILE__, __FUNCTION__, __LINE__ );
415
416 return false;
417 }
418
419 if( nullptr == aCacheItem->sceneData )
420 {
421 wxLogTrace( MASK_3D_CACHE, wxT( "%s:%s:%d\n * aCacheItem has no valid scene data" ),
422 __FILE__, __FUNCTION__, __LINE__ );
423
424 return false;
425 }
426
427 wxString bname = aCacheItem->GetCacheBaseName();
428
429 if( bname.empty() )
430 {
431 wxLogTrace( MASK_3D_CACHE,
432 wxT( " * [3D model] cannot load cached model; no file hash available" ) );
433
434 return false;
435 }
436
437 if( m_CacheDir.empty() )
438 {
439 wxLogTrace( MASK_3D_CACHE,
440 wxT( " * [3D model] cannot load cached model; config directory unknown" ) );
441
442 return false;
443 }
444
445 wxString fname = m_CacheDir + bname + wxT( ".3dc" );
446
447 if( wxFileName::Exists( fname ) )
448 {
449 if( !wxFileName::FileExists( fname ) )
450 {
451 wxLogTrace( MASK_3D_CACHE,
452 wxT( " * [3D model] path exists but is not a regular file '%s'" ), fname );
453
454 return false;
455 }
456 }
457
458 return S3D::WriteCache( fname.ToUTF8(), true, (SGNODE*)aCacheItem->sceneData,
459 aCacheItem->pluginInfo.c_str() );
460}
461
462
463bool S3D_CACHE::Set3DConfigDir( const wxString& aConfigDir )
464{
465 if( !m_ConfigDir.empty() )
466 return false;
467
468 wxFileName cfgdir( ExpandEnvVarSubstitutions( aConfigDir, m_project ), wxEmptyString );
469
470 cfgdir.Normalize( FN_NORMALIZE_FLAGS );
471
472 if( !cfgdir.DirExists() )
473 {
474 cfgdir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
475
476 if( !cfgdir.DirExists() )
477 {
478 wxLogTrace( MASK_3D_CACHE,
479 wxT( "%s:%s:%d\n * failed to create 3D configuration directory '%s'" ),
480 __FILE__, __FUNCTION__, __LINE__, cfgdir.GetPath() );
481
482 return false;
483 }
484 }
485
486 m_ConfigDir = cfgdir.GetPath();
487
488 // inform the file resolver of the config directory
489 if( !m_FNResolver->Set3DConfigDir( m_ConfigDir ) )
490 {
491 wxLogTrace( MASK_3D_CACHE,
492 wxT( "%s:%s:%d\n * could not set 3D Config Directory on filename resolver\n"
493 " * config directory: '%s'" ),
494 __FILE__, __FUNCTION__, __LINE__, m_ConfigDir );
495 }
496
497 // 3D cache data must go to a user's cache directory;
498 // unfortunately wxWidgets doesn't seem to provide
499 // functions to retrieve such a directory.
500 //
501 // 1. OSX: ~/Library/Caches/kicad/3d/
502 // 2. Linux: ${XDG_CACHE_HOME}/kicad/3d ~/.cache/kicad/3d/
503 // 3. MSWin: AppData\Local\kicad\3d
504 wxFileName cacheDir;
505 cacheDir.AssignDir( PATHS::GetUserCachePath() );
506 cacheDir.AppendDir( wxT( "3d" ) );
507
508 if( !cacheDir.DirExists() )
509 {
510 cacheDir.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
511
512 if( !cacheDir.DirExists() )
513 {
514 wxLogTrace( MASK_3D_CACHE,
515 wxT( "%s:%s:%d\n * failed to create 3D cache directory '%s'" ),
516 __FILE__, __FUNCTION__, __LINE__, cacheDir.GetPath() );
517
518 return false;
519 }
520 }
521
522 m_CacheDir = cacheDir.GetPathWithSep();
523 return true;
524}
525
526
528{
529 m_project = aProject;
530
531 bool hasChanged = false;
532
533 if( m_FNResolver->SetProject( aProject, &hasChanged ) && hasChanged )
534 {
535 std::lock_guard<std::mutex> lock( mutex3D_cache );
536
537 m_CacheMap.clear();
538
539 std::list< S3D_CACHE_ENTRY* >::iterator sL = m_CacheList.begin();
540 std::list< S3D_CACHE_ENTRY* >::iterator eL = m_CacheList.end();
541
542 while( sL != eL )
543 {
544 delete *sL;
545 ++sL;
546 }
547
548 m_CacheList.clear();
549
550 return true;
551 }
552
553 return false;
554}
555
556
558{
559 m_FNResolver->SetProgramBase( aBase );
560}
561
562
564{
565 return m_FNResolver;
566}
567
568
569std::list< wxString > const* S3D_CACHE::GetFileFilters() const
570{
571 return m_Plugins->GetFileFilters();
572}
573
574
575void S3D_CACHE::FlushCache( bool closePlugins )
576{
577 std::lock_guard<std::mutex> lock( mutex3D_cache );
578
579 std::list< S3D_CACHE_ENTRY* >::iterator sCL = m_CacheList.begin();
580 std::list< S3D_CACHE_ENTRY* >::iterator eCL = m_CacheList.end();
581
582 while( sCL != eCL )
583 {
584 delete *sCL;
585 ++sCL;
586 }
587
588 m_CacheList.clear();
589 m_CacheMap.clear();
590
591 if( closePlugins )
592 ClosePlugins();
593}
594
595
597{
598 if( m_Plugins )
599 m_Plugins->ClosePlugins();
600}
601
602
603S3DMODEL* S3D_CACHE::GetModel( const wxString& aModelFileName, const wxString& aBasePath,
604 std::vector<const EMBEDDED_FILES*> aEmbeddedFilesStack )
605{
606 S3DMODEL* mp = nullptr;
607
608 if( !load( aModelFileName, aBasePath, nullptr, std::move( aEmbeddedFilesStack ), &mp ) )
609 return nullptr;
610
611 return mp;
612}
613
614void S3D_CACHE::CleanCacheDir( int aNumDaysOld )
615{
616 wxDir dir;
617 wxString fileSpec = wxT( "*.3dc" );
618 wxArrayString fileList; // Holds list of ".3dc" files found in cache directory
619 size_t numFilesFound = 0;
620
621 wxFileName thisFile;
622 wxDateTime lastAccess, thresholdDate;
623 wxDateSpan durationInDays;
624
625 // Calc the threshold date above which we delete cache files
626 durationInDays.SetDays( aNumDaysOld );
627 thresholdDate = wxDateTime::Now() - durationInDays;
628
629 // If the cache directory can be found and opened, then we'll try and clean it up
630 if( dir.Open( m_CacheDir ) )
631 {
632 thisFile.SetPath( m_CacheDir ); // Set the base path to the cache folder
633
634 // Get a list of all the ".3dc" files in the cache directory
635 numFilesFound = dir.GetAllFiles( m_CacheDir, &fileList, fileSpec );
636
637 for( unsigned int i = 0; i < numFilesFound; i++ )
638 {
639 // Completes path to specific file so we can get its "last access" date
640 thisFile.SetFullName( fileList[i] );
641
642 // Only get "last access" time to compare against. Don't need the other 2 timestamps.
643 if( thisFile.GetTimes( &lastAccess, nullptr, nullptr ) )
644 {
645 if( lastAccess.IsEarlierThan( thresholdDate ) )
646 {
647 // This file is older than the threshold so delete it
648 wxRemoveFile( thisFile.GetFullPath() );
649 }
650 }
651 }
652 }
653}
#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:557
wxString m_CacheDir
Definition 3d_cache.h:191
bool loadCacheData(S3D_CACHE_ENTRY *aCacheItem)
Definition 3d_cache.cpp:369
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:575
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:463
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:603
SCENEGRAPH * checkCache(const wxString &aFileName, S3D_CACHE_ENTRY **aCachePtr=nullptr)
Find or create cache entry for file name.
Definition 3d_cache.cpp:270
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:409
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:569
FILENAME_RESOLVER * GetResolver() noexcept
Definition 3d_cache.cpp:563
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:527
void CleanCacheDir(int aNumDaysOld)
Delete up old cache files in cache directory.
Definition 3d_cache.cpp:614
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:263
void ClosePlugins()
Unload plugins to free memory.
Definition 3d_cache.cpp:596
bool getHash(const wxString &aFileName, HASH_128 &aHash)
Calculate the SHA1 hash of the given file.
Definition 3d_cache.cpp:337
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.
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:217
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:153
SGLIB_API void DestroyNode(SGNODE *aNode) noexcept
Delete the given SG* class node.
Definition ifsg_api.cpp:145
SGLIB_API S3DMODEL * GetModel(SCENEGRAPH *aNode)
Create an S3DMODEL representation of aNode (raw data, no transforms).
Definition ifsg_api.cpp:334
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:399
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