• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "lume_common.h"
17 
18 #include <dlfcn.h>
19 #include <string_view>
20 
21 #include <EGL/egl.h>
22 #include <EGL/eglext.h>
23 #include <GLES2/gl2.h>
24 #include <GLES2/gl2ext.h>
25 #include <GLES3/gl31.h>
26 
27 #include <3d/ecs/components/animation_track_component.h>
28 #include <3d/ecs/components/local_matrix_component.h>
29 #include <3d/ecs/components/material_component.h>
30 #include <3d/ecs/components/mesh_component.h>
31 #include <3d/ecs/components/name_component.h>
32 #include <3d/ecs/components/node_component.h>
33 #include <3d/ecs/components/render_handle_component.h>
34 #include <3d/ecs/components/render_mesh_batch_component.h>
35 #include <3d/ecs/components/render_mesh_component.h>
36 #include <3d/ecs/components/world_matrix_component.h>
37 #include <3d/ecs/systems/intf_morphing_system.h>
38 #include <3d/ecs/systems/intf_node_system.h>
39 #include <3d/ecs/systems/intf_render_preprocessor_system.h>
40 #include <3d/ecs/systems/intf_render_system.h>
41 #include <3d/implementation_uids.h>
42 #include <3d/util/intf_mesh_util.h>
43 #include <3d/util/intf_scene_util.h>
44 
45 #include <base/containers/array_view.h>
46 
47 #include <core/ecs/intf_system_graph_loader.h>
48 #include <core/implementation_uids.h>
49 #include <core/io/intf_file_manager.h>
50 #include <core/namespace.h>
51 #include <core/os/intf_platform.h>
52 #include <core/plugin/intf_plugin_register.h>
53 #include <core/property/intf_property_handle.h>
54 
55 #include <jpg/implementation_uids.h>
56 #include <png/implementation_uids.h>
57 
58 #include <render/datastore/intf_render_data_store_default_gpu_resource_data_copy.h>
59 #include <render/datastore/intf_render_data_store_default_staging.h>
60 #include <render/datastore/intf_render_data_store_manager.h>
61 #include <render/datastore/intf_render_data_store_pod.h>
62 #include <render/device/intf_gpu_resource_manager.h>
63 #include <render/device/intf_shader_manager.h>
64 #include <render/device/pipeline_state_desc.h>
65 #if CORE_HAS_GLES_BACKEND || CORE_HAS_GL_BACKEND
66 #include <render/gles/intf_device_gles.h>
67 #endif
68 #include <render/implementation_uids.h>
69 #include <render/intf_renderer.h>
70 #include <render/nodecontext/intf_render_node_graph_manager.h>
71 #if CORE_HAS_VULKAN_BACKEND
72 #include <render/vulkan/intf_device_vk.h>
73 #endif
74 
75 #include "3d_widget_adapter_log.h"
76 #include "graphics_manager.h"
77 #include "widget_trace.h"
78 
79 #include "include/gpu/vk/GrVkExtensions.h"
80 
81 #include "lume_render_config.h"
82 
83 #if _OPEN_BASIS_
84 #include "render_config.h"
85 #include "render_config_theme.h"
86 #endif
87 
88 #include "vulkan/vulkan_core.h"
89 #include "vulkan/vulkan_ohos.h"
90 
91 #include <parameter.h>
92 #include <parameters.h>
93 #include "param/sys_param.h"
94 
95 #if defined(CORE_DYNAMIC) && (CORE_DYNAMIC == 1)
96 
97 CORE_BEGIN_NAMESPACE()
98 /** Get plugin register */
99 IPluginRegister &(*GetPluginRegister)() = nullptr;
100 
101 /** Setup the plugin registry */
102 void (*CreatePluginRegistry)(const struct PlatformCreateInfo &platformCreateInfo) = nullptr;
103 
104 /** Get whether engine is build in debug mode */
105 bool (*IsDebugBuild)() = nullptr;
106 
107 /** Get version */
108 BASE_NS::string_view (*GetVersion)() = nullptr;
109 CORE_END_NAMESPACE()
110 #endif // CORE_DYNAMIC
111 
112 namespace OHOS::Render3D {
~LumeCommon()113 LumeCommon::~LumeCommon()
114 {
115     // explicit release resource before destructor
116 }
117 
UnloadEngineLib()118 void LumeCommon::UnloadEngineLib()
119 {
120     DeInitEngine();
121     if (libHandle_ == nullptr) {
122         return;
123     }
124     dlclose(libHandle_);
125     libHandle_ = nullptr;
126 
127     CORE_NS::GetPluginRegister = nullptr;
128     CORE_NS::CreatePluginRegistry = nullptr;
129     CORE_NS::IsDebugBuild = nullptr;
130     CORE_NS::GetVersion = nullptr;
131 }
132 
133 template <typename T>
LoadFunc(T & fn,const char * fName,void * handle)134 bool LoadFunc(T &fn, const char *fName, void *handle)
135 {
136     fn = reinterpret_cast<T>(dlsym(handle, fName));
137     if (fn == nullptr) {
138         WIDGET_LOGE("%s open %s", __func__, dlerror());
139         return false;
140     }
141     return true;
142 }
143 
LoadEngineLib()144 bool LumeCommon::LoadEngineLib()
145 {
146     if (libHandle_ != nullptr) {
147         WIDGET_LOGE("%s, already loaded", __func__);
148         return false;
149     }
150 
151     #define TO_STRING(name) #name
152     #define LIB_NAME(name) TO_STRING(name)
153     constexpr std::string_view lib { LIB_NAME(LIB_ENGINE_CORE)".so" };
154     libHandle_ = dlopen(lib.data(), RTLD_LAZY);
155 
156     if (libHandle_ == nullptr) {
157         WIDGET_LOGE("%s, open lib fail %s", __func__, dlerror());
158     }
159     #undef TO_STRING
160     #undef LIB_NAME
161 
162     #define LOAD_FUNC(fn, name) LoadFunc<decltype(fn)>(fn, name, libHandle_)
163     if (!(LOAD_FUNC(CORE_NS::CreatePluginRegistry,
164         "_ZN4Core20CreatePluginRegistryERKNS_18PlatformCreateInfoE")
165         && LOAD_FUNC(CORE_NS::GetPluginRegister, "_ZN4Core17GetPluginRegisterEv")
166         && LOAD_FUNC(CORE_NS::IsDebugBuild, "_ZN4Core12IsDebugBuildEv")
167         && LOAD_FUNC(CORE_NS::GetVersion, "_ZN4Core13GetVersionRevEv"))) {
168         return false;
169     }
170     #undef LOAD_FUNC
171 
172     return true;
173 }
174 
Clone(IEngine * proto)175 void LumeCommon::Clone(IEngine *proto)
176 {
177     auto p = static_cast<LumeCommon *>(proto);
178     engine_ = p->GetCoreEngine();
179     renderContext_ = p->GetRenderContext();
180     graphicsContext_ = p->GetGraphicsContext();
181     device_ = p->GetDevice();
182     activateProductBasis_ = p->activateProductBasis_;
183     activateProductContentBasis_ = p->activateProductContentBasis_;
184 }
185 
186 #if _OPEN_BASIS_
ActivateProductBasis(const std::string & bundleName)187 bool ActivateProductBasis(const std::string &bundleName)
188 {
189     auto &renderConfig = RenderConfig::GetInstance().productBasisHap_;
190     WIDGET_LOGD("ActivateProductBasishapPath: %s render config %s", bundleName.c_str(), renderConfig.c_str());
191     return bundleName.find(renderConfig.c_str()) != std::string::npos;
192 }
193 
ActivateProductContentBasis(const HapInfo & hapInfo)194 bool ActivateProductContentBasis(const HapInfo &hapInfo)
195 {
196     auto &renderConfigs = RenderConfigTheme::GetInstance().contentBasisHaps_;
197     for (auto iter = renderConfigs.begin(); iter != renderConfigs.end(); iter++) {
198         if (hapInfo.bundleName_.find(*iter) != std::string::npos ||
199             hapInfo.hapPath_.find(*iter) != std::string::npos) {
200             return true;
201         }
202     }
203     return false;
204 }
205 #endif
206 
InitEngine(EGLContext gfxContext,const PlatformData & data)207 bool LumeCommon::InitEngine(EGLContext gfxContext, const PlatformData &data)
208 {
209 #if _OPEN_BASIS_
210     activateProductBasis_ = ActivateProductBasis(data.hapInfo_.bundleName_);
211     if (!activateProductBasis_) {
212         activateProductContentBasis_ = ActivateProductContentBasis(data.hapInfo_);
213     }
214 #endif
215     return CreateCoreEngine(ToEnginePlatformData(data)) && CreateRenderContext(gfxContext) && CreateGfx3DContext() &&
216            GetDevice();
217 }
218 
CreateCoreEngine(const Core::PlatformCreateInfo & info)219 CORE_NS::IEngine::Ptr LumeCommon::CreateCoreEngine(const Core::PlatformCreateInfo &info)
220 {
221     CORE_NS::CreatePluginRegistry(info);
222     auto factory = CORE_NS::GetInstance<Core::IEngineFactory>(Core::UID_ENGINE_FACTORY);
223 
224     const Core::EngineCreateInfo engineCreateInfo{info,
225         {
226             "gltf_viewer",  // name
227             0,              // versionMajor
228             0,              // versionMinor
229             0,              // versionPatch
230         },
231         {}};
232     engine_ = factory->Create(engineCreateInfo);
233 
234     if (engine_ == nullptr) {
235         WIDGET_LOGE("3D engine create fail");
236         return nullptr;
237     }
238 
239     RegisterAssertPath();
240 
241     engine_->Init();
242 #if !USE_LIB_PNG_JPEG_DYNAMIC_PLUGIN
243     static constexpr CORE_NS::IImageLoaderManager::ImageLoaderTypeInfo PNG_LOADER {
244         { CORE_NS::IImageLoaderManager::ImageLoaderTypeInfo::UID },
245         nullptr,
246         BASE_NS::Uid { "dacbcb8d-60d6-4337-8295-7af99b517c1d" },
247         CreateImageLoaderLibPNGImage,
248         PNG_IMAGE_TYPES,
249     };
250     static constexpr CORE_NS::IImageLoaderManager::ImageLoaderTypeInfo JPEG_LOADER {
251         { CORE_NS::IImageLoaderManager::ImageLoaderTypeInfo::UID },
252         nullptr,
253         BASE_NS::Uid { "c5fb2284-561f-4078-8a00-74b82f161964" },
254         CreateImageLoaderLibJPEGImage,
255         JPEG_IMAGE_TYPES,
256     };
257     CORE_NS::GetPluginRegister().RegisterTypeInfo(PNG_LOADER);
258     CORE_NS::GetPluginRegister().RegisterTypeInfo(JPEG_LOADER);
259 #endif
260     return engine_;
261 }
262 
OnWindowChange(const TextureInfo & textureInfo)263 void LumeCommon::OnWindowChange(const TextureInfo &textureInfo)
264 {
265     textureInfo_ = textureInfo;
266     SetupCustomRenderTarget(textureInfo);
267     float widthScale = textureInfo.widthScale_;
268     float heightScale = textureInfo.heightScale_;
269     SetupCameraViewPort(textureInfo.width_ * widthScale, textureInfo.height_ * heightScale);
270 
271     if (customRender_) { // this moment customRender may not ready
272         customRender_->OnSizeChange(textureInfo.width_ * widthScale, textureInfo.height_ * heightScale);
273         customRender_->SetScaleInfo(widthScale, heightScale);
274     }
275 }
276 
CreateRenderContext(EGLContext gfxContext)277 RENDER_NS::IRenderContext::Ptr LumeCommon::CreateRenderContext(EGLContext gfxContext)
278 {
279     constexpr BASE_NS::Uid uid3dplugins[] = {
280     #if USE_LIB_PNG_JPEG_DYNAMIC_PLUGIN
281         JPGPlugin::UID_JPG_PLUGIN,
282         PNGPlugin::UID_PNG_PLUGIN,
283     #endif
284         RENDER_NS::UID_RENDER_PLUGIN,
285         CORE3D_NS::UID_3D_PLUGIN
286     };
287     CORE_NS::GetPluginRegister().LoadPlugins(uid3dplugins);
288 
289 #if _OPEN_BASIS_
290     if (activateProductBasis_ || activateProductContentBasis_) {
291         WIDGET_LOGD("activate product basis");
292         constexpr BASE_NS::Uid uidmbasisplugins[] = {
293             MbasisVfx::UID_MBASIS_VFX_PLUGIN
294         };
295         CORE_NS::GetPluginRegister().LoadPlugins(uidmbasisplugins);
296     }
297 #endif
298 
299     // Create render context
300     renderContext_ = CORE_NS::CreateInstance<RENDER_NS::IRenderContext>(
301         *engine_->GetInterface<Core::IClassFactory>(), RENDER_NS::UID_RENDER_CONTEXT);
302 
303     if (renderContext_ == nullptr) {
304         WIDGET_LOGE("lume Create render context fail");
305         return nullptr;
306     }
307 
308     Render::DeviceCreateInfo deviceCreateInfo;
309     std::string backendProp =
310         LumeRenderConfig::GetInstance().renderBackend_ == "force_vulkan"
311             ? "vulkan"
312             : ((activateProductBasis_ || activateProductContentBasis_) ? LumeRenderConfig::GetInstance().renderBackend_
313                                                                        : "gles");
314 
315     RENDER_NS::BackendExtraVk vkExtra;
316     RENDER_NS::BackendExtraGLES glesExtra;
317     if (backendProp == "vulkan") {
318         vkExtra.extensions.extensionNames.push_back(VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
319         vkExtra.extensions.extensionNames.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
320         vkExtra.extensions.extensionNames.push_back(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
321         vkExtra.extensions.extensionNames.push_back(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
322         vkExtra.extensions.extensionNames.push_back(VK_KHR_BIND_MEMORY_2_EXTENSION_NAME);
323         deviceCreateInfo.backendType = RENDER_NS::DeviceBackendType::VULKAN;
324         deviceCreateInfo.backendConfiguration = &vkExtra;
325     } else {
326         glesExtra.applicationContext = EGL_NO_CONTEXT;
327         glesExtra.sharedContext = gfxContext;
328         glesExtra.MSAASamples = 0;
329         glesExtra.depthBits = 0; // 24 bits of depth buffer.
330         deviceCreateInfo.backendType = Render::DeviceBackendType::OPENGLES;
331         deviceCreateInfo.backendConfiguration = &glesExtra;
332     }
333     WIDGET_LOGD("config backend %s", backendProp.c_str());
334     deviceCreateInfo.deviceConfiguration.bufferingCount = 5U;      // 5U: Maps to buffering count
335     deviceCreateInfo.deviceConfiguration.swapchainImageCount = 5U; // 5U: Maps to desired swapchain count
336     const RENDER_NS::RenderCreateInfo renderCreateInfo{
337         {
338             "core_gltf_viewer",  // name
339             1,
340             0,
341             0,
342         },
343         deviceCreateInfo,
344     };
345 
346     auto ret = renderContext_->Init(renderCreateInfo);
347     if (ret != RENDER_NS::RenderResultCode::RENDER_SUCCESS) {
348         WIDGET_LOGE("lume Init render context fail");
349         return nullptr;
350     }
351     return renderContext_;
352 }
353 
CreateGfx3DContext()354 CORE3D_NS::IGraphicsContext::Ptr LumeCommon::CreateGfx3DContext()
355 {
356     // Create an engine bound graphics context instance.
357     graphicsContext_ = CORE_NS::CreateInstance<CORE3D_NS::IGraphicsContext>(
358         *renderContext_->GetInterface<Core::IClassFactory>(), CORE3D_NS::UID_GRAPHICS_CONTEXT);
359 
360     if (graphicsContext_ == nullptr) {
361         WIDGET_LOGE("lume Create Graphic context fail");
362         return nullptr;
363     }
364 
365     graphicsContext_->Init();
366     return graphicsContext_;
367 }
368 
GetCoreEngine()369 CORE_NS::IEngine::Ptr LumeCommon::GetCoreEngine()
370 {
371     return engine_;
372 }
373 
GetRenderContext()374 RENDER_NS::IRenderContext::Ptr LumeCommon::GetRenderContext()
375 {
376     return renderContext_;
377 }
378 
GetGraphicsContext()379 CORE3D_NS::IGraphicsContext::Ptr LumeCommon::GetGraphicsContext()
380 {
381     return graphicsContext_;
382 }
383 
GetDevice()384 RENDER_NS::IDevice *LumeCommon::GetDevice()
385 {
386     if (renderContext_ == nullptr) {
387         WIDGET_LOGE("Get device but render context is empty");
388         return nullptr;
389     }
390 
391     device_ = &(renderContext_->GetDevice());
392 
393     if (device_ == nullptr) {
394         WIDGET_LOGE("Get device fail");
395     }
396 
397     return device_;
398 }
399 
DeInitEngine()400 void LumeCommon::DeInitEngine()
401 {
402     DestroySwapchain();
403     DestroyResource();
404     graphicsContext_ = nullptr;
405     renderContext_ = nullptr;
406     engine_ = nullptr;
407     ecs_ = nullptr;
408     device_ = nullptr;
409 }
410 
UpdateGeometries(const std::vector<std::shared_ptr<Geometry>> & shapes)411 void LumeCommon::UpdateGeometries(const std::vector<std::shared_ptr<Geometry>> &shapes)
412 {
413     for (auto shape = shapes_.begin(); shape != shapes_.end();) {
414         auto find = std::find_if(shapes.begin(), shapes.end(), [&shape](const std::shared_ptr<Geometry> &sNew) {
415             return (*shape)->GetName() == sNew->GetName();
416         });
417         if (find == shapes.end()) {
418             shape = shapes_.erase(shape);
419             continue;
420         }
421         shape++;
422     }
423     LoadCustGeometry(shapes);
424 }
425 
MultiSwapChain(const std::string & path)426 bool MultiSwapChain(const std::string &path)
427 {
428     return !(path.find("multiswapchain") == std::string::npos);
429 }
430 
UpdateCustomRender(const std::shared_ptr<CustomRenderDescriptor> & customRenderDescriptor)431 void LumeCommon::UpdateCustomRender(const std::shared_ptr<CustomRenderDescriptor> &customRenderDescriptor)
432 {
433     if (customRenderDescriptor) {
434         auto needsFrameCallback = customRenderDescriptor->NeedsFrameCallback();
435         useMultiSwapChain_ = MultiSwapChain(customRenderDescriptor->GetUri());
436         if (useMultiSwapChain_ || (!activateProductBasis_ && !activateProductContentBasis_)) {
437             customRender_ = std::make_shared<LumeCustomRender>(needsFrameCallback);
438         }
439 #if _OPEN_BASIS_
440         else {
441             LumeData data;
442             data.device_ = device_;
443             data.engine_ = engine_;
444             data.renderContext_ = renderContext_;
445             data.graphicsContext_ = graphicsContext_;
446             data.ecs_ = ecs_;
447             data.cameraEntity_ = cameraEntity_;
448             data.sceneEntity_ = sceneEntity_;
449             data.transformManager_ = transformManager_;
450             data.cameraManager_ = cameraManager_;
451             data.rccManager_ = sceneManager_;
452             data.materialManager_ = materialManager_;
453             data.meshManager_ = meshManager_;
454             data.nameManager_ = nameManager_;
455             data.uriManager_ = uriManager_;
456             data.gpuHandleManager_ = gpuHandleManager_;
457             data.nodeSystem_ = nodeSystem_;
458             data.renderMeshManager_ = renderMeshManager_;
459 
460             if (activateProductBasis_) {
461                 customRender_ = std::make_shared<ProductBasis>();
462                 auto &mbasis = static_cast<ProductBasis &>(*customRender_);
463                 mbasis.SetScaleInfo(textureInfo_.widthScale_, textureInfo_.heightScale_);
464                 mbasis.OnInit(data);
465             } else if (activateProductContentBasis_) {
466                 customRender_ = std::make_shared<ProductContentBasis>();
467                 auto &mbasis = static_cast<ProductContentBasis &>(*customRender_);
468                 mbasis.OnInit(data);
469             }
470         }
471 #endif
472         customRender_->Initialize({GetCoreEngine(),
473             GetGraphicsContext(),
474             GetRenderContext(),
475             ecs_,
476             textureInfo_.width_ * textureInfo_.widthScale_,
477             textureInfo_.height_ * textureInfo_.heightScale_,
478             useMultiSwapChain_});
479         customRender_->SetScaleInfo(textureInfo_.widthScale_, textureInfo_.heightScale_);
480         customRender_->LoadRenderNodeGraph(customRenderDescriptor->GetUri(), gpuResourceImgHandle_);
481         if (useMultiSwapChain_) {
482             CreateSwapchain(textureInfo_.nativeWindow_);
483         }
484         if (needsFrameCallback) {
485             needsFrameCallback_ = needsFrameCallback;
486         }
487     }
488 }
489 
UpdateShaderPath(const std::string & shaderPath)490 void LumeCommon::UpdateShaderPath(const std::string &shaderPath)
491 {
492     if (customRender_) {
493         customRender_->RegistorShaderPath(shaderPath);
494     }
495 }
496 
UpdateImageTexturePaths(const std::vector<std::string> & imageTextures)497 void LumeCommon::UpdateImageTexturePaths(const std::vector<std::string> &imageTextures)
498 {
499     if (customRender_) {
500         customRender_->LoadImages(imageTextures);
501     }
502 }
503 
UpdateShaderInputBuffer(const std::shared_ptr<OHOS::Render3D::ShaderInputBuffer> & shaderInputBuffer)504 void LumeCommon::UpdateShaderInputBuffer(const std::shared_ptr<OHOS::Render3D::ShaderInputBuffer> &shaderInputBuffer)
505 {
506     if (customRender_ && shaderInputBuffer) {
507         customRender_->UpdateShaderInputBuffer(shaderInputBuffer);
508         // When using multiple swapchain for the upper volume cloud, two LumeCommon instance are created,
509         // leading to call LumeCommon::DrawFrame() twice per frame.
510         // The second call in every frame causes abnormal effects for product scene drawn by basic engine
511         // Use useBasisEngine_ of GraphicsManager to record whether the product scene uses basic engine or not
512         // only if it is the default swapchain for HwProduct
513         if ((activateProductBasis_ || activateProductContentBasis_) && (!useMultiSwapChain_)) {
514             // set useBasisEngine_ of GraphicsManager with that modified by ProductBasis
515             GraphicsManager::GetInstance().SetUseBasisEngine(customRender_->GetUseBasisEngine());
516         }
517     }
518     hasShaderInput_ = true;
519 }
520 
DestroySceneNodeAndRes(CORE_NS::Entity & importedEntity,BASE_NS::vector<CORE3D_NS::GLTFResourceData> & res)521 void LumeCommon::DestroySceneNodeAndRes(
522     CORE_NS::Entity &importedEntity, BASE_NS::vector<CORE3D_NS::GLTFResourceData> &res)
523 {
524     if (!CORE_NS::EntityUtil::IsValid(importedEntity)) {
525         return;
526     }
527 
528     CORE3D_NS::INodeSystem &nodeSystem = *CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*ecs_);
529     CORE3D_NS::ISceneNode *sceneRoot = nodeSystem.GetNode(importedEntity);
530     if (sceneRoot) {
531         nodeSystem.DestroyNode(*sceneRoot);
532     }
533 
534     importedEntity = {};
535     res.clear();
536 }
537 
UnloadSceneModel()538 void LumeCommon::UnloadSceneModel()
539 {
540     // clean scene nodes
541     auto animationSystem = CORE_NS::GetSystem<CORE3D_NS::IAnimationSystem>(*ecs_);
542     for (auto animation : animations_) {
543         animationSystem->DestroyPlayback(animation);
544     }
545     animations_.clear();
546     DestroySceneNodeAndRes(importedSceneEntity_, importedSceneResources_);
547 }
548 
UnloadEnvModel()549 void LumeCommon::UnloadEnvModel()
550 {
551     WIDGET_LOGD("Unload enviroment model");
552     CORE_NS::ScopedHandle<CORE3D_NS::RenderConfigurationComponent> sceneComponent = sceneManager_->Write(sceneEntity_);
553     if (sceneComponent) {
554         auto envManager = CORE_NS::GetManager<CORE3D_NS::IEnvironmentComponentManager>(*ecs_);
555         envManager->Destroy(sceneComponent->environment);
556     }
557 
558     // clean scene nodes
559     DestroySceneNodeAndRes(importedEnvEntity_, importedEnvResources_);
560 }
561 
DestroyResource()562 void LumeCommon::DestroyResource()
563 {
564     WIDGET_SCOPED_TRACE("LumeCommon::UnloadModel");
565     if (!ecs_) {
566         return;
567     }
568     auto &ecs = *ecs_;
569     UnloadSceneModel();
570     UnloadEnvModel();
571 
572     // run garbage collection
573     ecs.ProcessEvents();
574 #if defined(MULTI_ECS_UPDATE_AT_ONCE) && (MULTI_ECS_UPDATE_AT_ONCE == 1)
575     if (ecs_) {
576         OHOS::Render3D::GraphicsManager::GetInstance().UnloadEcs(reinterpret_cast<void *>(ecs_.get()));
577         // gltf src update case crashes when MULTI_ECS_UPDATE_AT_ONCE is ON.
578     }
579 #endif
580     renderHandles_.clear();
581 }
582 
LoadAndImport(const GltfImportInfo & info,CORE_NS::Entity & importedEntity,BASE_NS::vector<CORE3D_NS::GLTFResourceData> & res)583 bool LumeCommon::LoadAndImport(
584     const GltfImportInfo &info, CORE_NS::Entity &importedEntity, BASE_NS::vector<CORE3D_NS::GLTFResourceData> &res)
585 {
586     WIDGET_SCOPED_TRACE_ARGS("LoadAndImport %s", info.fileName_);
587     auto &ecs = *ecs_;
588     auto gltf = graphicsContext_->GetGltf().LoadGLTF(info.fileName_);
589     if (!gltf.success) {
590         WIDGET_LOGE("LoadAndImport() Loaded '%s' with errors:\n%s", info.fileName_, gltf.error.c_str());
591         return false;
592     }
593     if (!gltf.data) {
594         WIDGET_LOGE("LoadAndImport gltf data is null. Error: %s ", gltf.error.c_str());
595         return false;
596     }
597 
598     auto importer = graphicsContext_->GetGltf().CreateGLTF2Importer(ecs);
599     importer->ImportGLTF(*gltf.data, info.resourceImportFlags_);
600 
601     auto const gltfImportResult = importer->GetResult();
602 
603     if (!gltfImportResult.success) {
604         WIDGET_LOGE("LoadAndImport() Importing of '%s' failed: %s", info.fileName_, gltfImportResult.error.c_str());
605         return false;
606     }
607 
608     res.push_back(gltfImportResult.data);
609 
610     // Import the default scene, or first scene if there is no default scene
611     // set.
612     size_t sceneIndex = gltf.data->GetDefaultSceneIndex();
613     if (sceneIndex == CORE3D_NS::CORE_GLTF_INVALID_INDEX && gltf.data->GetSceneCount() > 0) {
614         // Use first scene.
615         sceneIndex = 0;
616     }
617 
618     CORE_NS::Entity importedSceneEntity;
619     if (sceneIndex != CORE3D_NS::CORE_GLTF_INVALID_INDEX) {
620         importedSceneEntity = graphicsContext_->GetGltf().ImportGltfScene(
621             sceneIndex, *gltf.data, gltfImportResult.data, ecs, sceneEntity_, info.sceneImportFlags_);
622         if (CORE_NS::EntityUtil::IsValid(importedSceneEntity)) {
623             importedEntity = importedSceneEntity;
624         }
625     }
626 
627     // Assume that we always animate the 1st imported scene.
628     CORE_NS::Entity animationRoot = sceneEntity_;
629     if (info.target_ == GltfImportInfo::AnimateImportedScene && CORE_NS::EntityUtil::IsValid(importedSceneEntity)) {
630         // Scenes are self contained, so animate this particular imported
631         // scene.
632         animationRoot = importedSceneEntity;
633     }
634 
635     // Create animation playbacks.
636     if (!gltfImportResult.data.animations.empty()) {
637         CORE3D_NS::INodeSystem *nodeSystem = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(ecs);
638         assert(nodeSystem);
639 
640         CORE3D_NS::IAnimationSystem *animationSystem = CORE_NS::GetSystem<CORE3D_NS::IAnimationSystem>(ecs);
641         assert(animationSystem);
642         if (auto animationRootNode = nodeSystem->GetNode(animationRoot); animationRootNode) {
643             auto state = CORE3D_NS::AnimationComponent::PlaybackState::STOP;
644             for (const auto &animation : gltfImportResult.data.animations) {
645                 CORE3D_NS::IAnimationPlayback *playback =
646                     animationSystem->CreatePlayback(animation, *animationRootNode);
647                 if (playback) {
648                     playback->SetPlaybackState(state);
649                     playback->SetRepeatCount(-1);
650                     animations_.push_back(playback);
651                 }
652             }
653         }
654     }
655     return true;
656 }
657 
DrawFrame()658 void LumeCommon::DrawFrame()
659 {
660     WIDGET_SCOPED_TRACE("LumeCommon::DrawFrame");
661     // When using multiple swapchain for the upper volume cloud, two LumeCommon instance are created,
662     // leading to call LumeCommon::DrawFrame() twice per frame.
663     // The second call in every frame causes abnormal effects for product
664     // For the multiSwapchain of product, do not DrawFrame when using the product scene (i.e. useBasisEngine is true)
665     if ((activateProductBasis_ || activateProductContentBasis_) && useMultiSwapChain_ &&
666         GraphicsManager::GetInstance().GetUseBasisEngine()) {
667         return;
668     }
669     // Custom rendering must wait for ubo data to be uploaded
670     if (!loadedScene_ && !hasShaderInput_) {
671         WIDGET_LOGD("skip draw frame");
672         return;
673     }
674     auto *ecs = ecs_.get();
675     if (const bool needsRender = engine_->TickFrame(BASE_NS::array_view(&ecs, 1)); needsRender) {
676         // Collect render handles here
677         CollectRenderHandles();
678 
679         // Update custom renders
680         const Core::EngineTime et = engine_->GetEngineTime();
681         Tick(et.deltaTimeUs);
682         if (customRender_) {
683             customRender_->OnDrawFrame();
684         }
685 
686         GetRenderContext()->GetRenderer().RenderFrame(
687             BASE_NS::array_view(renderHandles_.data(), renderHandles_.size()));
688         if (textureInfo_.textureId_ == 0U && textureInfo_.nativeWindow_) {
689             return;
690         }
691         AddTextureMemoryBarrrier();
692     }
693 }
694 
Tick(const uint64_t deltaTime)695 void LumeCommon::Tick(const uint64_t deltaTime)
696 {
697     if (transformManager_ && sceneManager_ && CORE_NS::EntityUtil::IsValid(cameraEntity_)) {
698         orbitCamera_.Update(deltaTime);
699 
700         auto const position = orbitCamera_.GetCameraPosition();
701         auto const rotation = orbitCamera_.GetCameraRotation();
702         if (cameraUpdated_ || position != cameraPosition_ || (rotation.x != cameraRotation_.x) ||
703             (rotation.y != cameraRotation_.y) || (rotation.z != cameraRotation_.z) ||
704             (rotation.w != cameraRotation_.w)) {
705             cameraPosition_ = position;
706             cameraRotation_ = rotation;
707 
708             auto cameraTransform = transformManager_->Write(cameraEntity_);
709             cameraTransform->position = position;
710             cameraTransform->rotation = rotation;
711             cameraUpdated_ = false;
712         }
713     }
714 }
715 
OnTouchEvent(const PointerEvent & event)716 void LumeCommon::OnTouchEvent(const PointerEvent &event)
717 {
718     bool perspectiveCamera = true;
719     if (cameraManager_) {
720         if (auto cameraHandle = cameraManager_->Read(cameraEntity_); cameraHandle) {
721             perspectiveCamera = (cameraHandle->projection == CORE3D_NS::CameraComponent::Projection::PERSPECTIVE);
722         }
723     }
724 
725     if (perspectiveCamera && !activateProductBasis_ && !activateProductContentBasis_) {
726         orbitCamera_.HandlePointerEvent(event);
727     }
728 }
729 
OrbitCameraHelper()730 OrbitCameraHelper::OrbitCameraHelper()
731     : pressedButtonsBits_(0x0), touchPointerCount_(0), touchPointers_(), orbitDistance_(3.0f),
732       cameraTargetPosition_(0.0f, 0.0f, 0.0f), cameraRotation_(0.0f, 0.0f, 0.0f, 1.0f)
733 {}
734 
SetOrbitFromEye(const BASE_NS::Math::Vec3 & eyePosition,const BASE_NS::Math::Quat & rotation,float orbitDistance)735 void OrbitCameraHelper::SetOrbitFromEye(
736     const BASE_NS::Math::Vec3 &eyePosition, const BASE_NS::Math::Quat &rotation, float orbitDistance)
737 {
738     orbitDistance_ = orbitDistance;
739     cameraRotation_ = rotation;
740     const BASE_NS::Math::Vec3 toTargetVec = cameraRotation_ * BASE_NS::Math::Vec3(0.0f, 0.0f, -orbitDistance_);
741     cameraTargetPosition_ = eyePosition + toTargetVec;
742 }
743 
SetOrbitFromTarget(const BASE_NS::Math::Vec3 & targetPosition,const BASE_NS::Math::Quat & rotation,float orbitDistance)744 void OrbitCameraHelper::SetOrbitFromTarget(
745     const BASE_NS::Math::Vec3 &targetPosition, const BASE_NS::Math::Quat &rotation, float orbitDistance)
746 {
747     orbitDistance_ = orbitDistance;
748     cameraRotation_ = rotation;
749     cameraTargetPosition_ = targetPosition;
750 }
751 
GetCameraPosition()752 BASE_NS::Math::Vec3 OrbitCameraHelper::GetCameraPosition()
753 {
754     return cameraRotation_ * BASE_NS::Math::Vec3(0.0f, 0.0f, orbitDistance_) + cameraTargetPosition_;
755 }
756 
GetCameraRotation()757 BASE_NS::Math::Quat OrbitCameraHelper::GetCameraRotation()
758 {
759     return cameraRotation_;
760 }
761 
Update(uint64_t)762 void OrbitCameraHelper::Update(uint64_t /* delta */)
763 {
764     // Simple stupid pinch zoom (dolly) gesture.
765     if (touchPointerCount_ == 2) {
766         const BASE_NS::Math::Vec2 pos0(touchPointers_[0].x_, touchPointers_[0].y_);
767         const BASE_NS::Math::Vec2 pos1(touchPointers_[1].x_, touchPointers_[1].y_);
768 
769         const BASE_NS::Math::Vec2 prevPos0(
770             touchPointers_[0].x_ - touchPointers_[0].deltaX_, touchPointers_[0].y_ - touchPointers_[0].deltaY_);
771         const BASE_NS::Math::Vec2 prevPos1(
772             touchPointers_[1].x_ - touchPointers_[1].deltaX_, touchPointers_[1].y_ - touchPointers_[1].deltaY_);
773         const float deltaDistance = BASE_NS::Math::distance(prevPos0, prevPos1) - BASE_NS::Math::distance(pos0, pos1);
774 
775         const float sensitivity = 10.0f;
776         orbitDistance_ *= 1.0f + (deltaDistance * sensitivity);
777         if (orbitDistance_ < 0.01f) {
778             orbitDistance_ = 0.01f;
779         }
780 
781         touchPointers_[0].deltaX_ = 0.0f;
782         touchPointers_[0].deltaY_ = 0.0f;
783         touchPointers_[1].deltaX_ = 0.0f;
784         touchPointers_[1].deltaY_ = 0.0f;
785     }
786 }
787 
ResetPointerEvents()788 void OrbitCameraHelper::ResetPointerEvents()
789 {
790     touchPointerCount_ = 0;
791 }
792 
OnPress(const PointerEvent & event)793 void OrbitCameraHelper::OnPress(const PointerEvent &event)
794 {
795     if (event.buttonIndex_ >= 0) {
796         pressedButtonsBits_ |= 1 << event.buttonIndex_;
797     }
798 
799     const bool isMouse = (event.pointerId_ == -1);
800     if (isMouse) {
801         return;
802     }
803 
804     touchPointerCount_++;
805     if (touchPointerCount_ <= 2 && touchPointerCount_ > 0) {
806         touchPointers_[touchPointerCount_ - 1] = event;
807     }
808 
809     // Initialize midpoint on second press with default values
810     if (touchPointerCount_ == 2) {
811         midPoint_.x_ = 0;
812         midPoint_.y_ = 0;
813         midPoint_.deltaX_ = 0;
814         midPoint_.deltaY_ = 0;
815     }
816 }
817 
OnRelease(const PointerEvent & event)818 void OrbitCameraHelper::OnRelease(const PointerEvent &event)
819 {
820     if (event.buttonIndex_ >= 0) {
821         pressedButtonsBits_ &= ~(1 << event.buttonIndex_);
822     }
823 
824     const bool isMouse = (event.pointerId_ == -1);
825     if (isMouse) {
826         return;
827     }
828 
829     for (int i = 0; i < 2; ++i) {
830         if (touchPointers_[i].pointerId_ == event.pointerId_) {
831             touchPointers_[i].pointerId_ = -1;
832             break;
833         }
834     }
835     touchPointerCount_--;
836     if (touchPointerCount_ < 0) {
837         touchPointerCount_ = 0;
838     }
839     // Touch released. Reset midPoint_ to default values
840     if (touchPointerCount_ < 2) {
841         midPoint_.x_ = 0;
842         midPoint_.y_ = 0;
843         midPoint_.deltaX_ = 0;
844         midPoint_.deltaY_ = 0;
845     }
846 }
847 
UpdateCameraRotation(float dx,float dy)848 void OrbitCameraHelper::UpdateCameraRotation(float dx, float dy)
849 {
850     BASE_NS::Math::Quat rotationX = BASE_NS::Math::AngleAxis(dx, BASE_NS::Math::Vec3(0.0f, -1.0f, 0.0f));
851     BASE_NS::Math::Quat rotationY =
852         BASE_NS::Math::AngleAxis(dy, cameraRotation_ * BASE_NS::Math::Vec3(-1.0f, 0.0f, 0.0f));
853     cameraRotation_ = BASE_NS::Math::Normalize(rotationX * rotationY * cameraRotation_);
854 }
855 
OnMove(const PointerEvent & event)856 void OrbitCameraHelper::OnMove(const PointerEvent &event)
857 {
858     if (touchPointerCount_ == 1) {
859         touchPointers_[0] = event;
860 
861         // Orbit camera with single touch.
862         const float sensitivity = 25.0f;
863         UpdateCameraRotation(sensitivity * event.deltaX_, sensitivity * event.deltaY_);
864     }
865 
866     if (touchPointerCount_ == 2) {
867         // Pan camera with double touch (will apply this for both pointers).
868         PointerEvent newMidPoint;
869 
870         auto t1 = touchPointers_[0];
871         auto t2 = touchPointers_[1];
872 
873         if (t1.pointerId_ == event.pointerId_) {
874             t1 = event;
875         } else {
876             t2 = event;
877         }
878 
879         auto offset = t1.x_ == std::min(t2.x_, t1.x_) ? t1 : t2;
880 
881         newMidPoint.x_ = (abs(t2.x_ - t1.x_) / 2) + offset.x_;
882         newMidPoint.y_ = (abs(t2.y_ - t1.y_) / 2) + offset.y_;
883 
884         // Mid point at default value (0, 0), assume value of current mid point
885         if (midPoint_.x_ == 0 && midPoint_.y_ == 0) {
886             midPoint_.x_ = newMidPoint.x_;
887             midPoint_.y_ = newMidPoint.y_;
888         }
889 
890         float dX = newMidPoint.x_ - midPoint_.x_;
891         float dY = newMidPoint.y_ - midPoint_.y_;
892 
893         if (dX != 0 || dY != 0) {
894             const float sensitivity = 3.0f;
895             UpdateCameraRotation(sensitivity * dX, sensitivity * dY);
896         }
897 
898         midPoint_.x_ = newMidPoint.x_;
899         midPoint_.y_ = newMidPoint.y_;
900         midPoint_.deltaX_ = dX;
901         midPoint_.deltaY_ = dY;
902 
903         for (int i = 0; i < 2; ++i) {
904             if (touchPointers_[i].pointerId_ == event.pointerId_) {
905                 touchPointers_[i] = event;
906                 break;
907             }
908         }
909     }
910 }
911 
HandlePointerEvent(const PointerEvent & event)912 void OrbitCameraHelper::HandlePointerEvent(const PointerEvent &event)
913 {
914     switch (event.eventType_) {
915         case PointerEventType::PRESSED:
916             OnPress(event);
917             break;
918 
919         case PointerEventType::RELEASED:
920         case PointerEventType::CANCELLED:
921             OnRelease(event);
922             break;
923 
924         case PointerEventType::MOVED:
925             OnMove(event);
926             break;
927         default:
928             break;
929     }
930 }
931 
932 #if defined(MULTI_ECS_UPDATE_AT_ONCE) && (MULTI_ECS_UPDATE_AT_ONCE == 1)
DeferDraw()933 void LumeCommon::DeferDraw()
934 {
935     WIDGET_SCOPED_TRACE("LumeCommon::DeferDraw");
936 
937     if (renderHandles_.empty()) {
938         needsRedraw_ = true;
939         CollectRenderHandles();
940     } else {
941         needsRedraw_ = false;
942     }
943 
944     const Core::EngineTime et = engine_->GetEngineTime();
945     // Update app scene.
946     Tick(et.deltaTimeUs);
947 
948     // Update custom renders
949     if (customeRender_) {
950         customeRender_->OnDrawFrame();
951     }
952 
953     OHOS::Render3D::GraphicsManager::GetInstance().DrawFrame(
954         reinterpret_cast<void *>(ecs_.get()), reinterpret_cast<void *>(&renderHandles_));
955 }
956 
DrawMultiEcs(const std::unordered_map<void *,void * > & ecss)957 void LumeCommon::DrawMultiEcs(const std::unordered_map<void *, void *> &ecss)
958 {
959     if (ecss.size() == 0) {
960         WIDGET_LOGW("ACE-3D LumeCommon::DrawMultiEcs() - No dirty views");
961         return;
962     }
963 
964     BASE_NS::vector<RENDER_NS::RenderHandleReference> handles;
965     BASE_NS::vector<CORE_NS::IEcs *> ecsInputs;
966 
967     for (auto &key : ecss) {
968         CORE_NS::IEcs *ecs = reinterpret_cast<CORE_NS::IEcs *>(key.first);
969         ecsInputs.push_back(ecs);
970 
971         BASE_NS::vector<RENDER_NS::RenderHandleReference> *dirty =
972             reinterpret_cast<BASE_NS::vector<RENDER_NS::RenderHandleReference> *>(key.second);
973         handles.insert(handles.end(), dirty->begin(), dirty->end());
974     }
975 
976     if (engine_->TickFrame(BASE_NS::array_view(ecsInputs.data(), ecsInputs.size()))) {
977         GetRenderContext()->GetRenderer().RenderFrame(BASE_NS::array_view(handles.data(), handles.size()));
978     }
979 }
980 #endif
981 
CollectRenderHandles()982 void LumeCommon::CollectRenderHandles()
983 {
984     renderHandles_.clear();
985 
986     if (customRender_) {
987         auto rngs = customRender_->GetRenderHandles();
988         for (auto r : rngs) {
989             renderHandles_.push_back(r);
990         }
991     }
992 
993     if (!renderHandles_.empty()) {
994         return;
995     }
996 
997     auto *ecs = ecs_.get();
998     BASE_NS::array_view<const RENDER_NS::RenderHandleReference> main = GetGraphicsContext()->GetRenderNodeGraphs(*ecs);
999     if (main.size() == 0) {
1000         // GLTF resource handles not ready yet in lume. Do not schedule for render.
1001         return;
1002     }
1003 
1004     // Order of handles matters to Lume engine. Add custom render last to be drawn on top of GLTF resources
1005     for (auto handle : main) {
1006         renderHandles_.push_back(handle);
1007     }
1008 }
1009 
CreateEcs(uint32_t key)1010 void LumeCommon::CreateEcs(uint32_t key)
1011 {
1012     if (ecs_ != nullptr) {
1013         return;
1014     }
1015     key_ = key;
1016     ecs_ = engine_->CreateEcs();
1017 }
1018 
LoadSystemGraph(BASE_NS::string sysGraph)1019 void LumeCommon::LoadSystemGraph(BASE_NS::string sysGraph)
1020 {
1021     auto &ecs = *ecs_;
1022     static constexpr const RENDER_NS::IShaderManager::ShaderFilePathDesc desc{ "shaders://" };
1023     GetRenderContext()->GetDevice().GetShaderManager().LoadShaderFiles(desc);
1024     auto graphFactory = CORE_NS::GetInstance<CORE_NS::ISystemGraphLoaderFactory>(CORE_NS::UID_SYSTEM_GRAPH_LOADER);
1025     auto systemGraphLoader = graphFactory->Create(engine_->GetFileManager());
1026     auto result = systemGraphLoader->Load(sysGraph, ecs);
1027     if (!result.success) {
1028         WIDGET_LOGE("load system graph %s error %s", sysGraph.c_str(), result.error.c_str());
1029     }
1030 
1031     // multi ecs needs unique DataStore name, otherwise only one RenderSystem created
1032     std::string tmpPrefix = "EngineInstance:" + std::to_string(key_);
1033     BASE_NS::string dataStorePrefix = tmpPrefix.c_str();
1034 
1035     if (auto renderPreprocessorSystem = CORE_NS::GetSystem<CORE3D_NS::IRenderPreprocessorSystem>(ecs)) {
1036         CORE3D_NS::IRenderPreprocessorSystem::Properties rsProperties;
1037         rsProperties.dataStoreScene = dataStorePrefix + "RenderDataStoreDefaultScene";
1038         rsProperties.dataStoreCamera = dataStorePrefix + "RenderDataStoreDefaultCamera";
1039         rsProperties.dataStoreLight = dataStorePrefix + "RenderDataStoreDefaultLight";
1040         rsProperties.dataStoreMaterial = dataStorePrefix + "RenderDataStoreDefaultMaterial";
1041         rsProperties.dataStoreMorph = dataStorePrefix + "RenderDataStoreMorph";
1042         rsProperties.dataStorePrefix = dataStorePrefix;
1043 
1044         if (auto scopedHandle = CORE_NS::ScopedHandle<CORE3D_NS::IRenderPreprocessorSystem::Properties>(
1045                 renderPreprocessorSystem->GetProperties())) {
1046             *scopedHandle = rsProperties;
1047         }
1048     }
1049 
1050     ecs.Initialize();
1051     transformManager_ = CORE_NS::GetManager<CORE3D_NS::ITransformComponentManager>(ecs);
1052     cameraManager_ = CORE_NS::GetManager<CORE3D_NS::ICameraComponentManager>(ecs);
1053     sceneManager_ = CORE_NS::GetManager<CORE3D_NS::IRenderConfigurationComponentManager>(ecs);
1054 
1055     materialManager_ = CORE_NS::GetManager<CORE3D_NS::IMaterialComponentManager>(ecs);
1056     meshManager_ = CORE_NS::GetManager<CORE3D_NS::IMeshComponentManager>(ecs);
1057     nameManager_ = CORE_NS::GetManager<CORE3D_NS::INameComponentManager>(ecs);
1058     uriManager_ = CORE_NS::GetManager<CORE3D_NS::IUriComponentManager>(ecs);
1059     gpuHandleManager_ = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(ecs);
1060     nodeSystem_ = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(ecs);
1061     renderMeshManager_ = CORE_NS::GetManager<CORE3D_NS::IRenderMeshComponentManager>(ecs);
1062 
1063     lightManager_ = CORE_NS::GetManager<CORE3D_NS::ILightComponentManager>(ecs);
1064     postprocessManager_ = CORE_NS::GetManager<CORE3D_NS::IPostProcessComponentManager>(ecs);
1065 }
1066 
CreateScene()1067 void LumeCommon::CreateScene()
1068 {
1069     auto nodeSystem = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*ecs_);
1070     assert(nodeSystem);
1071 
1072     if (auto sceneHandle = sceneManager_->Read(sceneEntity_); sceneHandle) {
1073         return;
1074     }
1075 
1076     CORE3D_NS::ISceneNode *rootNode = nodeSystem->CreateNode();
1077     sceneEntity_ = rootNode->GetEntity();
1078     sceneManager_->Create(sceneEntity_);
1079 
1080     CORE_NS::ScopedHandle<CORE3D_NS::RenderConfigurationComponent> sceneComponent = sceneManager_->Write(sceneEntity_);
1081     sceneComponent->environment = sceneEntity_;
1082     sceneComponent->renderingFlags = CORE3D_NS::RenderConfigurationComponent::SceneRenderingFlagBits::CREATE_RNGS_BIT;
1083 }
1084 
CreateEnvScene(CORE3D_NS::EnvironmentComponent::Background type)1085 void LumeCommon::CreateEnvScene(CORE3D_NS::EnvironmentComponent::Background type)
1086 {
1087     auto sceneComponent = sceneManager_->Write(sceneEntity_);
1088 
1089     auto envManager = CORE_NS::GetManager<CORE3D_NS::IEnvironmentComponentManager>(*ecs_);
1090     if (auto envDataHandle = envManager->Read(sceneComponent->environment); envDataHandle) {
1091         return;
1092     }
1093 
1094     envManager->Create(sceneComponent->environment);
1095     auto envDataHandle = envManager->Write(sceneComponent->environment);
1096     if (!envDataHandle) {
1097         WIDGET_LOGE("ACE-3D LumeCommon::LoadBackgroundMode get env manager fail");
1098         return;
1099     }
1100     CORE3D_NS::EnvironmentComponent &envComponent = *envDataHandle;
1101     envComponent.background = type;
1102 
1103     const BASE_NS::Math::Vec3 defaultIrradianceCoefficients[]{{1.0f, 1.0f, 1.0f},
1104         {0.0f, 0.0f, 0.0f},
1105         {0.0f, 0.0f, 0.0f},
1106         {0.0f, 0.0f, 0.0f},
1107         {0.0f, 0.0f, 0.0f},
1108         {0.0f, 0.0f, 0.0f},
1109         {0.0f, 0.0f, 0.0f},
1110         {0.0f, 0.0f, 0.0f},
1111         {0.0f, 0.0f, 0.0f}};
1112     const size_t countOfSh = BASE_NS::countof(envComponent.irradianceCoefficients);
1113     CORE_ASSERT(countOfSh == BASE_NS::countof(defaultIrradianceCoefficients));
1114     std::copy(
1115         defaultIrradianceCoefficients, defaultIrradianceCoefficients + countOfSh, envComponent.irradianceCoefficients);
1116 
1117     if (auto cameraHandle = cameraManager_->Write(cameraEntity_); cameraHandle) {
1118         if (type == CORE3D_NS::EnvironmentComponent::Background::NONE) {
1119             cameraHandle->pipelineFlags |= CORE3D_NS::CameraComponent::CLEAR_COLOR_BIT;
1120         }
1121 
1122         const auto environments = static_cast<CORE_NS::IComponentManager::ComponentId>(envManager->GetComponentCount());
1123 
1124         for (CORE_NS::IComponentManager::ComponentId id = 0; id < environments; ++id) {
1125             const auto entity = envManager->GetEntity(id);
1126             if (entity == sceneComponent->environment) {
1127                 continue;
1128             }
1129             cameraHandle->environment = entity;
1130             break;
1131         }
1132     }
1133 }
1134 
CreateCamera()1135 void LumeCommon::CreateCamera()
1136 {
1137     if (auto cameraReadHandle = cameraManager_->Read(cameraEntity_); cameraReadHandle) {
1138         return;
1139     }
1140 
1141     const auto &sceneUtil = graphicsContext_->GetSceneUtil();
1142     cameraEntity_ = sceneUtil.CreateCamera(*ecs_, cameraPosition_, cameraRotation_, zNear_, zFar_, fovDegrees_);
1143     const float distance = BASE_NS::Math::Magnitude(cameraPosition_);
1144     orbitCamera_.SetOrbitFromEye(cameraPosition_, cameraRotation_, distance);
1145 
1146     if (auto cameraWriteHandle = cameraManager_->Write(cameraEntity_); cameraWriteHandle) {
1147         cameraWriteHandle->sceneFlags |=
1148             CORE3D_NS::CameraComponent::MAIN_CAMERA_BIT | CORE3D_NS::CameraComponent::ACTIVE_RENDER_BIT;
1149         cameraWriteHandle->pipelineFlags |= CORE3D_NS::CameraComponent::MSAA_BIT;
1150         cameraWriteHandle->renderingPipeline = CORE3D_NS::CameraComponent::RenderingPipeline::FORWARD;
1151     }
1152 }
1153 
LoadEnvModel(const std::string & modelPath,BackgroundType type)1154 void LumeCommon::LoadEnvModel(const std::string &modelPath, BackgroundType type)
1155 {
1156     UnloadEnvModel();
1157 
1158     GltfImportInfo file{modelPath.c_str(),
1159         GltfImportInfo::AnimateImportedScene,
1160         CORE3D_NS::CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL,
1161         CORE3D_NS::CORE_GLTF_IMPORT_COMPONENT_FLAG_BITS_ALL};
1162 
1163     auto loadResult = LoadAndImport(file, importedEnvEntity_, importedEnvResources_);
1164     if (!loadResult) {
1165         WIDGET_LOGE("3D model load fail");
1166     }
1167 
1168     CORE3D_NS::EnvironmentComponent::Background engineBackgourndType;
1169     switch (type) {
1170         case BackgroundType::TRANSPARENT:
1171             engineBackgourndType = CORE3D_NS::EnvironmentComponent::Background::NONE;
1172             break;
1173         case BackgroundType::CUBE_MAP:
1174         default:
1175             engineBackgourndType = CORE3D_NS::EnvironmentComponent::Background::CUBEMAP;
1176             break;
1177     }
1178 
1179     if (auto sceneHandle = sceneManager_->Read(sceneEntity_); !sceneHandle) {
1180         CreateScene();
1181     }
1182     CreateEnvScene(engineBackgourndType);
1183 }
1184 
LoadSceneModel(const std::string & modelPath)1185 void LumeCommon::LoadSceneModel(const std::string &modelPath)
1186 {
1187     uint32_t resourceImportFlags = CORE3D_NS::CORE_GLTF_IMPORT_RESOURCE_FLAG_BITS_ALL;
1188     uint32_t componentImportFlags = CORE3D_NS::CORE_GLTF_IMPORT_COMPONENT_FLAG_BITS_ALL;
1189     componentImportFlags &= ~CORE3D_NS::CORE_GLTF_IMPORT_COMPONENT_ENVIRONMENT;
1190     UnloadSceneModel();
1191     CreateScene();
1192     GltfImportInfo file{
1193         modelPath.c_str(), GltfImportInfo::AnimateImportedScene, resourceImportFlags, componentImportFlags};
1194     loadedScene_ = LoadAndImport(file, importedSceneEntity_, importedSceneResources_);
1195     if (!loadedScene_) {
1196         WIDGET_LOGE("3D environment model load fail");
1197     }
1198 }
1199 
SetupPostprocess()1200 void LumeCommon::SetupPostprocess()
1201 {
1202     if (enablePostprocess_ == false) {
1203         return;
1204     }
1205 
1206     CORE_NS::IEntityManager &em = ecs_->GetEntityManager();
1207     postprocessEntity_ = em.Create();
1208     postprocessManager_->Create(postprocessEntity_);
1209     auto postProcessHandle = postprocessManager_->Write(postprocessEntity_);
1210 
1211     if (!postProcessHandle) {
1212         return;
1213     }
1214 
1215     CORE3D_NS::PostProcessComponent &postProcess = *postProcessHandle;
1216     postProcess.enableFlags = RENDER_NS::PostProcessConfiguration::ENABLE_BLOOM_BIT |
1217                               RENDER_NS::PostProcessConfiguration::ENABLE_TONEMAP_BIT |
1218                               RENDER_NS::PostProcessConfiguration::ENABLE_COLOR_FRINGE_BIT;
1219     postProcess.bloomConfiguration.thresholdHard = 0.9f;
1220     postProcess.bloomConfiguration.thresholdSoft = 2.0f;
1221     postProcess.bloomConfiguration.amountCoefficient = 2.0f;
1222     postProcess.colorFringeConfiguration.coefficient = 1.5f;
1223     postProcess.colorFringeConfiguration.distanceCoefficient = 2.5f;
1224 }
1225 
UpdateGLTFAnimations(const std::vector<std::shared_ptr<GLTFAnimation>> & animations)1226 void LumeCommon::UpdateGLTFAnimations(const std::vector<std::shared_ptr<GLTFAnimation>> &animations)
1227 {
1228     gltfAnimations_.clear();
1229     gltfAnimations_ = animations;
1230     animProgress_ = false;
1231     ProcessGLTFAnimations();
1232 }
1233 
ProcessGLTFAnimations()1234 void LumeCommon::ProcessGLTFAnimations()
1235 {
1236     if (animations_.empty()) {
1237         WIDGET_LOGE("ProcessGLTFAnimations animations empty");
1238         return;
1239     }
1240 
1241     for (auto &gltfAnimation : gltfAnimations_) {
1242         std::string name = gltfAnimation->GetName();
1243         if (name == "") {
1244             UpdateSingleGLTFAnimation(0, gltfAnimation);
1245             WIDGET_LOGE("3D GLTFAnimations name empty");
1246             continue;
1247         }
1248 
1249         int index = FindGLTFAnimationIndex(name);
1250         if (index == -1) {
1251             continue;
1252         }
1253         UpdateSingleGLTFAnimation(index, gltfAnimation);
1254     }
1255 }
1256 
FindGLTFAnimationIndex(const std::string & name)1257 int LumeCommon::FindGLTFAnimationIndex(const std::string &name)
1258 {
1259     const char *animNameChr = name.c_str();
1260     uint32_t index = 0;
1261     for (auto animation : animations_) {
1262         BASE_NS::string_view getName = animation->GetName();
1263         int r = getName.compare(animNameChr);
1264         if (r == 0) {
1265             // Animation is found.
1266             break;
1267         }
1268         index++;
1269     }
1270 
1271     if (index == animations_.size()) {
1272         return -1;
1273     } else {
1274         return index;
1275     }
1276 }
1277 
UpdateSingleGLTFAnimation(int index,const std::shared_ptr<GLTFAnimation> & gltfAnimation)1278 void LumeCommon::UpdateSingleGLTFAnimation(int index, const std::shared_ptr<GLTFAnimation> &gltfAnimation)
1279 {
1280     CORE3D_NS::AnimationComponent::PlaybackState state;
1281     switch (gltfAnimation->GetState()) {
1282         case AnimationState::STOP:
1283             state = CORE3D_NS::AnimationComponent::PlaybackState::STOP;
1284             break;
1285         case AnimationState::PAUSE:
1286             state = CORE3D_NS::AnimationComponent::PlaybackState::PAUSE;
1287             break;
1288         case AnimationState::PLAY:
1289         default:
1290             state = CORE3D_NS::AnimationComponent::PlaybackState::PLAY;
1291             animProgress_ = true;
1292             break;
1293     }
1294     animations_[index]->SetPlaybackState(state);
1295 
1296     if (gltfAnimation->GetRepeatCount() == -1) {
1297         animations_[index]->SetRepeatCount(-1);  // infinite
1298     } else {
1299         animations_[index]->SetRepeatCount(gltfAnimation->GetRepeatCount());
1300     }
1301 
1302     if (gltfAnimation->GetReverse()) {
1303         animations_[index]->SetSpeed(-gltfAnimation->GetSpeed());
1304     } else {
1305         animations_[index]->SetSpeed(gltfAnimation->GetSpeed());
1306     }
1307 
1308     if (gltfAnimation->GetDuration() != -1.0) {
1309         animations_[index]->SetDuration(gltfAnimation->GetDuration());
1310     }
1311 }
1312 
CreateGeometry(CORE_NS::Entity & sceneEntity_,CORE_NS::Entity & entityMesh,const std::shared_ptr<Geometry> & geometryEntity,CORE3D_NS::INodeSystem & nodeSystem,CORE3D_NS::IRenderMeshComponentManager & rmm)1313 void CreateGeometry(CORE_NS::Entity &sceneEntity_, CORE_NS::Entity &entityMesh,
1314     const std::shared_ptr<Geometry> &geometryEntity, CORE3D_NS::INodeSystem &nodeSystem,
1315     CORE3D_NS::IRenderMeshComponentManager &rmm)
1316 {
1317     auto pos = geometryEntity->GetPosition();
1318 
1319     auto scene = nodeSystem.GetNode(sceneEntity_);
1320     auto node = nodeSystem.CreateNode();
1321     node->SetName(geometryEntity->GetName().c_str());
1322     node->SetPosition({pos.GetX(), pos.GetY(), pos.GetZ()});
1323     node->SetParent(*scene);
1324 
1325     auto entity = node->GetEntity();
1326     rmm.Create(entity);
1327 
1328     auto mesh = rmm.Get(entity);
1329     mesh.mesh = entityMesh;
1330     rmm.Set(entity, mesh);
1331 }
1332 
DestroyNode(CORE_NS::Entity & sceneEntity,std::shared_ptr<Geometry> & shape,CORE3D_NS::INodeSystem & nodeSystem)1333 void DestroyNode(CORE_NS::Entity &sceneEntity, std::shared_ptr<Geometry> &shape, CORE3D_NS::INodeSystem &nodeSystem)
1334 {
1335     auto sceneNode = nodeSystem.GetNode(sceneEntity);
1336     auto shapeNode = sceneNode->LookupNodeByName(shape->GetName().c_str());
1337     if (shapeNode) {
1338         nodeSystem.DestroyNode(*shapeNode);
1339     } else {
1340         WIDGET_LOGW("Failed to remove: %s", shape->GetName().c_str());
1341     }
1342 }
1343 
CreateNode(CORE_NS::Entity & sceneEntity,CORE_NS::IEcs::Ptr & ecs,CORE3D_NS::IMeshUtil & meshUtil,const std::shared_ptr<Geometry> & entity,const CORE_NS::Entity & materialEntity,CORE3D_NS::INodeSystem & nodeSystem,CORE3D_NS::IRenderMeshComponentManager & rmm)1344 void CreateNode(CORE_NS::Entity &sceneEntity, CORE_NS::IEcs::Ptr &ecs, CORE3D_NS::IMeshUtil &meshUtil,
1345     const std::shared_ptr<Geometry> &entity, const CORE_NS::Entity &materialEntity, CORE3D_NS::INodeSystem &nodeSystem,
1346     CORE3D_NS::IRenderMeshComponentManager &rmm)
1347 {
1348     switch (entity->GetType()) {
1349         case GeometryType::CUBE: {
1350             auto &cube = static_cast<Cube &>(*entity);
1351             auto mesh = meshUtil.GenerateCubeMesh(
1352                 *ecs, entity->GetName().c_str(), materialEntity, cube.GetWidth(), cube.GetHeight(), cube.GetDepth());
1353             CreateGeometry(sceneEntity, mesh, entity, nodeSystem, rmm);
1354             break;
1355         }
1356         case GeometryType::SPHARE: {
1357             auto &sphere = static_cast<Sphere &>(*entity);
1358             auto mesh = meshUtil.GenerateSphereMesh(*ecs,
1359                 entity->GetName().c_str(),
1360                 materialEntity,
1361                 sphere.GetRadius(),
1362                 sphere.GetRings(),
1363                 sphere.GetSectors());
1364             CreateGeometry(sceneEntity, mesh, entity, nodeSystem, rmm);
1365             break;
1366         }
1367         case GeometryType::CONE: {
1368             auto &cone = static_cast<Cone &>(*entity);
1369             auto mesh = meshUtil.GenerateConeMesh(
1370                 *ecs, entity->GetName().c_str(), materialEntity, cone.GetRadius(), cone.GetLength(), cone.GetSectors());
1371             CreateGeometry(sceneEntity, mesh, entity, nodeSystem, rmm);
1372             break;
1373         }
1374         default:
1375             break;
1376     }
1377 }
1378 
UpdateNodePosition(CORE_NS::Entity & sceneEntity,std::shared_ptr<Geometry> & shape,CORE3D_NS::INodeSystem & nodeSystem)1379 void UpdateNodePosition(
1380     CORE_NS::Entity &sceneEntity, std::shared_ptr<Geometry> &shape, CORE3D_NS::INodeSystem &nodeSystem)
1381 {
1382     auto sceneNode = nodeSystem.GetNode(sceneEntity);
1383     auto shapeNode = sceneNode->LookupNodeByName(shape->GetName().c_str());
1384     if (shapeNode) {
1385         auto pos = shape->GetPosition();
1386         shapeNode->SetPosition({pos.GetX(), pos.GetY(), pos.GetZ()});
1387         return;
1388     }
1389 
1390     WIDGET_LOGW("Failed to Update: %s", shape->GetName().c_str());
1391 }
1392 
LoadCustGeometry(const std::vector<std::shared_ptr<Geometry>> & shapes)1393 void LumeCommon::LoadCustGeometry(const std::vector<std::shared_ptr<Geometry>> &shapes)
1394 {
1395     if (!(sceneManager_ && sceneManager_->Read(sceneEntity_))) {
1396         WIDGET_LOGE("ACE-3D LumeCommon::LoadCustGeometry() Scene is not set up yet");
1397         return;
1398     }
1399 
1400     auto rmm = CORE_NS::GetManager<CORE3D_NS::IRenderMeshComponentManager>(*ecs_);
1401     auto nodeSystem = CORE_NS::GetSystem<CORE3D_NS::INodeSystem>(*ecs_);
1402     if (!rmm || !nodeSystem) {
1403         WIDGET_LOGE("render mesh component %d nodeSystem %d", !!rmm, !!nodeSystem);
1404         return;
1405     }
1406 
1407     CORE3D_NS::MaterialComponent desc;
1408     desc.textures[CORE3D_NS::MaterialComponent::TextureIndex::MATERIAL].factor.z = 0.0f;
1409     desc.textures[CORE3D_NS::MaterialComponent::TextureIndex::MATERIAL].factor.y = 1.0f;
1410 
1411     // default material
1412     const CORE_NS::Entity materialEntity = ecs_->GetEntityManager().Create();
1413     auto materialManager = CORE_NS::GetManager<CORE3D_NS::IMaterialComponentManager>(*ecs_);
1414     materialManager->Set(materialEntity, desc);
1415 
1416     CORE3D_NS::IMeshUtil &meshUtil = graphicsContext_->GetMeshUtil();
1417 
1418     for (auto &shape : shapes) {
1419         auto find = std::find_if(shapes_.begin(), shapes_.end(), [&shape](const std::shared_ptr<Geometry> &sOld) {
1420             return shape->GetName() == sOld->GetName();
1421         });
1422         if (find != shapes_.end()) {
1423             // shape already exists on scene, update
1424             const std::shared_ptr<OHOS::Render3D::Geometry> &oldShape = *find;
1425 
1426             bool updateEntity = !(shape->Equals(*oldShape));
1427             bool updatePosition = !(shape->PositionEquals(*oldShape));
1428             if (updateEntity) {
1429                 // destroy node, and recreate it
1430                 DestroyNode(sceneEntity_, *find, *nodeSystem);
1431                 CreateNode(sceneEntity_, ecs_, meshUtil, shape, materialEntity, *nodeSystem, *rmm);
1432             } else if (updatePosition) {
1433                 // just reposition the node
1434                 UpdateNodePosition(sceneEntity_, *find, *nodeSystem);
1435             } else {
1436                 // just update the map
1437             }
1438             shapesMap_[shape->GetName()] = shape;
1439         } else {
1440             // Shape does not exist on scene, create
1441             // update map
1442             CreateNode(sceneEntity_, ecs_, meshUtil, shape, materialEntity, *nodeSystem, *rmm);
1443             shapes_.push_back(shape);
1444         }
1445     }
1446 }
1447 
DestroySwapchain()1448 bool LumeCommon::DestroySwapchain()
1449 {
1450     WIDGET_LOGD("LumeCommon::DestroySwapchin");
1451 #ifdef CREATE_SURFACE
1452     EGLBoolean ret = EGL_TRUE;
1453     if (!device_) {
1454         WIDGET_LOGE("no device but has eglSurface");
1455         return false;
1456     }
1457 
1458     if (eglSurface_ == EGL_NO_SURFACE) {
1459         return true;
1460     }
1461 
1462     if (swapchainHandle_ && device_) {
1463         device_->DestroySwapchain(swapchainHandle_);
1464     }
1465 
1466     const auto &data = static_cast<const RENDER_NS::DevicePlatformDataGLES &>(device_->GetPlatformData());
1467     ret = eglDestroySurface(data.display, eglSurface_);
1468     eglSurface_ = EGL_NO_SURFACE;
1469 #endif
1470     // need check destroy swapchain
1471     swapchainHandle_ = {};
1472     return true;
1473 }
1474 
InitializeScene(uint32_t key)1475 void LumeCommon::InitializeScene(uint32_t key)
1476 {
1477     CreateEcs(key);
1478     BASE_NS::string sysGraph = LumeRenderConfig::GetInstance().systemGraph_.c_str();
1479     LoadSystemGraph(sysGraph);
1480     CreateCamera();
1481 }
1482 
CreateSwapchain(void * nativeWindow)1483 bool LumeCommon::CreateSwapchain(void *nativeWindow)
1484 {
1485     WIDGET_SCOPED_TRACE("LumeCommon::CreateSwapchain");
1486     WIDGET_LOGD("LumeCommon::CreateSwapchain");
1487 #ifdef CREATE_SURFACE
1488     if (nativeWindow == nullptr) {
1489         return false;
1490     }
1491     DestroySwapchain();
1492 
1493     auto window = reinterpret_cast<EGLNativeWindowType>(nativeWindow);
1494     EGLint COLOR_SPACE = 0;
1495     EGLint COLOR_SPACE_SRGB = 0;
1496     const auto &data = static_cast<const RENDER_NS::DevicePlatformDataGLES &>(device_->GetPlatformData());
1497     EGLConfig config = data.config;
1498 
1499     bool hasSRGB = true;
1500     if ((data.majorVersion > 1) || ((data.majorVersion == 1) && (data.minorVersion > 4))) {
1501         COLOR_SPACE = EGL_GL_COLORSPACE;
1502         COLOR_SPACE_SRGB = EGL_GL_COLORSPACE_SRGB;
1503     } else if (data.hasColorSpaceExt) {
1504         COLOR_SPACE = EGL_GL_COLORSPACE_KHR;
1505         COLOR_SPACE_SRGB = EGL_GL_COLORSPACE_SRGB_KHR;
1506     } else {
1507         hasSRGB = false;
1508     }
1509 
1510     if (hasSRGB) {
1511         const EGLint attribs[] = {COLOR_SPACE, COLOR_SPACE_SRGB, EGL_NONE};
1512         eglSurface_ = eglCreateWindowSurface(data.display, config, window, attribs);
1513         if (eglSurface_ == EGL_NO_SURFACE) {
1514             // okay fallback to whatever colorformat
1515             EGLint error = eglGetError();
1516             // EGL_BAD_ATTRIBUTE is generated if attrib_list contains an invalid window attribute or if an
1517             // attribute value is not recognized or is out of range
1518             WIDGET_LOGD("fallback to linear egl surface for reason %d", error);  // EGL_BAD_ATTRIBUTE 0x3004
1519             hasSRGB = false;
1520         }
1521     }
1522 
1523     if (!hasSRGB) {
1524         eglSurface_ = eglCreateWindowSurface(data.display, config, window, nullptr);
1525         if (eglSurface_ != EGL_NO_SURFACE) {
1526             WIDGET_LOGI("create linear egl surface success");
1527         } else {
1528             EGLint error = eglGetError();
1529             WIDGET_LOGE("fail to create linear egl surface for reason %d", error);
1530         }
1531     }
1532     RENDER_NS::SwapchainCreateInfo swapchainCreateInfo{
1533         reinterpret_cast<uint64_t>(eglSurface_),
1534         RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_COLOR_BUFFER_BIT |
1535             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT,
1536     };
1537 #endif
1538 
1539     RENDER_NS::SwapchainCreateInfo swapchainCreateInfo{
1540         // reinterpret_cast<uint64_t>(eglSurface_),
1541         0U,
1542         RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_COLOR_BUFFER_BIT |
1543             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_DEPTH_BUFFER_BIT |
1544             RENDER_NS::SwapchainFlagBits::CORE_SWAPCHAIN_SRGB_BIT,
1545         RENDER_NS::ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
1546         {reinterpret_cast<uintptr_t>(nativeWindow),
1547             reinterpret_cast<uintptr_t>(
1548                 static_cast<const RENDER_NS::DevicePlatformDataGLES &>(device_->GetPlatformData()).display)}};
1549 
1550     if (swapchainHandle_) {
1551         device_->DestroySwapchain(swapchainHandle_);
1552         swapchainHandle_ = {};
1553     }
1554     // as pair of lume_custom_render.cpp LoadRenderNodeGraph func, create swapchain name by filename.
1555     if (customRender_ && useMultiSwapChain_) {
1556         swapchainHandle_ = device_->CreateSwapchainHandle(
1557             swapchainCreateInfo, swapchainHandle_, customRender_->GetSwapchainName().c_str());
1558     } else {
1559         swapchainHandle_ = device_->CreateSwapchainHandle(swapchainCreateInfo, swapchainHandle_, {});
1560     }
1561     return eglSurface_ != EGL_NO_SURFACE;
1562 }
1563 
SetupCustomRenderTarget(const TextureInfo & info)1564 void LumeCommon::SetupCustomRenderTarget(const TextureInfo &info)
1565 {
1566     if (ecs_ == nullptr) {
1567         WIDGET_LOGE("ecs has not created");
1568         return;
1569     }
1570 
1571     auto &ecs = *ecs_;
1572     auto cameraComponent = cameraManager_->Write(cameraEntity_);
1573     auto *rhcManager = CORE_NS::GetManager<CORE3D_NS::IRenderHandleComponentManager>(ecs);
1574     cameraComponent->customColorTargets.clear();
1575     CORE_NS::EntityReference imageEntity;
1576 
1577     if (info.textureId_ == 0U && info.nativeWindow_) {
1578         // need check recreate window
1579         CreateSwapchain(info.nativeWindow_);
1580         imageEntity = GetOrCreateEntityReference(ecs.GetEntityManager(), *rhcManager, swapchainHandle_);
1581     } else {
1582         auto imageEntity =
1583             CORE3D_NS::GetOrCreateEntityReference(ecs.GetEntityManager(), *rhcManager, SetupGpuImageTarget());
1584         auto depthEntity =
1585             CORE3D_NS::GetOrCreateEntityReference(ecs.GetEntityManager(), *rhcManager, SetupGpuDepthTarget());
1586     }
1587     cameraComponent->postProcess = postprocessEntity_;
1588     cameraComponent->customColorTargets.emplace_back(std::move(imageEntity));
1589 }
1590 
UpdateLights(const std::vector<std::shared_ptr<OHOS::Render3D::Light>> & lights)1591 void LumeCommon::UpdateLights(const std::vector<std::shared_ptr<OHOS::Render3D::Light>> &lights)
1592 {
1593     const auto &sceneUtil = graphicsContext_->GetSceneUtil();
1594     auto &ecs = *ecs_;
1595 
1596     for (auto i = 0U; i < lights.size(); i++) {
1597         BASE_NS::Math::Vec3 position;
1598         BASE_NS::Math::Quat rotation;
1599         auto &light = lights[i];
1600         GetLightPositionAndRotation(light, position, rotation);
1601         // Check and update exisiting light entity or create a new light entity.
1602         if (lightEntities_.size() > i) {
1603             if (auto oldLC = lightManager_->Write(lightEntities_.at(i)); oldLC) {
1604                 oldLC->type = static_cast<CORE3D_NS::LightComponent::Type>(light->GetLightType());
1605                 oldLC->color = BASE_NS::Math::Vec3(
1606                     light->GetLightColor().GetX(), light->GetLightColor().GetY(), light->GetLightColor().GetZ());
1607                 oldLC->intensity = light->GetLightIntensity();
1608                 oldLC->shadowEnabled = light->GetLightShadow();
1609 
1610                 CORE3D_NS::TransformComponent tc;
1611                 tc.position = position;
1612                 tc.rotation = rotation;
1613                 transformManager_->Set(lightEntities_.at(i), tc);
1614             } else {
1615                 WIDGET_LOGE("update exsiting light error");
1616             }
1617         } else {
1618             CORE3D_NS::LightComponent lc;
1619             lc.type = static_cast<CORE3D_NS::LightComponent::Type>(light->GetLightType());
1620             lc.intensity = light->GetLightIntensity();
1621             lc.shadowEnabled = light->GetLightShadow();
1622             lc.color = BASE_NS::Math::Vec3(
1623                 light->GetLightColor().GetX(), light->GetLightColor().GetY(), light->GetLightColor().GetZ());
1624             lightEntities_.push_back(sceneUtil.CreateLight(ecs, lc, position, rotation));
1625         }
1626     }
1627 }
1628 
SetupGpuImageTarget()1629 RENDER_NS::RenderHandleReference LumeCommon::SetupGpuImageTarget()
1630 {
1631     std::string name = "tex_img" + std::to_string(key_);
1632     if (gpuResourceImgHandle_) {
1633         return gpuResourceImgHandle_;
1634     }
1635 
1636     auto imageDesc = GetImageDesc();
1637     RENDER_NS::ImageDescGLES glesImageDesc;
1638 
1639     glesImageDesc.type = GL_TEXTURE_2D;
1640     glesImageDesc.image = textureInfo_.textureId_;
1641     glesImageDesc.internalFormat = GL_RGBA8_OES;
1642     glesImageDesc.format = imageDesc.format;
1643     glesImageDesc.dataType = GL_UNSIGNED_BYTE;
1644     glesImageDesc.bytesperpixel = 4;
1645 
1646     gpuResourceImgHandle_ = GetRenderContext()->GetDevice().GetGpuResourceManager().CreateView(
1647         BASE_NS::string_view(name.c_str()), imageDesc, glesImageDesc);
1648 
1649     WIDGET_LOGD("ACE-3D LumeCommon::SetupGpuImageTarget texture %d", textureInfo_.textureId_);
1650     return gpuResourceImgHandle_;
1651 }
1652 
SetupGpuDepthTarget()1653 RENDER_NS::RenderHandleReference LumeCommon::SetupGpuDepthTarget()
1654 {
1655     std::string name = "depth_target" + std::to_string(key_);
1656     if (gpuDepthTargetHandle_) {
1657         return gpuDepthTargetHandle_;
1658     }
1659 
1660     auto imageDesc = GetImageDesc();
1661     imageDesc.format = Base::Format::BASE_FORMAT_D24_UNORM_S8_UINT;
1662     imageDesc.usageFlags = Render::ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
1663 
1664     gpuDepthTargetHandle_ = GetRenderContext()->GetDevice().GetGpuResourceManager().Create(name.c_str(), imageDesc);
1665 
1666     return gpuDepthTargetHandle_;
1667 }
1668 
GetImageDesc()1669 RENDER_NS::GpuImageDesc LumeCommon::GetImageDesc()
1670 {
1671     RENDER_NS::GpuImageDesc imageDesc;
1672     imageDesc.imageType = Render::ImageType::CORE_IMAGE_TYPE_2D;
1673     imageDesc.imageViewType = Render::ImageViewType::CORE_IMAGE_VIEW_TYPE_2D;
1674     imageDesc.format = Base::Format::BASE_FORMAT_R8G8B8A8_SRGB;
1675     imageDesc.imageTiling = Render::ImageTiling::CORE_IMAGE_TILING_OPTIMAL;
1676     imageDesc.usageFlags = Render::ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1677     imageDesc.memoryPropertyFlags = Render::MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1678     imageDesc.createFlags = 0;
1679     imageDesc.engineCreationFlags =
1680         RENDER_NS::EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS |
1681         RENDER_NS::EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS;
1682     imageDesc.width = textureInfo_.width_;
1683     imageDesc.height = textureInfo_.height_;
1684     imageDesc.depth = 1;
1685 
1686     return imageDesc;
1687 }
1688 
SetupCameraViewProjection(float zNear,float zFar,float fovDegrees)1689 void LumeCommon::SetupCameraViewProjection(float zNear, float zFar, float fovDegrees)
1690 {
1691     zNear_ = zNear;
1692     zFar_ = zFar;
1693     fovDegrees_ = fovDegrees;
1694 }
1695 
SetupCameraTransform(const OHOS::Render3D::Position & position,const OHOS::Render3D::Vec3 & lookAt,const OHOS::Render3D::Vec3 & up,const OHOS::Render3D::Quaternion & rotation)1696 void LumeCommon::SetupCameraTransform(const OHOS::Render3D::Position &position, const OHOS::Render3D::Vec3 &lookAt,
1697     const OHOS::Render3D::Vec3 &up, const OHOS::Render3D::Quaternion &rotation)
1698 {
1699     if (position.GetIsAngular()) {
1700         float radius = position.GetDistance();
1701         float x = (radius * BASE_NS::Math::sin((BASE_NS::Math::DEG2RAD * position.GetX())));
1702         float z = (radius * BASE_NS::Math::cos((BASE_NS::Math::DEG2RAD * position.GetZ())));
1703         float y = (radius * BASE_NS::Math::sin((BASE_NS::Math::DEG2RAD * position.GetY())));
1704         cameraPosition_ = BASE_NS::Math::Vec3(x, y, z);
1705     } else {
1706         cameraPosition_ = BASE_NS::Math::Vec3(position.GetX(), position.GetY(), position.GetZ());
1707     }
1708 
1709     if (IsValidQuaternion(rotation)) {
1710         // App provided rotation. So use it directly.
1711         cameraRotation_ = BASE_NS::Math::Quat(rotation.GetX(), rotation.GetY(), rotation.GetZ(), rotation.GetW());
1712     } else {
1713         // Use LookAtRh API.
1714         BASE_NS::Math::Vec3 look(lookAt.GetX(), lookAt.GetY(), lookAt.GetZ());
1715         BASE_NS::Math::Vec3 upTmp(up.GetX(), up.GetY(), up.GetZ());
1716         BASE_NS::Math::Mat4X4 mat = BASE_NS::Math::LookAtRh(cameraPosition_, look, upTmp);
1717         float determinantOut;
1718         BASE_NS::Math::Mat4X4 invMat = BASE_NS::Math::Inverse(mat, determinantOut);
1719         // Workaround for Lume LookAtRh API invalid matrix for specific data. Eg:
1720         // This workaround can handle only limited cases. Proper fix should come form Lume engine.
1721         // Eg., test data:
1722         // pos(0.0, 3.0, 0.0), lookAt(0.0, 0.0, 0.0), up(0.0, 1.0, 0.0)
1723         // pos(3.0, 0.0, 0.0), lookAt(0.0, 0.0, 0.0), up(1.0, 0.0, 0.0)
1724         // pos(0.0, 0.0, 3.0), lookAt(0.0, 0.0, 0.0), up(0.0, 0.0, 1.0)
1725         if (std::abs(determinantOut) < 0.001f) {
1726             WIDGET_LOGW("ACE-3D Inverse LookAt matrix is invalid.");
1727             BASE_NS::Math::Vec3 modifiedPos(cameraPosition_.x, cameraPosition_.y, cameraPosition_.z + 0.0001f);
1728             mat = BASE_NS::Math::LookAtRh(modifiedPos, look, upTmp);
1729             invMat = BASE_NS::Math::Inverse(mat, determinantOut);
1730         }
1731         BASE_NS::Math::Vec3 scale;
1732         BASE_NS::Math::Quat orientation;
1733         BASE_NS::Math::Vec3 translation;
1734         BASE_NS::Math::Vec3 skew;
1735         BASE_NS::Math::Vec4 perspective;
1736         BASE_NS::Math::Decompose(invMat, scale, orientation, translation, skew, perspective);
1737         cameraPosition_ = translation;
1738         cameraRotation_ = orientation;
1739     }
1740     // Update the Orbit camera.
1741     const float distance = BASE_NS::Math::Magnitude(cameraPosition_);
1742     orbitCamera_.SetOrbitFromEye(cameraPosition_, cameraRotation_, distance);
1743     cameraUpdated_ = true;
1744     // Needed to update Transform manager's cameraTransform.
1745 }
1746 
NeedsRepaint()1747 bool LumeCommon::NeedsRepaint()
1748 {
1749     auto isAnimating = animProgress_ || needsFrameCallback_;
1750     auto handlesNotReady = renderHandles_.size() == 0 || needsRedraw_;
1751     return isAnimating || handlesNotReady;
1752 }
1753 
SetupCameraViewPort(uint32_t width,uint32_t height)1754 void LumeCommon::SetupCameraViewPort(uint32_t width, uint32_t height)
1755 {
1756     if (cameraManager_ == nullptr || graphicsContext_ == nullptr) {
1757         return;
1758     }
1759 
1760     auto cameraComponent = cameraManager_->Read(cameraEntity_);
1761     if (!cameraComponent) {
1762         WIDGET_LOGE("ACE-3D LumeCommon::SetUpCameraViewPort get camera component error");
1763         return;
1764     }
1765 
1766     autoAspect_ = (cameraComponent->aspect <= 0.0f);
1767     originalYfov_ = cameraComponent->yFov;
1768     graphicsContext_->GetSceneUtil().UpdateCameraViewport(
1769         *ecs_, cameraEntity_, {width, height}, autoAspect_, originalYfov_, orthoScale_);
1770 }
1771 
IsValidQuaternion(const OHOS::Render3D::Quaternion & quat)1772 bool LumeCommon::IsValidQuaternion(const OHOS::Render3D::Quaternion &quat)
1773 {
1774     auto max = std::numeric_limits<float>::max();
1775     if (quat == Quaternion(max, max, max, max)) {
1776         return false;
1777     }
1778     return true;
1779 }
1780 
AddTextureMemoryBarrrier()1781 void LumeCommon::AddTextureMemoryBarrrier()
1782 {
1783     WIDGET_SCOPED_TRACE("LumeCommon::AddTextureMemoryBarrrier");
1784     AutoRestore scope;
1785     auto lumeContext =
1786         static_cast<const RENDER_NS::DevicePlatformDataGLES &>(GetRenderContext()->GetDevice().GetPlatformData())
1787             .context;
1788 
1789     auto disp = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1790     auto res = eglMakeCurrent(disp, EGL_NO_SURFACE, EGL_NO_SURFACE, lumeContext);
1791 
1792     if (!res) {
1793         WIDGET_LOGE("Make lume context error %d", eglGetError());
1794         return;
1795     }
1796 
1797     glMemoryBarrierByRegion(GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1798     auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1799     glWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, 0);
1800     glDeleteSync(sync);
1801 }
1802 
GetLightPositionAndRotation(const std::shared_ptr<Light> & light,BASE_NS::Math::Vec3 & position,BASE_NS::Math::Quat & rotation)1803 void LumeCommon::GetLightPositionAndRotation(
1804     const std::shared_ptr<Light> &light, BASE_NS::Math::Vec3 &position, BASE_NS::Math::Quat &rotation)
1805 {
1806     if (!light) {
1807         WIDGET_LOGE("GetLightPositionAndRotation() light is null");
1808         return;
1809     }
1810 
1811     if (light->GetPosition().GetIsAngular()) {
1812         float radius = light->GetPosition().GetDistance();
1813         float x = (radius * BASE_NS::Math::sin((BASE_NS::Math::DEG2RAD * light->GetPosition().GetX())));
1814         float z = (radius * BASE_NS::Math::cos((BASE_NS::Math::DEG2RAD * light->GetPosition().GetZ())));
1815         float y = (radius * BASE_NS::Math::sin((BASE_NS::Math::DEG2RAD * light->GetPosition().GetY())));
1816         position = BASE_NS::Math::Vec3(x, y, z);
1817     } else {
1818         position =
1819             BASE_NS::Math::Vec3(light->GetPosition().GetX(), light->GetPosition().GetY(), light->GetPosition().GetZ());
1820     }
1821 
1822     if (IsValidQuaternion(light->GetRotation())) {
1823         // App provided rotation. So use it directly.
1824         rotation = BASE_NS::Math::Quat(light->GetRotation().GetX(),
1825             light->GetRotation().GetY(),
1826             light->GetRotation().GetZ(),
1827             light->GetRotation().GetW());
1828     } else {
1829         // Use defaults. lookAt and up vectors are not provided in Applicatino API currently.
1830         BASE_NS::Math::Vec3 look(0.0, 0.0, 0.0);
1831         BASE_NS::Math::Vec3 up(0.0, 1.0, 0.0);
1832         BASE_NS::Math::Mat4X4 mat = BASE_NS::Math::LookAtRh(position, look, up);
1833         float determinantOut;
1834         BASE_NS::Math::Mat4X4 invMat = BASE_NS::Math::Inverse(mat, determinantOut);
1835         // Workaround for Lume LookAtRh API invalid matrix for specific data.
1836         if (std::abs(determinantOut) < 0.001f) {
1837             WIDGET_LOGE("ACE-3D Inverse LookAt matrix is invalid.");
1838             BASE_NS::Math::Vec3 modified_pos(position.x, position.y, position.z + 0.0001f);
1839             mat = BASE_NS::Math::LookAtRh(modified_pos, look, up);
1840             invMat = BASE_NS::Math::Inverse(mat, determinantOut);
1841             WIDGET_LOGD("ACE-3D 2nd Inverse LookAtRh: determinantOut: %f", determinantOut);
1842         }
1843         BASE_NS::Math::Vec3 scale;
1844         BASE_NS::Math::Quat orientation;
1845         BASE_NS::Math::Vec3 translation;
1846         BASE_NS::Math::Vec3 skew;
1847         BASE_NS::Math::Vec4 perspective;
1848         BASE_NS::Math::Decompose(invMat, scale, orientation, translation, skew, perspective);
1849         position = translation;
1850         rotation = orientation;
1851     }
1852 }
1853 
1854 } // namespace OHOS::Render3D
1855