Add model-loader to abstract gltf2-loader and dli-loader
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / resource-bundle.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // FILE HEADER
19 #include <dali-scene3d/public-api/loader/resource-bundle.h>
20
21 // EXTERNAL
22 #include <dali-toolkit/public-api/image-loader/sync-image-loader.h>
23 #include <dali/public-api/rendering/sampler.h>
24 #include <cstring>
25 #include <fstream>
26 #include <istream>
27
28 namespace Dali
29 {
30 using namespace Toolkit;
31
32 namespace Scene3D
33 {
34 namespace Loader
35 {
36 namespace
37 {
38 const char* const RESOURCE_TYPE_NAMES[] = {
39   "Environment",
40   "Shader",
41   "Mesh",
42   "Material",
43 };
44
45 } // namespace
46
47 const char* GetResourceTypeName(ResourceType::Value type)
48 {
49   return RESOURCE_TYPE_NAMES[static_cast<int>(type)];
50 }
51
52 ResourceBundle::ResourceBundle()
53 : mRawResourcesLoading(false),
54   mResourcesGenerating(false),
55   mRawResourcesLoaded(false),
56   mResourcesGenerated(false)
57 {
58 };
59
60 ResourceRefCounts ResourceBundle::CreateRefCounter() const
61 {
62   ResourceRefCounts refCounts(4);
63   refCounts[ResourceType::Environment].Resize(mEnvironmentMaps.size(), 0u);
64   refCounts[ResourceType::Shader].Resize(mShaders.size(), 0u);
65   refCounts[ResourceType::Mesh].Resize(mMeshes.size(), 0u);
66   refCounts[ResourceType::Material].Resize(mMaterials.size(), 0u);
67   return refCounts;
68 }
69
70 void ResourceBundle::CountEnvironmentReferences()
71 {
72   auto& environmentRefCounts = mReferenceCounts[ResourceType::Environment];
73
74   const auto& materialRefs = mReferenceCounts[ResourceType::Material];
75   for(uint32_t i = 0, iEnd = materialRefs.Size(); i != iEnd; ++i)
76   {
77     if(materialRefs[i] > 0)
78     {
79       ++environmentRefCounts[mMaterials[i].first.mEnvironmentIdx];
80     }
81   }
82 }
83
84 void ResourceBundle::LoadResources(PathProvider pathProvider, Options::Type options)
85 {
86   mRawResourcesLoading = true;
87   mResourcesGenerating = true;
88
89   const auto kForceLoad  = MaskMatch(options, Options::ForceReload);
90   const auto kKeepUnused = MaskMatch(options, Options::KeepUnused);
91
92   const auto& refCountEnvMaps  = mReferenceCounts[ResourceType::Environment];
93   auto        environmentsPath = pathProvider(ResourceType::Environment);
94   for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i)
95   {
96     auto  refCount = refCountEnvMaps[i];
97     auto& iEnvMap  = mEnvironmentMaps[i];
98     if(refCount > 0 && (kForceLoad || !iEnvMap.second.IsLoaded()))
99     {
100       auto raw       = iEnvMap.first.LoadRaw(environmentsPath);
101       iEnvMap.second = iEnvMap.first.Load(std::move(raw));
102     }
103     else if(!kKeepUnused && refCount == 0 && iEnvMap.second.IsLoaded())
104     {
105       iEnvMap.second.mDiffuse  = Texture();
106       iEnvMap.second.mSpecular = Texture();
107     }
108   }
109
110   const auto& refCountShaders = mReferenceCounts[ResourceType::Shader];
111   auto        shadersPath     = pathProvider(ResourceType::Shader);
112   for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
113   {
114     auto  refCount = refCountShaders[i];
115     auto& iShader  = mShaders[i];
116     if(refCount > 0 && (kForceLoad || !iShader.second))
117     {
118       auto raw       = iShader.first.LoadRaw(shadersPath);
119       iShader.second = iShader.first.Load(std::move(raw));
120     }
121     else if(!kKeepUnused && refCount == 0 && iShader.second)
122     {
123       iShader.second = Shader();
124     }
125   }
126
127   const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh];
128   auto        modelsPath     = pathProvider(ResourceType::Mesh);
129   for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i)
130   {
131     auto  refCount = refCountMeshes[i];
132     auto& iMesh    = mMeshes[i];
133     if(refCount > 0 && (kForceLoad || !iMesh.second.geometry))
134     {
135       auto raw     = iMesh.first.LoadRaw(modelsPath, mBuffers);
136       iMesh.second = iMesh.first.Load(std::move(raw));
137     }
138     else if(!kKeepUnused && refCount == 0 && iMesh.second.geometry)
139     {
140       iMesh.second.geometry = Geometry();
141     }
142   }
143
144   const auto& refCountMaterials = mReferenceCounts[ResourceType::Material];
145   auto        imagesPath        = pathProvider(ResourceType::Material);
146   for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i)
147   {
148     auto  refCount  = refCountMaterials[i];
149     auto& iMaterial = mMaterials[i];
150     if(refCount > 0 && (kForceLoad || !iMaterial.second))
151     {
152       auto raw         = iMaterial.first.LoadRaw(imagesPath);
153       iMaterial.second = iMaterial.first.Load(mEnvironmentMaps, std::move(raw));
154     }
155     else if(!kKeepUnused && refCount == 0 && iMaterial.second)
156     {
157       iMaterial.second = TextureSet();
158     }
159   }
160
161   mRawResourcesLoading = false;
162   mResourcesGenerating = false;
163
164   mRawResourcesLoaded = true;
165   mResourcesGenerated = true;
166 }
167
168 void ResourceBundle::LoadRawResources(PathProvider pathProvider, Options::Type options)
169 {
170   const auto kForceLoad = MaskMatch(options, Options::ForceReload);
171
172   if(kForceLoad || (!mRawResourcesLoaded && !mRawResourcesLoading))
173   {
174     mRawResourcesLoading = true;
175
176     const auto& refCountEnvMaps  = mReferenceCounts[ResourceType::Environment];
177     auto        environmentsPath = pathProvider(ResourceType::Environment);
178     for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i)
179     {
180       auto  refCount = refCountEnvMaps[i];
181       auto& iEnvMap  = mEnvironmentMaps[i];
182       if(refCount > 0 && (kForceLoad || (!iEnvMap.first.mRawData && !iEnvMap.second.IsLoaded())))
183       {
184         iEnvMap.first.mRawData = std::make_shared<EnvironmentDefinition::RawData>(iEnvMap.first.LoadRaw(environmentsPath));
185       }
186     }
187
188     const auto& refCountShaders = mReferenceCounts[ResourceType::Shader];
189     auto        shadersPath     = pathProvider(ResourceType::Shader);
190     for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
191     {
192       auto  refCount = refCountShaders[i];
193       auto& iShader  = mShaders[i];
194       if(refCount > 0 && (kForceLoad || !iShader.second))
195       {
196         iShader.first.mRawData = std::make_shared<ShaderDefinition::RawData>(iShader.first.LoadRaw(shadersPath));
197       }
198     }
199
200     const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh];
201     auto        modelsPath     = pathProvider(ResourceType::Mesh);
202     for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i)
203     {
204       auto  refCount = refCountMeshes[i];
205       auto& iMesh    = mMeshes[i];
206       if(refCount > 0 && (kForceLoad || (!iMesh.first.mRawData && !iMesh.second.geometry)))
207       {
208         iMesh.first.mRawData = std::make_shared<MeshDefinition::RawData>(iMesh.first.LoadRaw(modelsPath, mBuffers));
209       }
210     }
211
212     const auto& refCountMaterials = mReferenceCounts[ResourceType::Material];
213     auto        imagesPath        = pathProvider(ResourceType::Material);
214     for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i)
215     {
216       auto  refCount  = refCountMaterials[i];
217       auto& iMaterial = mMaterials[i];
218       if(refCount > 0 && (kForceLoad || (!iMaterial.first.mRawData && !iMaterial.second)))
219       {
220         iMaterial.first.mRawData = std::make_shared<MaterialDefinition::RawData>(iMaterial.first.LoadRaw(imagesPath));
221       }
222     }
223
224     mRawResourcesLoading = false;
225     mRawResourcesLoaded  = true;
226   }
227 }
228
229 void ResourceBundle::GenerateResources(Options::Type options)
230 {
231   const auto kForceLoad = MaskMatch(options, Options::ForceReload);
232
233   if(mRawResourcesLoaded)
234   {
235     if(kForceLoad || (!mResourcesGenerated && !mResourcesGenerating))
236     {
237       mResourcesGenerating = true;
238
239       const auto& refCountEnvMaps = mReferenceCounts[ResourceType::Environment];
240       for(uint32_t i = 0, iEnd = refCountEnvMaps.Size(); i != iEnd; ++i)
241       {
242         auto  refCount = refCountEnvMaps[i];
243         auto& iEnvMap  = mEnvironmentMaps[i];
244         if(refCount > 0 && (kForceLoad || !iEnvMap.second.IsLoaded()))
245         {
246           if(iEnvMap.first.mRawData)
247           {
248             iEnvMap.second = iEnvMap.first.Load(std::move(*(iEnvMap.first.mRawData)));
249           }
250           else
251           {
252             iEnvMap.second.mDiffuse  = Texture();
253             iEnvMap.second.mSpecular = Texture();
254           }
255         }
256       }
257
258       const auto& refCountShaders = mReferenceCounts[ResourceType::Shader];
259       for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
260       {
261         auto  refCount = refCountShaders[i];
262         auto& iShader  = mShaders[i];
263         if(refCount > 0 && (kForceLoad || !iShader.second))
264         {
265           if(iShader.first.mRawData)
266           {
267             iShader.second = iShader.first.Load(std::move(*(iShader.first.mRawData)));
268           }
269           else
270           {
271             iShader.second = Shader();
272           }
273         }
274       }
275
276       const auto& refCountMeshes = mReferenceCounts[ResourceType::Mesh];
277       for(uint32_t i = 0, iEnd = refCountMeshes.Size(); i != iEnd; ++i)
278       {
279         auto  refCount = refCountMeshes[i];
280         auto& iMesh    = mMeshes[i];
281         if(refCount > 0 && (kForceLoad || !iMesh.second.geometry))
282         {
283           if(iMesh.first.mRawData)
284           {
285             iMesh.second = iMesh.first.Load(std::move(*(iMesh.first.mRawData)));
286           }
287           else
288           {
289             iMesh.second.geometry = Geometry();
290           }
291         }
292       }
293
294       const auto& refCountMaterials = mReferenceCounts[ResourceType::Material];
295       for(uint32_t i = 0, iEnd = refCountMaterials.Size(); i != iEnd; ++i)
296       {
297         auto  refCount  = refCountMaterials[i];
298         auto& iMaterial = mMaterials[i];
299         if(refCount > 0 && (kForceLoad || !iMaterial.second))
300         {
301           if(iMaterial.first.mRawData)
302           {
303             iMaterial.second = iMaterial.first.Load(mEnvironmentMaps, std::move(*(iMaterial.first.mRawData)));
304           }
305           else
306           {
307             iMaterial.second = TextureSet();
308           }
309         }
310       }
311
312       mResourcesGenerating = false;
313       mResourcesGenerated  = true;
314     }
315     else if(mResourcesGenerated && !mResourcesGenerating)
316     {
317       mResourcesGenerating = true;
318
319       const auto& refCountShaders = mReferenceCounts[ResourceType::Shader];
320       for(uint32_t i = 0, iEnd = refCountShaders.Size(); i != iEnd; ++i)
321       {
322         auto  refCount = refCountShaders[i];
323         auto& iShader  = mShaders[i];
324
325         // Always regenerating the Shader objects as they can't be shared between multiple models.
326         if(refCount > 0 || kForceLoad)
327         {
328           if(iShader.first.mRawData)
329           {
330             iShader.second = iShader.first.Load(std::move(*(iShader.first.mRawData)));
331           }
332           else
333           {
334             iShader.second = Shader();
335           }
336         }
337       }
338
339       mResourcesGenerating = false;
340     }
341   }
342 }
343
344 } // namespace Loader
345 } // namespace Scene3D
346 } // namespace Dali