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 API_3D_LOADERS_ISCENE_LOADER_H 17 #define API_3D_LOADERS_ISCENE_LOADER_H 18 19 #include <3d/ecs/components/mesh_component.h> 20 #include <3d/namespace.h> 21 #include <base/containers/array_view.h> 22 #include <base/containers/refcnt_ptr.h> 23 #include <base/containers/string.h> 24 #include <base/containers/string_view.h> 25 #include <base/containers/vector.h> 26 #include <core/ecs/entity.h> 27 #include <core/ecs/entity_reference.h> 28 #include <core/plugin/intf_interface.h> 29 30 CORE_BEGIN_NAMESPACE() 31 class IEcs; 32 class IThreadPool; 33 CORE_END_NAMESPACE() 34 35 CORE3D_BEGIN_NAMESPACE() 36 /** No scene explicitly defined in import options. */ 37 const unsigned long CORE_SCENE_INVALID_INDEX = 0x7FFFFFFF; 38 39 class ISceneData : public CORE_NS::IInterface { 40 public: 41 static constexpr auto UID = BASE_NS::Uid { "eb6381c1-36a3-4709-8031-c37c1b9cd76e" }; 42 using Ptr = BASE_NS::refcnt_ptr<ISceneData>; 43 44 /** Retrieve default scene index. */ 45 virtual size_t GetDefaultSceneIndex() const = 0; 46 47 /** Retrieve number of scenes in this scene file. 48 * @return Number of scenes available. 49 */ 50 virtual size_t GetSceneCount() const = 0; 51 52 protected: 53 ISceneData() = default; 54 virtual ~ISceneData() = default; 55 }; 56 57 /** Access to imported resources. */ 58 struct ResourceData { 59 /** Imported samplers. */ 60 BASE_NS::vector<CORE_NS::EntityReference> samplers; 61 62 /** Imported images. */ 63 BASE_NS::vector<CORE_NS::EntityReference> images; 64 65 /** Imported textures. */ 66 BASE_NS::vector<CORE_NS::EntityReference> textures; 67 68 /** Imported materials. */ 69 BASE_NS::vector<CORE_NS::EntityReference> materials; 70 71 /** Imported geometry. */ 72 BASE_NS::vector<CORE_NS::EntityReference> meshes; 73 74 /** Imported skins. */ 75 BASE_NS::vector<CORE_NS::EntityReference> skins; 76 77 /** Imported animations. */ 78 BASE_NS::vector<CORE_NS::EntityReference> animations; 79 80 /** Imported IBL cubemaps. */ 81 BASE_NS::vector<CORE_NS::EntityReference> specularRadianceCubemaps; 82 }; 83 84 /** Flags for resource import. */ 85 enum ResourceImportFlagBits { 86 /** Sampler */ 87 CORE_IMPORT_RESOURCE_SAMPLER = 0x00000001, 88 /** Image */ 89 CORE_IMPORT_RESOURCE_IMAGE = 0x00000002, 90 /** Texture */ 91 CORE_IMPORT_RESOURCE_TEXTURE = 0x00000004, 92 /** Material */ 93 CORE_IMPORT_RESOURCE_MATERIAL = 0x00000008, 94 /** Mesh */ 95 CORE_IMPORT_RESOURCE_MESH = 0x00000010, 96 /** Skin */ 97 CORE_IMPORT_RESOURCE_SKIN = 0x00000020, 98 /** Animation */ 99 CORE_IMPORT_RESOURCE_ANIMATION = 0x00000040, 100 /** Skip resources that are not referenced and do not import them. */ 101 CORE_IMPORT_RESOURCE_SKIP_UNUSED = 0x00000080, 102 /** Keep mesh data for CPU access. Allowing CPU access increases memory usage. */ 103 CORE_IMPORT_RESOURCE_MESH_CPU_ACCESS = 0x00000100, 104 /** All flags bits */ 105 CORE_IMPORT_RESOURCE_FLAG_BITS_ALL = 0x7FFFFEFF 106 }; 107 108 /** Container for flags for resource import. */ 109 using ResourceImportFlags = uint32_t; 110 111 /** Flags for scene / ecs component import. */ 112 enum SceneImportFlagBits { 113 /** Environment */ 114 CORE_IMPORT_COMPONENT_ENVIRONMENT = 0x00000001, 115 /** Mesh */ 116 CORE_IMPORT_COMPONENT_MESH = 0x00000002, 117 /** Camera */ 118 CORE_IMPORT_COMPONENT_CAMERA = 0x00000004, 119 /** Skin */ 120 CORE_IMPORT_COMPONENT_SKIN = 0x00000008, 121 /** Light */ 122 CORE_IMPORT_COMPONENT_LIGHT = 0x00000010, 123 /** Morph */ 124 CORE_IMPORT_COMPONENT_MORPH = 0x00000020, 125 /** All flag bits */ 126 CORE_IMPORT_COMPONENT_FLAG_BITS_ALL = 0x7FFFFFFF 127 }; 128 129 /** Container for scene import flag bits */ 130 using SceneImportFlags = uint32_t; 131 132 struct MeshData { 133 struct SubMesh { 134 uint32_t indices; 135 uint32_t vertices; 136 BASE_NS::array_view<const uint8_t> indexBuffer; 137 BASE_NS::array_view<const uint8_t> attributeBuffers[MeshComponent::Submesh::BUFFER_COUNT]; 138 }; 139 struct Mesh { 140 BASE_NS::vector<SubMesh> subMeshes; 141 }; 142 /** Vertex input declaration used for formatting the data. */ 143 RENDER_NS::VertexInputDeclarationData vertexInputDeclaration; 144 /** Data of each imported mesh. They are in the same order as in ResourceData::meshes. */ 145 BASE_NS::vector<Mesh> meshes; 146 }; 147 148 class ISceneImporter : public CORE_NS::IInterface { 149 public: 150 static constexpr auto UID = BASE_NS::Uid { "6dd26fca-9ef1-40f1-ba67-1bbcc1740885" }; 151 152 using Ptr = BASE_NS::refcnt_ptr<ISceneImporter>; 153 154 struct Result { 155 /** Indicates, whether the import operation is successful. */ 156 int32_t error { 0 }; 157 158 /** In case of import error, contains the description of the error. */ 159 BASE_NS::string message; 160 161 /** Imported resources. */ 162 ResourceData data; 163 }; 164 165 /** Listener for import events. */ 166 class Listener { 167 public: 168 virtual ~Listener() = default; 169 170 /** On import started */ 171 virtual void OnImportStarted() = 0; 172 /** On import progressed */ 173 virtual void OnImportProgressed(size_t taskIndex, size_t taskCount) = 0; 174 /** On import finished */ 175 virtual void OnImportFinished() = 0; 176 }; 177 178 /** Import resources synchronously. The previous imported data will be discarded. 179 * @param data Scene data returned by the loader. 180 * @param flags Flags for scene / ecs component import. 181 */ 182 virtual void ImportResources(const ISceneData::Ptr& data, ResourceImportFlags flags) = 0; 183 184 /** Import resource data asynchronously. The previous imported data will be discarded. Import will mostly happen in 185 * a threadpool, but any access to the ECS must be done synchronized. Typically the user calls Execute() from the 186 * rendering thread each frame. 187 * @param data Scene data returned by the loader. 188 * @param flags Flags for scene / ecs component import. 189 * @param listener Listener which receives updates of the imports progress. 190 */ 191 virtual void ImportResources(const ISceneData::Ptr& data, ResourceImportFlags flags, Listener* listener) = 0; 192 193 /** Advances the import process when performing asynchronous import. Needs to be called synchronized with other ECS 194 * usage. 195 * @param timeBudget Time budget for resource import in microseconds, if 0 all available work will be executed 196 * during this frame. 197 * @return True if the import was compled. 198 */ 199 virtual bool Execute(uint32_t timeBudget) = 0; 200 201 /** Cancel import operation, this does not discard imported data. */ 202 virtual void Cancel() = 0; 203 204 /** Returns true when import process is completed. */ 205 virtual bool IsCompleted() const = 0; 206 207 /** Returns imported data and success of the whole operation. The imported resources are reference counted and the 208 * importer holds references until a new import is started or the imported is destroyed. Therefore a copy of 209 * ImportResult::ResourceData (or selected EntityReferences) should be stored. */ 210 virtual const Result& GetResult() const = 0; 211 212 /** Returns CPU accessible mesh data. Data is available when CORE_IMPORT_RESOURCE_MESH_CPU_ACCESS was included 213 * in import flags. Unless copied, the data is valid until a new import is started or the imported is destroyed. */ 214 virtual const MeshData& GetMeshData() const = 0; 215 216 /** Import scene to ECS using pre-imported resources. 217 * @param sceneIndex Index of scene to import. 218 * @return Scene root entity. 219 */ 220 virtual CORE_NS::Entity ImportScene(size_t sceneIndex) = 0; 221 222 /** Import scene to ECS using pre-imported resources. 223 * @param sceneIndex Index of scene to import. 224 * @param flags Import flags to filter out which components are imported. 225 * @return Scene root entity. 226 */ 227 virtual CORE_NS::Entity ImportScene(size_t sceneIndex, SceneImportFlags flags) = 0; 228 229 /** Import scene to ECS using pre-imported resources. 230 * @param sceneIndex Index of scene to import. 231 * @param parentEntity Scene will be added as a child of the parent entity. 232 * @return Scene root entity. 233 */ 234 virtual CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity) = 0; 235 236 /** Import scene to ECS using pre-imported resources. 237 * @param sceneIndex Index of scene to import. 238 * @param parentEntity Scene will be added as a child of the parent entity. 239 * @param flags Import flags to filter out which components are imported. 240 * @return Scene root entity. 241 */ 242 virtual CORE_NS::Entity ImportScene(size_t sceneIndex, CORE_NS::Entity parentEntity, SceneImportFlags flags) = 0; 243 244 protected: 245 }; 246 247 class ISceneLoader : public CORE_NS::IInterface { 248 public: 249 static constexpr auto UID = BASE_NS::Uid { "61997694-aa64-4753-9d01-17d18aad4822" }; 250 251 using Ptr = BASE_NS::refcnt_ptr<ISceneLoader>; 252 253 struct Result { 254 /** Indicates, whether the loading was successful. */ 255 int32_t error { 0 }; 256 257 /** In case of an error, contains the description of the error. */ 258 BASE_NS::string message; 259 260 /** Loaded data. */ 261 ISceneData::Ptr data; 262 }; 263 264 /** Load scene data from URI. 265 * @param uri URI pointing to the scene data. 266 * @return If the scene data could be parsed LoadResult::result will be zero and LoadResult::data is valid. If 267 * parsing fails LoadResult::result will be a non-zero, loader specific error code and LoadResult::error will give 268 * more details on the failure. 269 */ 270 virtual Result Load(BASE_NS::string_view uri) = 0; 271 272 /** Create an importer that builds 3D resources and scenes from loaded scene data. 273 * The importer will create a thread pool where import task are executed. 274 * @param ecs ECS that contains all required subsystems that are needed for resource creation. 275 * @return Scene importer instance. 276 */ 277 virtual ISceneImporter::Ptr CreateSceneImporter(CORE_NS::IEcs& ecs) = 0; 278 279 /** Create an importer that builds 3D resources and scenes from loaded scene data. 280 * @param ecs ECS that contains all required subsystems that are needed for resource creation. 281 * @param pool Importer will use the given thread pool instead of creating its own. 282 * @return Scene importer instance. 283 */ 284 virtual ISceneImporter::Ptr CreateSceneImporter(CORE_NS::IEcs& ecs, CORE_NS::IThreadPool& pool) = 0; 285 286 /** Returns a list of extensions the loader supports. 287 * @return List of supported file extensions. 288 */ 289 virtual BASE_NS::array_view<const BASE_NS::string_view> GetSupportedExtensions() const = 0; 290 291 protected: 292 ISceneLoader() = default; 293 virtual ~ISceneLoader() = default; 294 }; 295 CORE3D_END_NAMESPACE() 296 #endif // API_3D_LOADERS_ISCENE_LOADER_H