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