99#include " buffer/InterleavedBuffer.h"
1010#include " io/FileData.h"
1111#include " io/Data.h"
12+ #include " pool/ModelPool.h"
1213#include " thread/ResourceProgress.h"
1314#include " thread/ThreadPoolManager.h"
1415
@@ -600,14 +601,14 @@ std::string MeshSystem::getAsyncModelLoadScenePrefix(const Scene* scene){
600601 return key.str ();
601602}
602603
603- std::string MeshSystem::getAsyncModelLoadKey (const Scene* scene, Entity entity, const std::string& filename){
604+ std::string MeshSystem::getAsyncModelLoadKey (const Scene* scene, const std::string& filename){
604605 std::ostringstream key;
605- key << getAsyncModelLoadScenePrefix (scene) << entity << ' | ' << filename;
606+ key << getAsyncModelLoadScenePrefix (scene) << getModelFilenameKey ( filename) ;
606607 return key.str ();
607608}
608609
609- std::string MeshSystem::getAsyncModelLoadKey (Entity entity, const std::string& filename) const {
610- return getAsyncModelLoadKey (scene, entity, filename);
610+ std::string MeshSystem::getAsyncModelLoadKey (const std::string& filename) const {
611+ return getAsyncModelLoadKey (scene, filename);
611612}
612613
613614bool MeshSystem::hasPendingAsyncModelLoads () const {
@@ -656,13 +657,15 @@ void MeshSystem::cancelAllAsyncModelLoads(){
656657}
657658
658659bool MeshSystem::isAsyncModelLoadPending (Entity entity, const std::string& filename) const {
659- const std::string key = getAsyncModelLoadKey (entity, filename);
660+ (void )entity;
661+ const std::string key = getAsyncModelLoadKey (filename);
660662 std::lock_guard<std::mutex> lock (asyncModelMutex);
661663 return pendingModelLoads.find (key) != pendingModelLoads.end ();
662664}
663665
664666void MeshSystem::cancelAsyncModelLoad (Entity entity, const std::string& filename){
665- const std::string key = getAsyncModelLoadKey (entity, filename);
667+ (void )entity;
668+ const std::string key = getAsyncModelLoadKey (filename);
666669 const uint64_t buildId = std::hash<std::string>{}(key);
667670 bool erased = false ;
668671 {
@@ -715,8 +718,8 @@ std::shared_ptr<MeshSystem::AsyncModelLoadResult> MeshSystem::loadModelFileOnWor
715718 return result;
716719}
717720
718- std::shared_ptr<MeshSystem::AsyncModelLoadResult> MeshSystem::pollOrStartAsyncModelLoad (Entity entity, const std::string& filename, bool obj){
719- const std::string key = getAsyncModelLoadKey (entity, filename);
721+ std::shared_ptr<MeshSystem::AsyncModelLoadResult> MeshSystem::pollOrStartAsyncModelLoad (const std::string& filename, bool obj){
722+ const std::string key = getAsyncModelLoadKey (filename);
720723 const uint64_t buildId = std::hash<std::string>{}(key);
721724
722725 std::shared_future<std::shared_ptr<AsyncModelLoadResult>> future;
@@ -2200,9 +2203,16 @@ void MeshSystem::createTorus(MeshComponent& mesh, float radius, float ringRadius
22002203}
22012204
22022205bool MeshSystem::loadGLTF (Entity entity, const std::string filename, bool asyncLoad, bool skipEntities, bool changeRootTransform){
2206+ const std::string poolKey = getModelFilenameKey (filename);
2207+
2208+ // If parsed data is already cached, skip the async background-thread entirely.
2209+ if (asyncLoad && ModelPool::get (poolKey)){
2210+ asyncLoad = false ;
2211+ }
2212+
22032213 std::shared_ptr<AsyncModelLoadResult> asyncResult;
22042214 if (asyncLoad){
2205- asyncResult = pollOrStartAsyncModelLoad (entity, filename, false );
2215+ asyncResult = pollOrStartAsyncModelLoad (filename, false );
22062216 if (!asyncResult || !asyncResult->success || !asyncResult->gltfModel ){
22072217 return false ;
22082218 }
@@ -2216,14 +2226,11 @@ bool MeshSystem::loadGLTF(Entity entity, const std::string filename, bool asyncL
22162226
22172227 model.filename = filename;
22182228
2219- uint64_t buildId = asyncLoad ? std::hash<std::string>{}(getAsyncModelLoadKey (entity, filename)) : 0 ;
2229+ uint64_t buildId = asyncLoad ? std::hash<std::string>{}(getAsyncModelLoadKey (filename)) : 0 ;
22202230
22212231 mesh.submeshes [0 ].primitiveType = PrimitiveType::TRIANGLES;
22222232 mesh.numSubmeshes = 1 ;
22232233
2224- if (!model.gltfModel )
2225- model.gltfModel = new tinygltf::Model ();
2226-
22272234 std::string err;
22282235 std::string warn;
22292236
@@ -2235,32 +2242,50 @@ bool MeshSystem::loadGLTF(Entity entity, const std::string filename, bool asyncL
22352242 bool res = false ;
22362243
22372244 if (asyncLoad){
2238- *model.gltfModel = std::move (*asyncResult->gltfModel );
2245+ // Async loader already produced a parsed model; reuse it (and cache it).
2246+ auto cached = ModelPool::get (poolKey);
2247+ if (cached){
2248+ model.gltfModel = cached;
2249+ }else {
2250+ model.gltfModel = asyncResult->gltfModel ;
2251+ ModelPool::add (poolKey, model.gltfModel );
2252+ }
22392253 res = true ;
22402254 }else {
2241- tinygltf::TinyGLTF loader;
2242- loader.SetFsCallbacks ({&fileExists, &tinygltf::ExpandFilePath, &readWholeFile, &tinygltf::WriteWholeFile, &getFileSizeInBytes});
2255+ // Try cache before hitting disk.
2256+ auto cached = ModelPool::get (poolKey);
2257+ if (cached){
2258+ model.gltfModel = cached;
2259+ res = true ;
2260+ }else {
2261+ model.gltfModel = std::make_shared<tinygltf::Model>();
22432262
2244- std::string ext = FileData::getFilePathExtension (filename);
2263+ tinygltf::TinyGLTF loader;
2264+ loader.SetFsCallbacks ({&fileExists, &tinygltf::ExpandFilePath, &readWholeFile, &tinygltf::WriteWholeFile, &getFileSizeInBytes});
22452265
2246- if (ext.compare (" glb" ) == 0 ) {
2247- res = loader.LoadBinaryFromFile (model.gltfModel , &err, &warn, filename); // for binary glTF(.glb)
2248- }else {
2249- res = loader.LoadASCIIFromFile (model.gltfModel , &err, &warn, filename);
2250- }
2266+ std::string ext = FileData::getFilePathExtension (filename);
22512267
2252- if (!warn.empty ()) {
2253- Log::warn (" Loading GLTF model (%s): %s" , filename.c_str (), warn.c_str ());
2254- }
2268+ if (ext.compare (" glb" ) == 0 ) {
2269+ res = loader.LoadBinaryFromFile (model.gltfModel .get (), &err, &warn, filename); // for binary glTF(.glb)
2270+ }else {
2271+ res = loader.LoadASCIIFromFile (model.gltfModel .get (), &err, &warn, filename);
2272+ }
22552273
2256- if (!err.empty ()) {
2257- Log::error (" Can't load GLTF model (%s): %s" , filename.c_str (), err.c_str ());
2258- return false ;
2259- }
2274+ if (!warn.empty ()) {
2275+ Log::warn (" Loading GLTF model (%s): %s" , filename.c_str (), warn.c_str ());
2276+ }
22602277
2261- if (!res) {
2262- Log::verbose (" Failed to load glTF: %s" , filename.c_str ());
2263- return false ;
2278+ if (!err.empty ()) {
2279+ Log::error (" Can't load GLTF model (%s): %s" , filename.c_str (), err.c_str ());
2280+ return false ;
2281+ }
2282+
2283+ if (!res) {
2284+ Log::verbose (" Failed to load glTF: %s" , filename.c_str ());
2285+ return false ;
2286+ }
2287+
2288+ ModelPool::add (poolKey, model.gltfModel );
22642289 }
22652290 }
22662291
@@ -3016,7 +3041,7 @@ bool MeshSystem::loadGLTF(Entity entity, const std::string filename, bool asyncL
30163041bool MeshSystem::loadOBJ (Entity entity, const std::string filename, bool asyncLoad){
30173042 std::shared_ptr<AsyncModelLoadResult> asyncResult;
30183043 if (asyncLoad){
3019- asyncResult = pollOrStartAsyncModelLoad (entity, filename, true );
3044+ asyncResult = pollOrStartAsyncModelLoad (filename, true );
30203045 if (!asyncResult || !asyncResult->success ){
30213046 return false ;
30223047 }
@@ -3030,7 +3055,7 @@ bool MeshSystem::loadOBJ(Entity entity, const std::string filename, bool asyncLo
30303055
30313056 model.filename = filename;
30323057
3033- uint64_t buildId = asyncLoad ? std::hash<std::string>{}(getAsyncModelLoadKey (entity, filename)) : 0 ;
3058+ uint64_t buildId = asyncLoad ? std::hash<std::string>{}(getAsyncModelLoadKey (filename)) : 0 ;
30343059
30353060 mesh.submeshes [0 ].primitiveType = PrimitiveType::TRIANGLES;
30363061 mesh.numSubmeshes = 1 ;
@@ -3299,8 +3324,11 @@ void MeshSystem::clearAnimationMapping(ModelComponent& model){
32993324
33003325void MeshSystem::destroyModel (ModelComponent& model){
33013326 if (model.gltfModel ){
3302- delete model.gltfModel ;
3303- model.gltfModel = NULL ;
3327+ model.gltfModel .reset ();
3328+ }
3329+
3330+ if (!model.loadedFilename .empty ()){
3331+ ModelPool::remove (model.loadedFilename );
33043332 }
33053333
33063334 model.morphNameMapping .clear ();
0 commit comments