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_GLTF_GLTF_H 17 #define API_3D_GLTF_GLTF_H 18 19 #include <cstdint> 20 21 #include <3d/ecs/components/mesh_component.h> 22 #include <3d/namespace.h> 23 #include <base/containers/array_view.h> 24 #include <base/containers/string.h> 25 #include <base/containers/string_view.h> 26 #include <base/containers/unique_ptr.h> 27 #include <base/containers/vector.h> 28 #include <core/ecs/entity_reference.h> 29 #include <render/device/pipeline_state_desc.h> 30 #include <render/resource_handle.h> 31 32 CORE_BEGIN_NAMESPACE() 33 class IEcs; 34 class IThreadPool; 35 CORE_END_NAMESPACE() 36 37 CORE3D_BEGIN_NAMESPACE() 38 /** \addtogroup group_gltf_gltf 39 * @{ 40 */ 41 /** No scene explicitly defined in import options. */ 42 const unsigned long CORE_GLTF_INVALID_INDEX = 0x7FFFFFFF; 43 44 /** Interface to GLTF data. */ 45 class IGLTFData { 46 public: 47 /** Populates buffers with binary data. 48 * @return true if buffers were successfully loaded, otherwise false. 49 */ 50 virtual bool LoadBuffers() = 0; 51 52 /** Releases allocated data from buffers. */ 53 virtual void ReleaseBuffers() = 0; 54 55 /** Can be used to retrieve external file dependencies. 56 * @return Array of file uris that describe required files that need to be available for this glTF file to 57 * successfully load. 58 */ 59 virtual BASE_NS::vector<BASE_NS::string> GetExternalFileUris() = 0; 60 61 /** Retrieve default scene index. */ 62 virtual size_t GetDefaultSceneIndex() const = 0; 63 64 /** Retrieve number of scenes in this glTF file. 65 * @return Number of scenes available. 66 */ 67 virtual size_t GetSceneCount() const = 0; 68 69 /** Describes thumbnail image structure. */ 70 struct ThumbnailImage { 71 /** Data extension, such as 'png'. */ 72 BASE_NS::string extension; 73 74 /** Image data buffer. */ 75 BASE_NS::array_view<const uint8_t> data; 76 }; 77 78 /** Retrieve number of thumbnails in this glTF file. 79 * @return Number of thumbnail images available. 80 */ 81 virtual size_t GetThumbnailImageCount() const = 0; 82 83 /** Retrieve thumbnail image data of given thumbnail. 84 * @param thumbnailIndex Index of the requested thumbnail image. 85 * @return A structure containing thumbnail image data. 86 */ 87 virtual ThumbnailImage GetThumbnailImage(size_t thumbnailIndex) = 0; 88 89 struct Deleter { 90 constexpr Deleter() noexcept = default; operatorDeleter91 void operator()(IGLTFData* ptr) const 92 { 93 ptr->Destroy(); 94 } 95 }; 96 using Ptr = BASE_NS::unique_ptr<IGLTFData, Deleter>; 97 98 protected: 99 IGLTFData() = default; 100 virtual ~IGLTFData() = default; 101 virtual void Destroy() = 0; 102 }; 103 104 /** Describes result of the loading operation. */ 105 struct GLTFLoadResult { 106 GLTFLoadResult() = default; GLTFLoadResultGLTFLoadResult107 explicit GLTFLoadResult(BASE_NS::string&& error) : success(false), error(error) {} 108 109 /** Indicates, whether the loading operation is successful. */ 110 bool success { true }; 111 112 /** In case of parsing error, contains the description of the error. */ 113 BASE_NS::string error; 114 115 /** Loaded data. */ 116 IGLTFData::Ptr data; 117 }; 118 119 /** Access to imported GLTF resources. */ 120 struct GLTFResourceData { 121 /** Imported samplers. */ 122 BASE_NS::vector<CORE_NS::EntityReference> samplers; 123 124 /** Imported images. */ 125 BASE_NS::vector<CORE_NS::EntityReference> images; 126 127 /** Imported textures. */ 128 BASE_NS::vector<CORE_NS::EntityReference> textures; 129 130 /** Imported materials. */ 131 BASE_NS::vector<CORE_NS::EntityReference> materials; 132 133 /** Imported geometry. */ 134 BASE_NS::vector<CORE_NS::EntityReference> meshes; 135 136 /** Imported skins. */ 137 BASE_NS::vector<CORE_NS::EntityReference> skins; 138 139 /** Imported animations. */ 140 BASE_NS::vector<CORE_NS::EntityReference> animations; 141 142 /** Imported IBL cubemaps. */ 143 BASE_NS::vector<CORE_NS::EntityReference> specularRadianceCubemaps; 144 }; 145 146 /** Flags for resource import. */ 147 enum GltfResourceImportFlagBits { 148 /** Sampler */ 149 CORE_GLTF_IMPORT_RESOURCE_SAMPLER = 0x00000001, 150 /** Image */ 151 CORE_GLTF_IMPORT_RESOURCE_IMAGE = 0x00000002, 152 /** Texture */ 153 CORE_GLTF_IMPORT_RESOURCE_TEXTURE = 0x00000004, 154 /** Material */ 155 CORE_GLTF_IMPORT_RESOURCE_MATERIAL = 0x00000008, 156 /** Mesh */ 157 CORE_GLTF_IMPORT_RESOURCE_MESH = 0x00000010, 158 /** Skin */ 159 CORE_GLTF_IMPORT_RESOURCE_SKIN = 0x00000020, 160 /** Animation */ 161 CORE_GLTF_IMPORT_RESOURCE_ANIMATION = 0x00000040, 162 /** Skip resources that are not referenced and do not import them. */ 163 CORE_GLTF_IMPORT_RESOURCE_SKIP_UNUSED = 0x00000080, 164 /** Keep mesh data for CPU access. Allowing CPU access increases memory usage. */ 165 CORE_GLTF_IMPORT_RESOURCE_MESH_CPU_ACCESS = 0x00000100, 166 /** All flags bits */ 167 CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL = 0x7FFFFEFF 168 }; 169 170 /** Container for flags for resource import. */ 171 using GltfResourceImportFlags = uint32_t; 172 173 /** Flags for scene / ecs component import. */ 174 enum GltfSceneImportFlagBits { 175 /** Scene, Deprecated value used for environment */ 176 CORE_GLTF_IMPORT_COMPONENT_SCENE = 0x00000001, 177 /** Environment */ 178 CORE_GLTF_IMPORT_COMPONENT_ENVIRONMENT = 0x00000001, 179 /** Mesh */ 180 CORE_GLTF_IMPORT_COMPONENT_MESH = 0x00000002, 181 /** Camera */ 182 CORE_GLTF_IMPORT_COMPONENT_CAMERA = 0x00000004, 183 /** Skin */ 184 CORE_GLTF_IMPORT_COMPONENT_SKIN = 0x00000008, 185 /** Light */ 186 CORE_GLTF_IMPORT_COMPONENT_LIGHT = 0x00000010, 187 /** Morph */ 188 CORE_GLTF_IMPORT_COMPONENT_MORPH = 0x00000020, 189 /** All flag bits */ 190 CORE_GLTF_IMPORT_COMPONENT_FLAG_BITS_ALL = 0x7FFFFFFF 191 }; 192 193 /** Container for Gltf scene import flag bits */ 194 using GltfSceneImportFlags = uint32_t; 195 196 /** Describes result of the import operation. */ 197 struct GLTFImportResult { 198 /** Indicates, whether the import operation is successful. */ 199 bool success { true }; 200 201 /** In case of import error, contains the description of the error. */ 202 BASE_NS::string error; 203 204 /** Imported data. */ 205 GLTFResourceData data; 206 }; 207 208 struct GltfMeshData { 209 struct SubMesh { 210 uint32_t indices; 211 uint32_t vertices; 212 BASE_NS::array_view<const uint8_t> indexBuffer; 213 BASE_NS::array_view<const uint8_t> attributeBuffers[MeshComponent::Submesh::BUFFER_COUNT]; 214 }; 215 struct Mesh { 216 BASE_NS::vector<SubMesh> subMeshes; 217 }; 218 /** Vertex input declaration used for formatting the data. */ 219 RENDER_NS::VertexInputDeclarationData vertexInputDeclaration; 220 /** Data of each imported mesh. They are in the same order as in GLTFResourceData::meshes. */ 221 BASE_NS::vector<Mesh> meshes; 222 }; 223 224 /** GLTF2 importer interface */ 225 class IGLTF2Importer { 226 public: 227 /** Listener for import events. */ 228 class Listener { 229 public: 230 virtual ~Listener() = default; 231 232 /** On import started */ 233 virtual void OnImportStarted() = 0; 234 /** On import finished */ 235 virtual void OnImportFinished() = 0; 236 /** On import progressed */ 237 virtual void OnImportProgressed(size_t taskIndex, size_t taskCount) = 0; 238 }; 239 240 /** Import GLTF2 data synchronously. The previous imported data will be discarded. */ 241 virtual void ImportGLTF(const IGLTFData& data, GltfResourceImportFlags flags) = 0; 242 243 /** Import GLTF2 data asynchronously, user is required to call Execute() from main thread until it returns true. 244 * The previous imported data will be discarded. */ 245 virtual void ImportGLTFAsync(const IGLTFData& data, GltfResourceImportFlags flags, Listener* listener) = 0; 246 247 /** Advances the import process, needs to be called from the main thread when performing asynchronous import. 248 * @param timeBudget Time budget for resource import in microseconds, if 0 all available work will be executed 249 * during this frame. 250 */ 251 virtual bool Execute(uint32_t timeBudget) = 0; 252 253 /** Cancel import operation, this does not discard imported data. */ 254 virtual void Cancel() = 0; 255 256 /** Returns true when import process is completed. */ 257 virtual bool IsCompleted() const = 0; 258 259 /** Returns imported data and success of the whole operation. The imported resources are reference counted and the 260 * importer holds references until a new import is started or the imported is destroyed. Therefore a copy of 261 * GLTFImportResult::GLTFResourceData (or selected EntityReferences) should be stored. */ 262 virtual const GLTFImportResult& GetResult() const = 0; 263 264 /** Returns CPU accessible mesh data. Data is available when CORE_GLTF_IMPORT_RESOURCE_MESH_CPU_ACCESS was included 265 * in import flags. Unless copied, the data is valid until a new import is started or the imported is destroyed. */ 266 virtual const GltfMeshData& GetMeshData() const = 0; 267 268 struct Deleter { 269 constexpr Deleter() noexcept = default; operatorDeleter270 void operator()(IGLTF2Importer* ptr) const 271 { 272 ptr->Destroy(); 273 } 274 }; 275 using Ptr = BASE_NS::unique_ptr<IGLTF2Importer, Deleter>; 276 277 protected: 278 IGLTF2Importer() = default; 279 virtual ~IGLTF2Importer() = default; 280 virtual void Destroy() = 0; 281 }; 282 283 class IGltf2 { 284 public: 285 /** Load GLTF data from URI. 286 * @param uri URI pointing to the glTF data. 287 * @return If the glTF data could be parsed GLTFLoadResult::success will be true and GLTFLoadResult::data is valid. 288 * If parsing fails GLTFLoadResult::success will be false and GLTFLoadResult::error will give more details on the 289 * failure. 290 */ 291 virtual GLTFLoadResult LoadGLTF(BASE_NS::string_view uri) = 0; 292 293 /** Load GLTF data from memory. 294 * @param data Contents of a GLB or a glTF file with embedded data. 295 * The memory should not be released until loading and importing have been completed. 296 * @return If the glTF data could be parsed GLTFLoadResult::success will be true and GLTFLoadResult::data is valid. 297 * If parsing fails GLTFLoadResult::success will be false and GLTFLoadResult::error will give more details on the 298 * failure. 299 */ 300 virtual GLTFLoadResult LoadGLTF(BASE_NS::array_view<uint8_t const> data) = 0; 301 302 /** Save GLTF data to file. 303 * @param ecs ECS instance from which data is exported as a glTF file. 304 * @param uri URI pointing to the glTF file. 305 * @return True if the data could be saved, false otherwise. 306 */ 307 virtual bool SaveGLTF(CORE_NS::IEcs& ecs, BASE_NS::string_view uri) = 0; 308 309 /** Create glTF file importer that builds 3D resources from glTF data. 310 * The importer will create a thread pool where import task are executed. 311 * @param ecs ECS that contains all required subsystems that are needed for resource creation. 312 * @return glTF importer instance. 313 */ 314 virtual IGLTF2Importer::Ptr CreateGLTF2Importer(CORE_NS::IEcs& ecs) = 0; 315 316 /** Create glTF file importer that builds 3D resources from glTF data. 317 * @param ecs ECS that contains all required subsystems that are needed for resource creation. 318 * @param pool Importer will use the given thread pool instead of creating its own. 319 * @return glTF importer instance. 320 */ 321 virtual IGLTF2Importer::Ptr CreateGLTF2Importer(CORE_NS::IEcs& ecs, CORE_NS::IThreadPool& pool) = 0; 322 323 /** Import glTF scene to Ecs using pre-imported glTF resources. 324 * @param sceneIndex Index of scene to import. 325 * @param gltfData Pre-loaded glTF data. 326 * @param gltfImportData Structure that contains glTF resource handles related to imported glTF. 327 * @param ecs Ecs structure that receives the imported entities and components. 328 * @param rootEntity Root entity for imported data. 329 * @param flags Import flags to filter out which components are imported. 330 * @return Scene root entity. 331 */ 332 virtual CORE_NS::Entity ImportGltfScene(size_t sceneIndex, const IGLTFData& gltfData, 333 const GLTFResourceData& gltfImportData, CORE_NS::IEcs& ecs, CORE_NS::Entity rootEntity = {}, 334 GltfSceneImportFlags flags = CORE_GLTF_IMPORT_COMPONENT_FLAG_BITS_ALL) = 0; 335 336 protected: 337 IGltf2() = default; 338 virtual ~IGltf2() = default; 339 }; 340 /** @} */ 341 CORE3D_END_NAMESPACE() 342 343 #endif // API_3D_GLTF_GLTF_H 344