• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "gltf2.h"
16 
17 #include <3d/gltf/gltf.h>
18 #include <3d/intf_graphics_context.h>
19 #include <core/ecs/intf_ecs.h>
20 #include <core/ecs/intf_entity_manager.h>
21 #include <core/intf_engine.h>
22 #include <core/io/intf_file_manager.h>
23 #include <core/log.h>
24 #include <core/plugin/intf_plugin_register.h>
25 #include <render/device/intf_gpu_resource_manager.h>
26 #include <render/intf_render_context.h>
27 
28 #include "data.h"
29 #include "gltf2_exporter.h"
30 #include "gltf2_importer.h"
31 #include "gltf2_loader.h"
32 
33 CORE3D_BEGIN_NAMESPACE()
34 using namespace BASE_NS;
35 using namespace CORE_NS;
36 
Gltf2(IGraphicsContext & graphicsContext)37 Gltf2::Gltf2(IGraphicsContext& graphicsContext)
38     : engine_(&(graphicsContext.GetRenderContext().GetEngine())), renderContext_(&graphicsContext.GetRenderContext()),
39       fileManager_(engine_->GetFileManager())
40 {}
41 
Gltf2(IFileManager & fileManager)42 Gltf2::Gltf2(IFileManager& fileManager) : fileManager_(fileManager) {}
43 
44 // Internal helper.
LoadGLTF(IFileManager & fileManager,const string_view uri)45 GLTFLoadResult LoadGLTF(IFileManager& fileManager, const string_view uri)
46 {
47     auto loadResult = GLTF2::LoadGLTF(fileManager, uri);
48     GLTFLoadResult result;
49     result.error = move(loadResult.error);
50     result.success = loadResult.success;
51     result.data = IGLTFData::Ptr { loadResult.data.release() };
52 
53     return result;
54 }
55 
56 // Api loading function.
LoadGLTF(const string_view uri)57 GLTFLoadResult Gltf2::LoadGLTF(const string_view uri)
58 {
59     return CORE3D_NS::LoadGLTF(fileManager_, uri);
60 }
61 
LoadGLTF(array_view<uint8_t const> data)62 GLTFLoadResult Gltf2::LoadGLTF(array_view<uint8_t const> data)
63 {
64     auto loadResult = GLTF2::LoadGLTF(fileManager_, data);
65     GLTFLoadResult result;
66     result.error = move(loadResult.error);
67     result.success = loadResult.success;
68     result.data = IGLTFData::Ptr { loadResult.data.release() };
69     return result;
70 }
71 
72 // Api import functions
ImportGltfScene(size_t sceneIndex,const IGLTFData & gltfData,const GLTFResourceData & gltfResourceData,IEcs & ecs,Entity rootEntity,GltfSceneImportFlags flags)73 Entity Gltf2::ImportGltfScene(size_t sceneIndex, const IGLTFData& gltfData, const GLTFResourceData& gltfResourceData,
74     IEcs& ecs, Entity rootEntity, GltfSceneImportFlags flags)
75 {
76     CORE_ASSERT(renderContext_);
77     if (renderContext_) {
78         const GLTF2::Data& data = static_cast<const GLTF2::Data&>(gltfData);
79         return ImportScene(renderContext_->GetDevice(), sceneIndex, data, gltfResourceData, ecs, rootEntity, 0U, flags);
80     }
81     return {};
82 }
83 
ImportGltfScene(const size_t sceneIndex,const IGLTFData & gltfData,const GLTFResourceData & gltfResourceData,IEcs & ecs,const uint32_t level,const GltfSceneImportFlags flags)84 Entity Gltf2::ImportGltfScene(const size_t sceneIndex, const IGLTFData& gltfData,
85     const GLTFResourceData& gltfResourceData, IEcs& ecs, const uint32_t level, const GltfSceneImportFlags flags)
86 {
87     CORE_ASSERT(renderContext_);
88     if (renderContext_) {
89         const GLTF2::Data& data = static_cast<const GLTF2::Data&>(gltfData);
90         return ImportScene(renderContext_->GetDevice(), sceneIndex, data, gltfResourceData, ecs, {}, level, flags);
91     }
92     return {};
93 }
94 
CreateGLTF2Importer(IEcs & ecs)95 IGLTF2Importer::Ptr Gltf2::CreateGLTF2Importer(IEcs& ecs)
96 {
97     CORE_ASSERT(engine_ && renderContext_);
98     if (engine_ && renderContext_) {
99         if (auto pool = ecs.GetThreadPool(); pool) {
100             return CreateGLTF2Importer(ecs, *pool);
101         }
102         auto ret = BASE_NS::make_unique<GLTF2::GLTF2Importer>(*engine_, *renderContext_, ecs);
103         if (ret->IsValid()) {
104             return IGLTF2Importer::Ptr { ret.release() };
105         }
106     }
107     return nullptr;
108 }
109 
CreateGLTF2Importer(IEcs & ecs,IThreadPool & pool)110 IGLTF2Importer::Ptr Gltf2::CreateGLTF2Importer(IEcs& ecs, IThreadPool& pool)
111 {
112     CORE_ASSERT(engine_ && renderContext_);
113     if (engine_ && renderContext_) {
114         auto ret = BASE_NS::make_unique<GLTF2::GLTF2Importer>(*engine_, *renderContext_, ecs, pool);
115         if (ret->IsValid()) {
116             return IGLTF2Importer::Ptr { ret.release() };
117         }
118     }
119     return nullptr;
120 }
121 
Load(string_view uri)122 ISceneLoader::Result Gltf2::Load(string_view uri)
123 {
124     ISceneLoader::Result sceneResult;
125     auto loadResult = GLTF2::LoadGLTF(fileManager_, uri);
126     sceneResult.error = loadResult.success ? 0 : 1;
127     sceneResult.message = BASE_NS::move(loadResult.error);
128     sceneResult.data.reset(new GLTF2::SceneData(BASE_NS::move(loadResult.data)));
129     return sceneResult;
130 }
131 
CreateSceneImporter(IEcs & ecs)132 ISceneImporter::Ptr Gltf2::CreateSceneImporter(IEcs& ecs)
133 {
134     CORE_ASSERT(engine_ && renderContext_);
135     if (engine_ && renderContext_) {
136         return ISceneImporter::Ptr { new GLTF2::Gltf2SceneImporter(*engine_, *renderContext_, ecs) };
137     }
138     return nullptr;
139 }
140 
CreateSceneImporter(IEcs & ecs,IThreadPool & pool)141 ISceneImporter::Ptr Gltf2::CreateSceneImporter(IEcs& ecs, IThreadPool& pool)
142 {
143     CORE_ASSERT(engine_ && renderContext_);
144     if (engine_ && renderContext_) {
145         return ISceneImporter::Ptr { new GLTF2::Gltf2SceneImporter(*engine_, *renderContext_, ecs, pool) };
146     }
147     return nullptr;
148 }
149 
GetSupportedExtensions() const150 array_view<const string_view> Gltf2::GetSupportedExtensions() const
151 {
152     static constexpr string_view extensions[] = { "gltf", "glb" };
153     return extensions;
154 }
155 
156 // IInterface
GetInterface(const Uid & uid) const157 const IInterface* Gltf2::GetInterface(const Uid& uid) const
158 {
159     if (uid == ISceneLoader::UID) {
160         return static_cast<const ISceneLoader*>(this);
161     }
162     if (uid == IInterface::UID) {
163         return static_cast<const IInterface*>(this);
164     }
165     return nullptr;
166 }
167 
GetInterface(const Uid & uid)168 IInterface* Gltf2::GetInterface(const Uid& uid)
169 {
170     if (uid == ISceneLoader::UID) {
171         return static_cast<ISceneLoader*>(this);
172     }
173     if (uid == IInterface::UID) {
174         return static_cast<IInterface*>(this);
175     }
176     return nullptr;
177 }
178 
Ref()179 void Gltf2::Ref() {}
180 
Unref()181 void Gltf2::Unref() {}
182 
183 // Api exporting function.
SaveGLTF(IEcs & ecs,const string_view uri)184 bool Gltf2::SaveGLTF(IEcs& ecs, const string_view uri)
185 {
186     CORE_ASSERT(engine_);
187     if (!engine_) {
188         return false;
189     }
190     auto file = fileManager_.CreateFile(uri);
191     if (!file) {
192         return false;
193     }
194     const auto result = GLTF2::ExportGLTF(*engine_, ecs);
195     if (!result.success) {
196         return false;
197     }
198 
199     auto const ext = uri.rfind('.');
200     auto const extension = string_view(uri.data() + ext + 1);
201     if (extension == "gltf") {
202         for (auto const& buffer : result.data->buffers) {
203             string dataFileUri = uri.substr(0, ext) + ".bin";
204             auto dataFile = fileManager_.CreateFile(dataFileUri);
205             if (!dataFile) {
206             }
207             dataFile->Write(buffer->data.data(), buffer->data.size());
208             if (auto const path = dataFileUri.rfind('/'); path != string::npos) {
209                 dataFileUri.erase(0, path + 1);
210             }
211             buffer->uri = dataFileUri;
212         }
213         GLTF2::SaveGLTF(*result.data, *file, engine_->GetVersion());
214     } else {
215         GLTF2::SaveGLB(*result.data, *file, engine_->GetVersion());
216     }
217 
218     return true;
219 }
220 CORE3D_END_NAMESPACE()
221