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