• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "util/scene_util.h"
17 
18 #include <3d/ecs/components/animation_component.h>
19 #include <3d/ecs/components/animation_output_component.h>
20 #include <3d/ecs/components/animation_track_component.h>
21 #include <3d/ecs/components/camera_component.h>
22 #include <3d/ecs/components/light_component.h>
23 #include <3d/ecs/components/local_matrix_component.h>
24 #include <3d/ecs/components/material_component.h>
25 #include <3d/ecs/components/mesh_component.h>
26 #include <3d/ecs/components/name_component.h>
27 #include <3d/ecs/components/node_component.h>
28 #include <3d/ecs/components/planar_reflection_component.h>
29 #include <3d/ecs/components/render_handle_component.h>
30 #include <3d/ecs/components/render_mesh_component.h>
31 #include <3d/ecs/components/skin_joints_component.h>
32 #include <3d/ecs/components/transform_component.h>
33 #include <3d/ecs/components/uri_component.h>
34 #include <3d/ecs/components/world_matrix_component.h>
35 #include <3d/ecs/systems/intf_animation_system.h>
36 #include <3d/intf_graphics_context.h>
37 #include <3d/render/default_material_constants.h>
38 #include <3d/util/intf_mesh_util.h>
39 #include <base/containers/fixed_string.h>
40 #include <core/ecs/intf_ecs.h>
41 #include <core/ecs/intf_entity_manager.h>
42 #include <core/intf_engine.h>
43 #include <core/namespace.h>
44 #include <core/property/intf_property_handle.h>
45 #include <render/device/intf_gpu_resource_manager.h>
46 #include <render/device/intf_shader_manager.h>
47 #include <render/intf_render_context.h>
48 
49 #include "uri_lookup.h"
50 #include "util/component_util_functions.h"
51 #include "util/string_util.h"
52 
53 CORE3D_BEGIN_NAMESPACE()
54 using namespace BASE_NS;
55 using namespace CORE_NS;
56 using namespace RENDER_NS;
57 
SceneUtil(IGraphicsContext & graphicsContext)58 SceneUtil::SceneUtil(IGraphicsContext& graphicsContext) : graphicsContext_(graphicsContext) {}
59 
CreateCamera(IEcs & ecs,const Math::Vec3 & position,const Math::Quat & rotation,float zNear,float zFar,float fovDegrees) const60 Entity SceneUtil::CreateCamera(
61     IEcs& ecs, const Math::Vec3& position, const Math::Quat& rotation, float zNear, float zFar, float fovDegrees) const
62 {
63     IEntityManager& em = ecs.GetEntityManager();
64     const Entity camera = em.Create();
65 
66     auto lmm = GetManager<ILocalMatrixComponentManager>(ecs);
67     lmm->Create(camera);
68 
69     auto wmm = GetManager<IWorldMatrixComponentManager>(ecs);
70     wmm->Create(camera);
71 
72     auto ncm = GetManager<INodeComponentManager>(ecs);
73     ncm->Create(camera);
74 
75     auto tcm = GetManager<ITransformComponentManager>(ecs);
76     TransformComponent tc;
77     tc.position = position;
78     tc.rotation = rotation;
79     tcm->Set(camera, tc);
80 
81     auto ccm = GetManager<ICameraComponentManager>(ecs);
82     CameraComponent cc;
83     cc.sceneFlags |= CameraComponent::SceneFlagBits::ACTIVE_RENDER_BIT;
84     cc.projection = CameraComponent::Projection::PERSPECTIVE;
85     cc.yFov = Math::DEG2RAD * fovDegrees;
86     cc.zNear = zNear;
87     cc.zFar = zFar;
88     ccm->Set(camera, cc);
89 
90     return camera;
91 }
92 
UpdateCameraViewport(IEcs & ecs,Entity entity,const Math::UVec2 & renderResolution) const93 void SceneUtil::UpdateCameraViewport(IEcs& ecs, Entity entity, const Math::UVec2& renderResolution) const
94 {
95     auto ccm = GetManager<ICameraComponentManager>(ecs);
96     if (ccm && CORE_NS::EntityUtil::IsValid(entity)) {
97         CameraComponent cameraComponent = ccm->Get(entity);
98         cameraComponent.aspect =
99             (renderResolution.y > 0) ? (static_cast<float>(renderResolution.x) / renderResolution.y) : 1.0f;
100         cameraComponent.renderResolution[0] = renderResolution.x;
101         cameraComponent.renderResolution[1] = renderResolution.y;
102 
103         ccm->Set(entity, cameraComponent);
104     }
105 }
106 
UpdateCameraViewport(IEcs & ecs,Entity entity,const Math::UVec2 & renderResolution,bool autoAspect,float fovY,float orthoScale) const107 void SceneUtil::UpdateCameraViewport(
108     IEcs& ecs, Entity entity, const Math::UVec2& renderResolution, bool autoAspect, float fovY, float orthoScale) const
109 {
110     auto ccm = GetManager<ICameraComponentManager>(ecs);
111     if (ccm && CORE_NS::EntityUtil::IsValid(entity)) {
112         CameraComponent cameraComponent = ccm->Get(entity);
113         if (autoAspect) {
114             const float aspectRatio =
115                 (renderResolution.y > 0) ? (static_cast<float>(renderResolution.x) / renderResolution.y) : 1.0f;
116 
117             // Using the fov value as xfov on portrait screens to keep the object
118             // better in the frame.
119             const float yFov = (aspectRatio > 1.0f) ? fovY : (2.0f * Math::atan(Math::tan(fovY * 0.5f) / aspectRatio));
120 
121             // Update the camera parameters.
122             cameraComponent.aspect = aspectRatio;
123             cameraComponent.yFov = yFov;
124 
125             // The camera can also be in ortho mode. Using a separate zoom value.
126             cameraComponent.yMag = orthoScale;
127             cameraComponent.xMag = cameraComponent.yMag * aspectRatio;
128         }
129 
130         cameraComponent.renderResolution[0] = renderResolution.x;
131         cameraComponent.renderResolution[1] = renderResolution.y;
132 
133         ccm->Set(entity, cameraComponent);
134     }
135 }
136 
CreateLight(IEcs & ecs,const LightComponent & lightComponent,const Math::Vec3 & position,const Math::Quat & rotation) const137 Entity SceneUtil::CreateLight(
138     IEcs& ecs, const LightComponent& lightComponent, const Math::Vec3& position, const Math::Quat& rotation) const
139 {
140     IEntityManager& em = ecs.GetEntityManager();
141     const Entity light = em.Create();
142 
143     auto lmm = GetManager<ILocalMatrixComponentManager>(ecs);
144     lmm->Create(light);
145 
146     auto wmm = GetManager<IWorldMatrixComponentManager>(ecs);
147     wmm->Create(light);
148 
149     auto ncm = GetManager<INodeComponentManager>(ecs);
150     ncm->Create(light);
151 
152     auto nameM = GetManager<INameComponentManager>(ecs);
153     nameM->Create(light);
154     constexpr string_view lightName("Light");
155     nameM->Write(light)->name = lightName;
156 
157     auto tcm = GetManager<ITransformComponentManager>(ecs);
158     TransformComponent tc;
159     tc.position = position;
160     tc.rotation = rotation;
161     tcm->Set(light, tc);
162 
163     auto lcm = GetManager<ILightComponentManager>(ecs);
164     LightComponent lc = lightComponent;
165     lc.shadowEnabled = (lc.type == LightComponent::Type::POINT) ? false : lc.shadowEnabled;
166     lc.range = ComponentUtilFunctions::CalculateSafeLightRange(lc.range, lc.intensity);
167     lcm->Set(light, lc);
168 
169     return light;
170 }
171 
172 // reflection plane helpers
173 namespace {
174 // default size, updated in render system based on main scene camera
175 constexpr Math::UVec2 DEFAULT_PLANE_TARGET_SIZE { 2u, 2u };
176 
CreateReflectionPlaneGpuImage(IGpuResourceManager & gpuResourceMgr,IRenderHandleComponentManager & handleManager,INameComponentManager & nameManager,const string_view name,const Format format,const ImageUsageFlags usageFlags)177 EntityReference CreateReflectionPlaneGpuImage(IGpuResourceManager& gpuResourceMgr,
178     IRenderHandleComponentManager& handleManager, INameComponentManager& nameManager, const string_view name,
179     const Format format, const ImageUsageFlags usageFlags)
180 {
181     const auto entity = handleManager.GetEcs().GetEntityManager().CreateReferenceCounted();
182     handleManager.Create(entity);
183 
184     GpuImageDesc desc;
185     desc.width = DEFAULT_PLANE_TARGET_SIZE.x;
186     desc.height = DEFAULT_PLANE_TARGET_SIZE.y;
187     desc.depth = 1;
188     desc.format = format;
189     desc.memoryPropertyFlags = MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
190     desc.usageFlags = usageFlags;
191     desc.imageType = ImageType::CORE_IMAGE_TYPE_2D;
192     desc.imageTiling = ImageTiling::CORE_IMAGE_TILING_OPTIMAL;
193     desc.imageViewType = ImageViewType::CORE_IMAGE_VIEW_TYPE_2D;
194     desc.engineCreationFlags = EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS;
195     handleManager.Write(entity)->reference = gpuResourceMgr.Create(name, desc);
196 
197     nameManager.Create(entity);
198     nameManager.Write(entity)->name = name;
199     return entity;
200 }
201 
CreateReflectionPlaneObjectFromEntity(IEcs & ecs,IGraphicsContext & graphicsContext,const Entity & nodeEntity)202 SceneUtil::ReflectionPlane CreateReflectionPlaneObjectFromEntity(
203     IEcs& ecs, IGraphicsContext& graphicsContext, const Entity& nodeEntity)
204 {
205     SceneUtil::ReflectionPlane plane;
206     IRenderMeshComponentManager* renderMeshCM = GetManager<IRenderMeshComponentManager>(ecs);
207     IMeshComponentManager* meshCM = GetManager<IMeshComponentManager>(ecs);
208     IMaterialComponentManager* matCM = GetManager<IMaterialComponentManager>(ecs);
209     IRenderHandleComponentManager* gpuHandleCM = GetManager<IRenderHandleComponentManager>(ecs);
210 
211     INameComponentManager* nameCM = GetManager<INameComponentManager>(ecs);
212     if (!(renderMeshCM && meshCM && matCM && gpuHandleCM && nameCM)) {
213         return plane;
214     }
215 
216     auto& device = graphicsContext.GetRenderContext().GetDevice();
217     auto& gpuResourceMgr = device.GetGpuResourceManager();
218     plane.entity = nodeEntity;
219     plane.colorTarget = CreateReflectionPlaneGpuImage(gpuResourceMgr, *gpuHandleCM, *nameCM,
220         DefaultMaterialCameraConstants::CAMERA_COLOR_PREFIX_NAME + to_hex(nodeEntity.id),
221         Format::BASE_FORMAT_R8G8B8A8_SRGB,
222         ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT);
223 
224     // NOTE: uses transient attachement usage flag and cannot be read.
225     plane.depthTarget = CreateReflectionPlaneGpuImage(gpuResourceMgr, *gpuHandleCM, *nameCM,
226         DefaultMaterialCameraConstants::CAMERA_DEPTH_PREFIX_NAME + to_hex(nodeEntity.id), Format::BASE_FORMAT_D16_UNORM,
227         ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
228             ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT);
229 
230     if (const auto rmcHandle = renderMeshCM->Read(nodeEntity); rmcHandle) {
231         const RenderMeshComponent& rmc = *rmcHandle;
232         if (const auto meshHandle = meshCM->Read(rmc.mesh); meshHandle) {
233             const MeshComponent& meshComponent = *meshHandle;
234             if (!meshComponent.submeshes.empty()) {
235                 if (auto matHandle = matCM->Write(meshComponent.submeshes[0].material); matHandle) {
236                     MaterialComponent& matComponent = *matHandle;
237                     auto* uriCM = GetManager<IUriComponentManager>(ecs);
238                     auto* renderHandleCM = GetManager<IRenderHandleComponentManager>(ecs);
239                     constexpr const string_view uri = "3dshaders://shader/core3d_dm_fw_reflection_plane.shader";
240                     auto shaderEntity = LookupResourceByUri(uri, *uriCM, *renderHandleCM);
241                     if (!EntityUtil::IsValid(shaderEntity)) {
242                         shaderEntity = ecs.GetEntityManager().Create();
243                         renderHandleCM->Create(shaderEntity);
244                         renderHandleCM->Write(shaderEntity)->reference = device.GetShaderManager().GetShaderHandle(uri);
245                         uriCM->Create(shaderEntity);
246                         uriCM->Write(shaderEntity)->uri = uri;
247                     }
248                     matComponent.materialShader.shader = ecs.GetEntityManager().GetReferenceCounted(shaderEntity);
249                     matComponent.textures[MaterialComponent::TextureIndex::SHEEN].image = plane.colorTarget;
250                     matComponent.extraRenderingFlags = MaterialComponent::ExtraRenderingFlagBits::DISCARD_BIT;
251                 }
252             }
253         }
254     }
255 
256     return plane;
257 }
258 } // namespace
259 
CreateReflectionPlaneComponent(IEcs & ecs,const Entity & nodeEntity)260 void SceneUtil::CreateReflectionPlaneComponent(IEcs& ecs, const Entity& nodeEntity)
261 {
262     SceneUtil::ReflectionPlane plane = CreateReflectionPlaneObjectFromEntity(ecs, graphicsContext_, nodeEntity);
263     if (EntityUtil::IsValid(plane.entity)) {
264         auto prcm = GetManager<IPlanarReflectionComponentManager>(ecs);
265         PlanarReflectionComponent prc;
266         prc.colorRenderTarget = plane.colorTarget;
267         prc.depthRenderTarget = plane.depthTarget;
268         prc.renderTargetResolution[0] = DEFAULT_PLANE_TARGET_SIZE.x;
269         prc.renderTargetResolution[1] = DEFAULT_PLANE_TARGET_SIZE.y;
270         prcm->Set(plane.entity, prc);
271     }
272 }
273 
CalculateScalingFactor(IEcs & ecs,Entity targetEntity,Entity sourceEntity)274 float CalculateScalingFactor(IEcs& ecs, Entity targetEntity, Entity sourceEntity)
275 {
276     float scale = 1.f;
277     auto renderMeshManager = GetManager<IRenderMeshComponentManager>(ecs);
278     auto meshManager = GetManager<IMeshComponentManager>(ecs);
279     auto transformManager = GetManager<ITransformComponentManager>(ecs);
280     if (!renderMeshManager || !meshManager || !transformManager) {
281         return scale;
282     }
283 
284     Entity dstMeshEntity;
285     Entity srcMeshEntity;
286     if (auto renderMeshComponent = renderMeshManager->Read(targetEntity); renderMeshComponent) {
287         dstMeshEntity = renderMeshComponent->mesh;
288     }
289     if (auto renderMeshComponent = renderMeshManager->Read(sourceEntity); renderMeshComponent) {
290         srcMeshEntity = renderMeshComponent->mesh;
291     }
292     if (!EntityUtil::IsValid(dstMeshEntity) || !EntityUtil::IsValid(srcMeshEntity)) {
293         return scale;
294     }
295     auto getMeshHeight = [](IMeshComponentManager& meshManager, Entity entity) {
296         if (auto meshComponent = meshManager.Read(entity); meshComponent) {
297             return (meshComponent->aabbMax.y - meshComponent->aabbMin.y);
298         }
299         return 0.f;
300     };
301 
302     const float dstHeight = getMeshHeight(*meshManager, dstMeshEntity);
303     const float srcHeight = getMeshHeight(*meshManager, srcMeshEntity);
304     if ((dstHeight == 0.f) || (srcHeight == 0.f)) {
305         return scale;
306     }
307 
308     auto dstMeshScale = transformManager->Get(targetEntity).scale;
309     auto srcMeshScale = transformManager->Get(sourceEntity).scale;
310     const auto dstSize = dstHeight * dstMeshScale.y;
311     const auto srcSize = srcHeight * srcMeshScale.y;
312     if (srcSize == 0.f) {
313         return scale;
314     }
315     scale = dstSize / srcSize;
316     return scale;
317 }
318 
CreateJointMapping(IEcs & ecs,array_view<const Entity> dstJointEntities,array_view<const Entity> srcJointEntities)319 vector<Entity> CreateJointMapping(
320     IEcs& ecs, array_view<const Entity> dstJointEntities, array_view<const Entity> srcJointEntities)
321 {
322     vector<Entity> srcToDstJointMapping;
323 
324     auto getName = [nameManager = GetManager<INameComponentManager>(ecs)](const Entity& jointEntity) -> string_view {
325         if (auto nameComponent = nameManager->Read(jointEntity); nameComponent) {
326             return nameComponent->name;
327         }
328         return {};
329     };
330 
331     vector<string_view> dstJointNames;
332     dstJointNames.reserve(dstJointEntities.size());
333     std::transform(dstJointEntities.begin(), dstJointEntities.end(), std::back_inserter(dstJointNames), getName);
334 
335     vector<string_view> srcJointNames;
336     srcJointNames.reserve(srcJointEntities.size());
337     std::transform(srcJointEntities.begin(), srcJointEntities.end(), std::back_inserter(srcJointNames), getName);
338 
339     srcToDstJointMapping.reserve(srcJointEntities.size());
340 
341     const auto dstJointNamesBegin = dstJointNames.cbegin();
342     const auto dstJointNamesEnd = dstJointNames.cend();
343     for (const auto& srcJointName : srcJointNames) {
344         const auto pos = std::find(dstJointNamesBegin, dstJointNamesEnd, srcJointName);
345         srcToDstJointMapping.push_back(
346             (pos != dstJointNamesEnd) ? dstJointEntities[static_cast<size_t>(std::distance(dstJointNamesBegin, pos))]
347                                       : Entity {});
348         if (pos == dstJointNamesEnd) {
349             CORE_LOG_W("Target skin missing joint %s", srcJointName.data());
350         }
351     }
352     return srcToDstJointMapping;
353 }
354 
UpdateTracks(IEcs & ecs,array_view<EntityReference> targetTracks,array_view<const EntityReference> sourceTracks,array_view<const Entity> srcJointEntities,array_view<const Entity> srcToDstJointMapping,float scale)355 vector<Entity> UpdateTracks(IEcs& ecs, array_view<EntityReference> targetTracks,
356     array_view<const EntityReference> sourceTracks, array_view<const Entity> srcJointEntities,
357     array_view<const Entity> srcToDstJointMapping, float scale)
358 {
359     vector<Entity> trackTargets;
360     trackTargets.reserve(sourceTracks.size());
361     auto& entityManager = ecs.GetEntityManager();
362     auto animationTrackManager = GetManager<IAnimationTrackComponentManager>(ecs);
363     auto animationOutputManager = GetManager<IAnimationOutputComponentManager>(ecs);
364     // update tracks to point to target skin's joints.
365     std::transform(sourceTracks.begin(), sourceTracks.end(), targetTracks.begin(),
366         [&entityManager, animationTrackManager, animationOutputManager, &srcJointEntities, &srcToDstJointMapping,
367             &trackTargets, scale](const EntityReference& srcTrackEntity) {
368             const auto srcTargetEntity = animationTrackManager->Read(srcTrackEntity)->target;
369             // check that the src track target is one of the src joints
370             if (const auto pos = std::find(srcJointEntities.begin(), srcJointEntities.end(), srcTargetEntity);
371                 pos != srcJointEntities.end()) {
372                 auto dstTrackEntity = entityManager.CreateReferenceCounted();
373                 animationTrackManager->Create(dstTrackEntity);
374                 auto dstTrack = animationTrackManager->Write(dstTrackEntity);
375                 auto srcTrack = animationTrackManager->Read(srcTrackEntity);
376                 *dstTrack = *srcTrack;
377                 const auto jointIndex = (pos - srcJointEntities.begin());
378                 trackTargets.push_back(srcToDstJointMapping[jointIndex]);
379                 dstTrack->target = {};
380 
381                 // joint position track needs to be offset
382                 if ((dstTrack->component == ITransformComponentManager::UID) && (dstTrack->property == "position")) {
383                     // create new animation output with original position corrected by the scale.
384                     dstTrack->data = entityManager.CreateReferenceCounted();
385                     animationOutputManager->Create(dstTrack->data);
386                     const auto dstOutput = animationOutputManager->Write(dstTrack->data);
387                     const auto srcOutput = animationOutputManager->Read(srcTrack->data);
388                     dstOutput->type = srcOutput->type;
389                     auto& dst = dstOutput->data;
390                     const auto& src = srcOutput->data;
391                     dst.resize(src.size());
392                     const auto count = dst.size() / sizeof(Math::Vec3);
393                     const auto srcPositions = array_view(reinterpret_cast<const Math::Vec3*>(src.data()), count);
394                     auto dstPositions = array_view(reinterpret_cast<Math::Vec3*>(dst.data()), count);
395                     std::transform(srcPositions.begin(), srcPositions.end(), dstPositions.begin(),
396                         [scale](const Math::Vec3 position) { return position * scale; });
397                 }
398                 return dstTrackEntity;
399             }
400             return srcTrackEntity;
401         });
402     return trackTargets;
403 }
404 
RetargetSkinAnimation(IEcs & ecs,Entity targetEntity,Entity sourceEntity,Entity animationEntity) const405 IAnimationPlayback* SceneUtil::RetargetSkinAnimation(
406     IEcs& ecs, Entity targetEntity, Entity sourceEntity, Entity animationEntity) const
407 {
408     auto jointsManager = GetManager<ISkinJointsComponentManager>(ecs);
409     auto dstJointsComponent = jointsManager->Read(targetEntity);
410     auto srcJointsComponent = jointsManager->Read(sourceEntity);
411     if (!dstJointsComponent || !srcJointsComponent) {
412         return nullptr;
413     }
414     if (!GetManager<IAnimationComponentManager>(ecs)->HasComponent(animationEntity)) {
415         return nullptr;
416     }
417 
418     auto dstJointEntities = array_view(dstJointsComponent->jointEntities, dstJointsComponent->count);
419     auto srcJointEntities = array_view(srcJointsComponent->jointEntities, srcJointsComponent->count);
420 
421     const vector<Entity> srcToDstJointMapping = CreateJointMapping(ecs, dstJointEntities, srcJointEntities);
422 
423     // calculate a scaling factor based on mesh heights
424     const auto scale = CalculateScalingFactor(ecs, targetEntity, sourceEntity);
425 
426     // compensate difference in root joint positions.
427     // synchronize initial pose by copying src joint rotations to dst joints.
428     {
429         auto transformManager = GetManager<ITransformComponentManager>(ecs);
430         auto srcIt = srcJointEntities.begin();
431         for (const auto& dstE : srcToDstJointMapping) {
432             auto srcTransform = transformManager->Read(*srcIt);
433             auto dstTransform = transformManager->Write(dstE);
434             if (srcTransform && dstTransform) {
435                 dstTransform->position = srcTransform->position * scale;
436                 dstTransform->rotation = srcTransform->rotation;
437             }
438             ++srcIt;
439         }
440     }
441 
442     auto& entityManager = ecs.GetEntityManager();
443     const auto dstAnimationEntity = entityManager.Create();
444     {
445         INameComponentManager* nameManager = GetManager<INameComponentManager>(ecs);
446         nameManager->Create(dstAnimationEntity);
447         nameManager->Write(dstAnimationEntity)->name = nameManager->Read(animationEntity)->name + " retargeted";
448     }
449 
450     vector<Entity> trackTargets;
451     {
452         auto animationManager = GetManager<IAnimationComponentManager>(ecs);
453         animationManager->Create(dstAnimationEntity);
454         auto dstAnimationComponent = animationManager->Write(dstAnimationEntity);
455         auto srcAnimationComponent = animationManager->Read(animationEntity);
456         if (!srcAnimationComponent) {
457             return nullptr;
458         }
459         // copy the src animation.
460         *dstAnimationComponent = *srcAnimationComponent;
461         trackTargets = UpdateTracks(ecs, dstAnimationComponent->tracks, srcAnimationComponent->tracks, srcJointEntities,
462             srcToDstJointMapping, scale);
463     }
464     auto animationSystem = GetSystem<IAnimationSystem>(ecs);
465     return animationSystem->CreatePlayback(dstAnimationEntity, trackTargets);
466 }
467 
GetDefaultMaterialShaderData(IEcs & ecs,const ISceneUtil::MaterialShaderInfo & info,MaterialComponent::Shader & materialShader,MaterialComponent::Shader & depthShader) const468 void SceneUtil::GetDefaultMaterialShaderData(IEcs& ecs, const ISceneUtil::MaterialShaderInfo& info,
469     MaterialComponent::Shader& materialShader, MaterialComponent::Shader& depthShader) const
470 {
471     IRenderHandleComponentManager* renderHandleMgr = GetManager<IRenderHandleComponentManager>(ecs);
472     if (renderHandleMgr) {
473         IEntityManager& entityMgr = ecs.GetEntityManager();
474         const IShaderManager& shaderMgr = graphicsContext_.GetRenderContext().GetDevice().GetShaderManager();
475         {
476             const uint32_t renderSlotId =
477                 (info.alphaBlend)
478                     ? shaderMgr.GetRenderSlotId(DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_TRANSLUCENT)
479                     : shaderMgr.GetRenderSlotId(DefaultMaterialShaderConstants::RENDER_SLOT_FORWARD_OPAQUE);
480 
481             const IShaderManager::RenderSlotData rsd = shaderMgr.GetRenderSlotData(renderSlotId);
482             materialShader.shader = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, rsd.shader);
483             RENDER_NS::GraphicsState gs = shaderMgr.GetGraphicsState(rsd.graphicsState);
484             gs.rasterizationState.cullModeFlags = info.cullModeFlags;
485             gs.rasterizationState.frontFace = info.frontFace;
486             const uint64_t gsHash = shaderMgr.HashGraphicsState(gs);
487             const RenderHandleReference gsHandle = shaderMgr.GetGraphicsStateHandleByHash(gsHash);
488             if (gsHandle) {
489                 materialShader.graphicsState = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, gsHandle);
490             }
491         }
492         if (!info.alphaBlend) {
493             const uint32_t renderSlotId = shaderMgr.GetRenderSlotId(DefaultMaterialShaderConstants::RENDER_SLOT_DEPTH);
494             const IShaderManager::RenderSlotData rsd = shaderMgr.GetRenderSlotData(renderSlotId);
495             depthShader.shader = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, rsd.shader);
496             RENDER_NS::GraphicsState gs = shaderMgr.GetGraphicsState(rsd.graphicsState);
497             gs.rasterizationState.cullModeFlags = info.cullModeFlags;
498             gs.rasterizationState.frontFace = info.frontFace;
499             const uint64_t gsHash = shaderMgr.HashGraphicsState(gs);
500             const RenderHandleReference gsHandle = shaderMgr.GetGraphicsStateHandleByHash(gsHash);
501             if (gsHandle) {
502                 depthShader.graphicsState = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, gsHandle);
503             }
504         }
505     }
506 }
507 
GetDefaultMaterialShaderData(IEcs & ecs,const ISceneUtil::MaterialShaderInfo & info,const string_view renderSlot,MaterialComponent::Shader & shader) const508 void SceneUtil::GetDefaultMaterialShaderData(IEcs& ecs, const ISceneUtil::MaterialShaderInfo& info,
509     const string_view renderSlot, MaterialComponent::Shader& shader) const
510 {
511     IRenderHandleComponentManager* renderHandleMgr = GetManager<IRenderHandleComponentManager>(ecs);
512     if (renderHandleMgr) {
513         IEntityManager& entityMgr = ecs.GetEntityManager();
514         const IShaderManager& shaderMgr = graphicsContext_.GetRenderContext().GetDevice().GetShaderManager();
515         const uint32_t renderSlotId = shaderMgr.GetRenderSlotId(renderSlot);
516         if (renderSlotId != ~0u) {
517             const IShaderManager::RenderSlotData rsd = shaderMgr.GetRenderSlotData(renderSlotId);
518             if (rsd.shader) {
519                 shader.shader = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, rsd.shader);
520             } else {
521                 CORE_LOG_D("SceneUtil: render slot base shader not found (%s)", renderSlot.data());
522             }
523             if (rsd.graphicsState) {
524                 RENDER_NS::GraphicsState gs = shaderMgr.GetGraphicsState(rsd.graphicsState);
525                 gs.rasterizationState.cullModeFlags = info.cullModeFlags;
526                 gs.rasterizationState.frontFace = info.frontFace;
527                 const uint64_t gsHash = shaderMgr.HashGraphicsState(gs);
528                 const RenderHandleReference gsHandle = shaderMgr.GetGraphicsStateHandleByHash(gsHash);
529                 shader.graphicsState = GetOrCreateEntityReference(entityMgr, *renderHandleMgr, gsHandle);
530             } else {
531                 CORE_LOG_D("SceneUtil: render slot base graphics state not found (%s)", renderSlot.data());
532             }
533         } else {
534             CORE_LOG_W("SceneUtil: render slot id not found (%s)", renderSlot.data());
535         }
536     }
537 }
538 CORE3D_END_NAMESPACE()
539