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