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