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