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