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