1 /* 2 * Copyright (c) 2022 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 <mutex> 21 22 #include <3d/gltf/gltf.h> 23 #include <3d/loaders/intf_scene_loader.h> 24 #include <3d/util/intf_mesh_builder.h> 25 #include <base/containers/string.h> 26 #include <base/containers/unique_ptr.h> 27 #include <base/containers/vector.h> 28 #include <base/util/color.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 bool IsValid() const; 99 100 struct DefaultMaterialShaderData { 101 struct SingleShaderData { 102 CORE_NS::EntityReference shader; 103 CORE_NS::EntityReference gfxState; 104 CORE_NS::EntityReference gfxStateDoubleSided; 105 }; 106 SingleShaderData opaque; 107 SingleShaderData blend; 108 SingleShaderData depth; 109 }; 110 111 protected: 112 void Destroy() override; 113 114 private: 115 friend class Gltf2; 116 117 struct ImporterTask; 118 template<typename T> 119 struct GatheredDataTask; 120 template<typename Component> 121 struct ComponentTaskData; 122 struct AnimationTaskData; 123 124 class ImportThreadTask; 125 class GatherThreadTask; 126 127 void LaunchGatherTasks(size_t firstTask, ImportPhase phase); 128 void Prepare(); 129 void PrepareBufferTasks(); 130 void PrepareSamplerTasks(); 131 void PrepareImageTasks(); 132 void PrepareImageBasedLightTasks(); 133 void PrepareMaterialTasks(); 134 void PrepareAnimationTasks(); 135 void PrepareSkinTasks(); 136 void PrepareMeshTasks(); 137 template<typename T> 138 GatheredDataTask<T>* PrepareAnimationInputTask(BASE_NS::unordered_map<GLTF2::Accessor*, GatheredDataTask<T>*>&, 139 const GLTF2::AnimationTrack&, IAnimationInputComponentManager*); 140 template<typename T> 141 GatheredDataTask<T>* PrepareAnimationOutputTask(BASE_NS::unordered_map<GLTF2::Accessor*, GatheredDataTask<T>*>&, 142 const GLTF2::AnimationTrack&, IAnimationOutputComponentManager*); 143 void QueueImage(size_t i, BASE_NS::string&& uri, BASE_NS::string&& name); 144 145 void QueueTask(BASE_NS::unique_ptr<ImporterTask>&& task); 146 bool ProgressTask(ImporterTask& task); 147 void Gather(ImporterTask& task); 148 void Import(ImporterTask& task); 149 void CompleteTask(ImporterTask& task); 150 151 void StartPhase(ImportPhase phase); 152 void HandleGatherTasks(); 153 void HandleImportTasks(); 154 155 ImporterTask* FindTaskById(uint64_t id); 156 157 ImportPhase phase_ { ImportPhase::BUFFERS }; 158 GltfResourceImportFlags flags_ { CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL }; 159 160 const CORE_NS::IThreadPool::ITask* bufferTask_ { nullptr }; 161 BASE_NS::vector<BASE_NS::unique_ptr<ImporterTask>> tasks_; 162 CORE_NS::IThreadPool::IResult::Ptr gatherResults_[static_cast<uint32_t>(ImportPhase::FINISHED)]; 163 164 CORE_NS::IEngine& engine_; 165 RENDER_NS::IRenderContext& renderContext_; 166 RENDER_NS::IDevice& device_; 167 RENDER_NS::IGpuResourceManager& gpuResourceManager_; 168 CORE_NS::IEcs::Ptr ecs_; 169 IRenderHandleComponentManager* renderHandleManager_; 170 IMaterialComponentManager* materialManager_; 171 IMeshComponentManager* meshManager_; 172 INameComponentManager* nameManager_; 173 IUriComponentManager* uriManager_; 174 175 // assigned to material in import 176 DefaultMaterialShaderData dmShaderData_; 177 178 const Data* data_ { nullptr }; 179 180 CORE_NS::IThreadPool::Ptr threadPool_; 181 CORE_NS::IDispatcherTaskQueue::Ptr mainThreadQueue_; 182 Listener* listener_ { nullptr }; 183 184 GLTFImportResult result_; 185 186 std::mutex gatherTasksLock_; 187 BASE_NS::vector<uint64_t> finishedGatherTasks_[static_cast<uint32_t>(ImportPhase::FINISHED)]; 188 189 size_t pendingGatherTasks_[static_cast<uint32_t>(ImportPhase::FINISHED)] {}; 190 size_t pendingImportTasks_ { 0 }; 191 size_t completedTasks_ { 0 }; 192 193 BASE_NS::vector<IMeshBuilder::Ptr> meshBuilders_; 194 GltfMeshData meshData_; 195 196 BASE_NS::ColorSpaceFlags colorSpaceFlags_ { 0U }; 197 std::atomic_bool cancelled_ { false }; 198 }; 199 200 class Gltf2SceneImporter final : public ISceneImporter, IGLTF2Importer::Listener { 201 public: 202 Gltf2SceneImporter(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs); 203 Gltf2SceneImporter(CORE_NS::IEngine& engine, RENDER_NS::IRenderContext& renderContext, CORE_NS::IEcs& ecs, 204 CORE_NS::IThreadPool& pool); 205 ~Gltf2SceneImporter() = default; 206 207 void ImportResources(const ISceneData::Ptr& data, ResourceImportFlags flags) override; 208 void ImportResources( 209 const ISceneData::Ptr& data, ResourceImportFlags flags, ISceneImporter::Listener* listener) override; 210 bool Execute(uint32_t timeBudget) override; 211 void Cancel() override; 212 bool IsCompleted() const override; 213 const Result& GetResult() const override; 214 const MeshData& GetMeshData() const override; 215 CORE_NS::Entity ImportScene(size_t sceneIndex) override; 216 CORE_NS::Entity ImportScene(size_t sceneIndex, SceneImportFlags flags) override; 217 CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity) override; 218 CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity, SceneImportFlags flags) override; 219 CORE_NS::Entity ImportScene(size_t sceneIndex, uint32_t sceneId, SceneImportFlags flags) override; 220 221 // IInterface 222 const IInterface* GetInterface(const BASE_NS::Uid& uid) const override; 223 IInterface* GetInterface(const BASE_NS::Uid& uid) override; 224 void Ref() override; 225 void Unref() override; 226 227 // IGLTF2Importer::Listener 228 void OnImportStarted() override; 229 void OnImportFinished() override; 230 void OnImportProgressed(size_t taskIndex, size_t taskCount) override; 231 232 private: 233 void UpdateResults(); 234 235 CORE_NS::IEcs& ecs_; 236 IGraphicsContext* graphicsContext_ { nullptr }; 237 GLTF2Importer::Ptr importer_; 238 ISceneData::Ptr data_; 239 uint32_t refcnt_ { 0 }; 240 Result result_; 241 MeshData meshData_; 242 ISceneImporter::Listener* listener_ { nullptr }; 243 }; 244 } // namespace GLTF2 245 246 CORE_NS::Entity ImportScene(RENDER_NS::IDevice& device, size_t sceneIndex, const GLTF2::Data& data, 247 const GLTFResourceData& gltfResourceData, CORE_NS::IEcs& ecs, CORE_NS::Entity rootEntity, uint32_t level, 248 GltfSceneImportFlags flags); 249 CORE3D_END_NAMESPACE() 250 251 #endif // CORE__GLTF__GLTF2_IMPORTER_H 252