1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef CORE__GLTF__GLTF2_IMPORTER_H 17 #define CORE__GLTF__GLTF2_IMPORTER_H 18 19 #include <atomic> 20 #include <condition_variable> 21 #include <mutex> 22 23 #include <3d/gltf/gltf.h> 24 #include <3d/loaders/intf_scene_loader.h> 25 #include <3d/util/intf_mesh_builder.h> 26 #include <base/containers/string.h> 27 #include <base/containers/unique_ptr.h> 28 #include <base/containers/vector.h> 29 #include <core/ecs/entity_reference.h> 30 #include <core/ecs/intf_ecs.h> 31 #include <core/namespace.h> 32 #include <core/threading/intf_thread_pool.h> 33 34 BASE_BEGIN_NAMESPACE() 35 template<class Key, class T> 36 class unordered_map; 37 BASE_END_NAMESPACE() 38 39 CORE_BEGIN_NAMESPACE() 40 class IEngine; 41 class IImageLoaderManager; 42 class IPerformanceDataManager; 43 CORE_END_NAMESPACE() 44 45 RENDER_BEGIN_NAMESPACE() 46 class IDevice; 47 class IGpuResourceManager; 48 class IRenderContext; 49 class IShaderManager; 50 RENDER_END_NAMESPACE() 51 52 CORE3D_BEGIN_NAMESPACE() 53 class IGraphicsContext; 54 class IRenderHandleComponentManager; 55 class IMaterialComponentManager; 56 class IMeshComponentManager; 57 class INameComponentManager; 58 class IUriComponentManager; 59 class IAnimationInputComponentManager; 60 class IAnimationOutputComponentManager; 61 62 namespace GLTF2 { 63 class Data; 64 struct Accessor; 65 struct AnimationTrack; 66 enum class ImportPhase { 67 BUFFERS = 0, 68 SAMPLERS, 69 IMAGES, 70 TEXTURES, 71 MATERIALS, 72 ANIMATION_SAMPLERS, 73 ANIMATIONS, 74 SKINS, 75 MESHES, 76 FINISHED 77 }; 78 79 // A class that executes GLTF load and import operation over multiple frames. 80 class GLTF2Importer final : public IGLTF2Importer { 81 public: 82 GLTF2Importer(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs); 83 GLTF2Importer(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs, 84 CORE_NS::IThreadPool& pool); 85 ~GLTF2Importer() override; 86 87 void ImportGLTF(const IGLTFData& data, GltfResourceImportFlags flags) override; 88 void ImportGLTFAsync(const IGLTFData& data, GltfResourceImportFlags flags, Listener* listener) override; 89 bool Execute(uint32_t timeBudget) override; 90 91 void Cancel() override; 92 bool IsCompleted() const override; 93 94 const GLTFImportResult& GetResult() const override; 95 96 const GltfMeshData& GetMeshData() const override; 97 98 struct DefaultMaterialShaderData { 99 struct SingleShaderData { 100 CORE_NS::EntityReference shader; 101 CORE_NS::EntityReference gfxState; 102 CORE_NS::EntityReference gfxStateDoubleSided; 103 }; 104 SingleShaderData opaque; 105 SingleShaderData blend; 106 SingleShaderData depth; 107 }; 108 109 protected: 110 void Destroy() override; 111 112 private: 113 struct ImporterTask; 114 template<typename T> 115 struct GatheredDataTask; 116 template<typename Component> 117 struct ComponentTaskData; 118 struct AnimationTaskData; 119 120 class ImportThreadTask; 121 class GatherThreadTask; 122 123 void Prepare(); 124 void PrepareBufferTasks(); 125 void PrepareSamplerTasks(); 126 void PrepareImageTasks(); 127 void PrepareImageBasedLightTasks(); 128 void PrepareMaterialTasks(); 129 void PrepareAnimationTasks(); 130 void PrepareSkinTasks(); 131 void PrepareMeshTasks(); 132 template<typename T> 133 GatheredDataTask<T>* PrepareAnimationInputTask(BASE_NS::unordered_map<GLTF2::Accessor*, GatheredDataTask<T>*>&, 134 const GLTF2::AnimationTrack&, IAnimationInputComponentManager*); 135 template<typename T> 136 GatheredDataTask<T>* PrepareAnimationOutputTask(BASE_NS::unordered_map<GLTF2::Accessor*, GatheredDataTask<T>*>&, 137 const GLTF2::AnimationTrack&, IAnimationOutputComponentManager*); 138 void QueueImage(size_t i, BASE_NS::string&& uri, BASE_NS::string&& name); 139 140 void QueueTask(BASE_NS::unique_ptr<ImporterTask>&& task); 141 bool ProgressTask(ImporterTask& task); 142 void Gather(ImporterTask& task); 143 void Import(ImporterTask& task); 144 void CompleteTask(ImporterTask& task); 145 146 void StartPhase(ImportPhase phase); 147 void HandleGatherTasks(); 148 void HandleImportTasks(); 149 150 ImporterTask* FindTaskById(uint64_t id); 151 152 ImportPhase phase_ { ImportPhase::BUFFERS }; 153 BASE_NS::vector<BASE_NS::unique_ptr<ImporterTask>> tasks_; 154 155 CORE_NS::IEngine& engine_; 156 RENDER_NS::IRenderContext& renderContext_; 157 RENDER_NS::IDevice& device_; 158 RENDER_NS::IGpuResourceManager& gpuResourceManager_; 159 CORE_NS::IEcs::Ptr ecs_; 160 IRenderHandleComponentManager& gpuHandleManager_; 161 IMaterialComponentManager& materialManager_; 162 IMeshComponentManager& meshManager_; 163 INameComponentManager& nameManager_; 164 IUriComponentManager& uriManager_; 165 166 // assigned to material in import 167 DefaultMaterialShaderData dmShaderData_; 168 169 const Data* data_ { nullptr }; 170 171 CORE_NS::IThreadPool::Ptr threadPool_; 172 CORE_NS::IDispatcherTaskQueue::Ptr mainThreadQueue_; 173 Listener* listener_ { nullptr }; 174 175 GltfResourceImportFlags flags_ { CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL }; 176 GLTFImportResult result_; 177 178 std::mutex gatherTasksLock_; 179 std::condition_variable condition_; 180 BASE_NS::vector<uint64_t> finishedGatherTasks_; 181 BASE_NS::vector<CORE_NS::IThreadPool::IResult::Ptr> gatherTaskResults_; 182 183 size_t pendingGatherTasks_ { 0 }; 184 size_t pendingImportTasks_ { 0 }; 185 size_t completedTasks_ { 0 }; 186 187 std::atomic_bool cancelled_ { false }; 188 189 BASE_NS::vector<IMeshBuilder::Ptr> meshBuilders_; 190 GltfMeshData meshData_; 191 }; 192 193 class Gltf2SceneImporter final : public ISceneImporter, IGLTF2Importer::Listener { 194 public: 195 Gltf2SceneImporter(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs); 196 Gltf2SceneImporter(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs, 197 CORE_NS::IThreadPool& pool); 198 ~Gltf2SceneImporter() = default; 199 200 void ImportResources(const ISceneData::Ptr& data, ResourceImportFlags flags) override; 201 void ImportResources( 202 const ISceneData::Ptr& data, ResourceImportFlags flags, ISceneImporter::Listener* listener) override; 203 bool Execute(uint32_t timeBudget) override; 204 void Cancel() override; 205 bool IsCompleted() const override; 206 const Result& GetResult() const override; 207 const MeshData& GetMeshData() const override; 208 CORE_NS::Entity ImportScene(size_t sceneIndex) override; 209 CORE_NS::Entity ImportScene(size_t sceneIndex, SceneImportFlags flags) override; 210 CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity) override; 211 CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity, SceneImportFlags flags) override; 212 213 // IInterface 214 const IInterface* GetInterface(const BASE_NS::Uid& uid) const override; 215 IInterface* GetInterface(const BASE_NS::Uid& uid) override; 216 void Ref() override; 217 void Unref() override; 218 219 // IGLTF2Importer::Listener 220 void OnImportStarted() override; 221 void OnImportFinished() override; 222 void OnImportProgressed(size_t taskIndex, size_t taskCount) override; 223 224 private: 225 CORE_NS::IEcs& ecs_; 226 IGraphicsContext* graphicsContext_ { nullptr }; 227 GLTF2Importer::Ptr importer_; 228 ISceneData::Ptr data_; 229 uint32_t refcnt_ { 0 }; 230 Result result_; 231 MeshData meshData_; 232 ISceneImporter::Listener* listener_ { nullptr }; 233 }; 234 } // namespace GLTF2 235 236 CORE_NS::Entity ImportScene(RENDER_NS::IDevice& device, size_t sceneIndex, const GLTF2::Data& data, 237 const GLTFResourceData& gltfResourceData, CORE_NS::IEcs& ecs, CORE_NS::Entity rootEntity, 238 GltfSceneImportFlags flags); 239 CORE3D_END_NAMESPACE() 240 241 #endif // CORE__GLTF__GLTF2_IMPORTER_H 242