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