18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci#include "gltf2.h" 168bf80f4bSopenharmony_ci 178bf80f4bSopenharmony_ci#include <3d/gltf/gltf.h> 188bf80f4bSopenharmony_ci#include <3d/intf_graphics_context.h> 198bf80f4bSopenharmony_ci#include <core/ecs/intf_ecs.h> 208bf80f4bSopenharmony_ci#include <core/ecs/intf_entity_manager.h> 218bf80f4bSopenharmony_ci#include <core/intf_engine.h> 228bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h> 238bf80f4bSopenharmony_ci#include <core/log.h> 248bf80f4bSopenharmony_ci#include <core/plugin/intf_plugin_register.h> 258bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h> 268bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ci#include "data.h" 298bf80f4bSopenharmony_ci#include "gltf2_exporter.h" 308bf80f4bSopenharmony_ci#include "gltf2_importer.h" 318bf80f4bSopenharmony_ci#include "gltf2_loader.h" 328bf80f4bSopenharmony_ci 338bf80f4bSopenharmony_ciCORE3D_BEGIN_NAMESPACE() 348bf80f4bSopenharmony_ciusing namespace BASE_NS; 358bf80f4bSopenharmony_ciusing namespace CORE_NS; 368bf80f4bSopenharmony_ci 378bf80f4bSopenharmony_ciGltf2::Gltf2(IGraphicsContext& graphicsContext) 388bf80f4bSopenharmony_ci : engine_(&(graphicsContext.GetRenderContext().GetEngine())), renderContext_(&graphicsContext.GetRenderContext()), 398bf80f4bSopenharmony_ci fileManager_(engine_->GetFileManager()) 408bf80f4bSopenharmony_ci{} 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ciGltf2::Gltf2(IFileManager& fileManager) : fileManager_(fileManager) {} 438bf80f4bSopenharmony_ci 448bf80f4bSopenharmony_ci// Internal helper. 458bf80f4bSopenharmony_ciGLTFLoadResult LoadGLTF(IFileManager& fileManager, const string_view uri) 468bf80f4bSopenharmony_ci{ 478bf80f4bSopenharmony_ci auto loadResult = GLTF2::LoadGLTF(fileManager, uri); 488bf80f4bSopenharmony_ci GLTFLoadResult result; 498bf80f4bSopenharmony_ci result.error = move(loadResult.error); 508bf80f4bSopenharmony_ci result.success = loadResult.success; 518bf80f4bSopenharmony_ci result.data = IGLTFData::Ptr { loadResult.data.release() }; 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_ci return result; 548bf80f4bSopenharmony_ci} 558bf80f4bSopenharmony_ci 568bf80f4bSopenharmony_ci// Api loading function. 578bf80f4bSopenharmony_ciGLTFLoadResult Gltf2::LoadGLTF(const string_view uri) 588bf80f4bSopenharmony_ci{ 598bf80f4bSopenharmony_ci return CORE3D_NS::LoadGLTF(fileManager_, uri); 608bf80f4bSopenharmony_ci} 618bf80f4bSopenharmony_ci 628bf80f4bSopenharmony_ciGLTFLoadResult Gltf2::LoadGLTF(array_view<uint8_t const> data) 638bf80f4bSopenharmony_ci{ 648bf80f4bSopenharmony_ci auto loadResult = GLTF2::LoadGLTF(fileManager_, data); 658bf80f4bSopenharmony_ci GLTFLoadResult result; 668bf80f4bSopenharmony_ci result.error = move(loadResult.error); 678bf80f4bSopenharmony_ci result.success = loadResult.success; 688bf80f4bSopenharmony_ci result.data = IGLTFData::Ptr { loadResult.data.release() }; 698bf80f4bSopenharmony_ci return result; 708bf80f4bSopenharmony_ci} 718bf80f4bSopenharmony_ci 728bf80f4bSopenharmony_ci// Api import functions 738bf80f4bSopenharmony_ciEntity Gltf2::ImportGltfScene(size_t sceneIndex, const IGLTFData& gltfData, const GLTFResourceData& gltfResourceData, 748bf80f4bSopenharmony_ci IEcs& ecs, Entity rootEntity, GltfSceneImportFlags flags) 758bf80f4bSopenharmony_ci{ 768bf80f4bSopenharmony_ci CORE_ASSERT(renderContext_); 778bf80f4bSopenharmony_ci if (renderContext_) { 788bf80f4bSopenharmony_ci const GLTF2::Data& data = static_cast<const GLTF2::Data&>(gltfData); 798bf80f4bSopenharmony_ci return ImportScene(renderContext_->GetDevice(), sceneIndex, data, gltfResourceData, ecs, rootEntity, flags); 808bf80f4bSopenharmony_ci } 818bf80f4bSopenharmony_ci return {}; 828bf80f4bSopenharmony_ci} 838bf80f4bSopenharmony_ci 848bf80f4bSopenharmony_ciIGLTF2Importer::Ptr Gltf2::CreateGLTF2Importer(IEcs& ecs) 858bf80f4bSopenharmony_ci{ 868bf80f4bSopenharmony_ci CORE_ASSERT(engine_ && renderContext_); 878bf80f4bSopenharmony_ci if (engine_ && renderContext_) { 888bf80f4bSopenharmony_ci if (auto pool = ecs.GetThreadPool(); pool) { 898bf80f4bSopenharmony_ci return CreateGLTF2Importer(ecs, *pool); 908bf80f4bSopenharmony_ci } 918bf80f4bSopenharmony_ci return IGLTF2Importer::Ptr { new GLTF2::GLTF2Importer(*engine_, *renderContext_, ecs) }; 928bf80f4bSopenharmony_ci } 938bf80f4bSopenharmony_ci return nullptr; 948bf80f4bSopenharmony_ci} 958bf80f4bSopenharmony_ci 968bf80f4bSopenharmony_ciIGLTF2Importer::Ptr Gltf2::CreateGLTF2Importer(IEcs& ecs, IThreadPool& pool) 978bf80f4bSopenharmony_ci{ 988bf80f4bSopenharmony_ci CORE_ASSERT(engine_ && renderContext_); 998bf80f4bSopenharmony_ci if (engine_ && renderContext_) { 1008bf80f4bSopenharmony_ci return IGLTF2Importer::Ptr { new GLTF2::GLTF2Importer(*engine_, *renderContext_, ecs, pool) }; 1018bf80f4bSopenharmony_ci } 1028bf80f4bSopenharmony_ci return nullptr; 1038bf80f4bSopenharmony_ci} 1048bf80f4bSopenharmony_ci 1058bf80f4bSopenharmony_ciISceneLoader::Result Gltf2::Load(string_view uri) 1068bf80f4bSopenharmony_ci{ 1078bf80f4bSopenharmony_ci ISceneLoader::Result sceneResult; 1088bf80f4bSopenharmony_ci auto loadResult = GLTF2::LoadGLTF(fileManager_, uri); 1098bf80f4bSopenharmony_ci sceneResult.error = loadResult.success ? 0 : 1; 1108bf80f4bSopenharmony_ci sceneResult.message = BASE_NS::move(loadResult.error); 1118bf80f4bSopenharmony_ci sceneResult.data.reset(new GLTF2::SceneData(BASE_NS::move(loadResult.data))); 1128bf80f4bSopenharmony_ci return sceneResult; 1138bf80f4bSopenharmony_ci} 1148bf80f4bSopenharmony_ci 1158bf80f4bSopenharmony_ciISceneImporter::Ptr Gltf2::CreateSceneImporter(IEcs& ecs) 1168bf80f4bSopenharmony_ci{ 1178bf80f4bSopenharmony_ci CORE_ASSERT(engine_ && renderContext_); 1188bf80f4bSopenharmony_ci if (engine_ && renderContext_) { 1198bf80f4bSopenharmony_ci return ISceneImporter::Ptr { new GLTF2::Gltf2SceneImporter(*engine_, *renderContext_, ecs) }; 1208bf80f4bSopenharmony_ci } 1218bf80f4bSopenharmony_ci return nullptr; 1228bf80f4bSopenharmony_ci} 1238bf80f4bSopenharmony_ci 1248bf80f4bSopenharmony_ciISceneImporter::Ptr Gltf2::CreateSceneImporter(IEcs& ecs, IThreadPool& pool) 1258bf80f4bSopenharmony_ci{ 1268bf80f4bSopenharmony_ci CORE_ASSERT(engine_ && renderContext_); 1278bf80f4bSopenharmony_ci if (engine_ && renderContext_) { 1288bf80f4bSopenharmony_ci return ISceneImporter::Ptr { new GLTF2::Gltf2SceneImporter(*engine_, *renderContext_, ecs, pool) }; 1298bf80f4bSopenharmony_ci } 1308bf80f4bSopenharmony_ci return nullptr; 1318bf80f4bSopenharmony_ci} 1328bf80f4bSopenharmony_ci 1338bf80f4bSopenharmony_ciarray_view<const string_view> Gltf2::GetSupportedExtensions() const 1348bf80f4bSopenharmony_ci{ 1358bf80f4bSopenharmony_ci static constexpr string_view extensions[] = { "gltf", "glb" }; 1368bf80f4bSopenharmony_ci return extensions; 1378bf80f4bSopenharmony_ci} 1388bf80f4bSopenharmony_ci 1398bf80f4bSopenharmony_ci// IInterface 1408bf80f4bSopenharmony_ciconst IInterface* Gltf2::GetInterface(const Uid& uid) const 1418bf80f4bSopenharmony_ci{ 1428bf80f4bSopenharmony_ci if (uid == ISceneLoader::UID) { 1438bf80f4bSopenharmony_ci return static_cast<const ISceneLoader*>(this); 1448bf80f4bSopenharmony_ci } 1458bf80f4bSopenharmony_ci if (uid == IInterface::UID) { 1468bf80f4bSopenharmony_ci return static_cast<const IInterface*>(this); 1478bf80f4bSopenharmony_ci } 1488bf80f4bSopenharmony_ci return nullptr; 1498bf80f4bSopenharmony_ci} 1508bf80f4bSopenharmony_ci 1518bf80f4bSopenharmony_ciIInterface* Gltf2::GetInterface(const Uid& uid) 1528bf80f4bSopenharmony_ci{ 1538bf80f4bSopenharmony_ci if (uid == ISceneLoader::UID) { 1548bf80f4bSopenharmony_ci return static_cast<ISceneLoader*>(this); 1558bf80f4bSopenharmony_ci } 1568bf80f4bSopenharmony_ci if (uid == IInterface::UID) { 1578bf80f4bSopenharmony_ci return static_cast<IInterface*>(this); 1588bf80f4bSopenharmony_ci } 1598bf80f4bSopenharmony_ci return nullptr; 1608bf80f4bSopenharmony_ci} 1618bf80f4bSopenharmony_ci 1628bf80f4bSopenharmony_civoid Gltf2::Ref() {} 1638bf80f4bSopenharmony_ci 1648bf80f4bSopenharmony_civoid Gltf2::Unref() {} 1658bf80f4bSopenharmony_ci 1668bf80f4bSopenharmony_ci// Api exporting function. 1678bf80f4bSopenharmony_cibool Gltf2::SaveGLTF(IEcs& ecs, const string_view uri) 1688bf80f4bSopenharmony_ci{ 1698bf80f4bSopenharmony_ci CORE_ASSERT(engine_); 1708bf80f4bSopenharmony_ci if (engine_) { 1718bf80f4bSopenharmony_ci if (auto result = GLTF2::ExportGLTF(*engine_, ecs); result.success) { 1728bf80f4bSopenharmony_ci if (auto file = fileManager_.CreateFile(uri); file) { 1738bf80f4bSopenharmony_ci auto const ext = uri.rfind('.'); 1748bf80f4bSopenharmony_ci auto const extension = string_view(uri.data() + ext + 1); 1758bf80f4bSopenharmony_ci if (extension == "gltf") { 1768bf80f4bSopenharmony_ci for (auto const& buffer : result.data->buffers) { 1778bf80f4bSopenharmony_ci string dataFileUri = uri.substr(0, ext) + ".bin"; 1788bf80f4bSopenharmony_ci if (auto dataFile = fileManager_.CreateFile(dataFileUri); dataFile) { 1798bf80f4bSopenharmony_ci dataFile->Write(buffer->data.data(), buffer->data.size()); 1808bf80f4bSopenharmony_ci if (auto const path = dataFileUri.rfind('/'); path != string::npos) { 1818bf80f4bSopenharmony_ci dataFileUri.erase(0, path + 1); 1828bf80f4bSopenharmony_ci } 1838bf80f4bSopenharmony_ci buffer->uri = dataFileUri; 1848bf80f4bSopenharmony_ci } 1858bf80f4bSopenharmony_ci } 1868bf80f4bSopenharmony_ci GLTF2::SaveGLTF(*result.data, *file, engine_->GetVersion()); 1878bf80f4bSopenharmony_ci } else { 1888bf80f4bSopenharmony_ci GLTF2::SaveGLB(*result.data, *file, engine_->GetVersion()); 1898bf80f4bSopenharmony_ci } 1908bf80f4bSopenharmony_ci } else { 1918bf80f4bSopenharmony_ci result.error += "Failed to create file: " + uri; 1928bf80f4bSopenharmony_ci result.success = false; 1938bf80f4bSopenharmony_ci } 1948bf80f4bSopenharmony_ci return result.success; 1958bf80f4bSopenharmony_ci } else { 1968bf80f4bSopenharmony_ci return result.success; 1978bf80f4bSopenharmony_ci } 1988bf80f4bSopenharmony_ci } 1998bf80f4bSopenharmony_ci return false; 2008bf80f4bSopenharmony_ci} 2018bf80f4bSopenharmony_ciCORE3D_END_NAMESPACE() 202