1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef API_3D_UTIL_SCENE_UTIL_H
17 #define API_3D_UTIL_SCENE_UTIL_H
18 
19 #include <3d/ecs/components/material_component.h>
20 #include <3d/loaders/intf_scene_loader.h>
21 #include <3d/namespace.h>
22 #include <base/containers/string_view.h>
23 #include <base/math/quaternion.h>
24 #include <base/math/vector.h>
25 #include <core/ecs/entity.h>
26 #include <core/namespace.h>
27 #include <render/device/pipeline_state_desc.h>
28 #include <render/resource_handle.h>
29 
30 CORE_BEGIN_NAMESPACE()
31 class IEcs;
32 CORE_END_NAMESPACE()
33 
34 CORE3D_BEGIN_NAMESPACE()
35 class IAnimationPlayback;
36 struct LightComponent;
37 
38 /** @ingroup group_util_isceneutil
39  * @{
40  */
41 /** Interface for helper class to create different ECS related objects.
42  */
43 class ISceneUtil {
44 public:
45     /** Create camera.
46      * @param ecs Entity component system to contain the camera instance.
47      * @param position Position of the camera, defaults to origin.
48      * @param rotation Rotation of the camera, defaults to identity.
49      * @param zNear Near plane distance.
50      * @param zFar Far plane distance.
51      * @param fovDegrees FOV in degrees.
52      * @return Newly created camera entity.
53      */
54     virtual CORE_NS::Entity CreateCamera(CORE_NS::IEcs& ecs, const BASE_NS::Math::Vec3& position,
55         const BASE_NS::Math::Quat& rotation, float zNear, float zFar, float fovDegrees) const = 0;
56 
57     /** Update camera viewport and aspect ratio according to render resolution.
58      * @param ecs Entity component system to contain the camera instance.
59      * @param entity Camera entity.
60      * @param renderResolution Render resolution (width and height).
61      */
62     virtual void UpdateCameraViewport(
63         CORE_NS::IEcs& ecs, CORE_NS::Entity entity, const BASE_NS::Math::UVec2& renderResolution) const = 0;
64 
65     /** Update camera viewport according to render resolution, optionally also determines aspect ratio and proper FOV
66      * according to screen shape.
67      * Calculated values might change due to projection type.
68      * @param ecs Entity component system to contain the camera instance.
69      * @param entity Camera entity.
70      * @param renderResolution Render resolution (width and height).
71      * @param autoAspect If true, also calculates the aspect ratio.
72      * @param fovY Suggested y-fov in radians, in case the screen shape is portrait the x-fov is calculated and used.
73      * @param orthoScale Scale for ortho camera.
74      */
75     virtual void UpdateCameraViewport(CORE_NS::IEcs& ecs, CORE_NS::Entity entity,
76         const BASE_NS::Math::UVec2& renderResolution, bool autoAspect, float fovY, float orthoScale) const = 0;
77 
78     /** Update the transformation of the given entity such that it is located at 'eye', rotated towards 'target', and
79      * its up vector is 'up'. The up vector will only match 'up' if the direction from 'eye' to 'target' is
80      * perpendicular to 'up'.
81      * @param ecs Entity component system to contain the camera instance.
82      * @param entity Entity to modify.
83      * @param eye Final world space position of the entity.
84      * @param target World space position where the entity's z-axis will point to.
85      * @param up Desired up vector of the entity.
86      */
87     virtual void CameraLookAt(CORE_NS::IEcs& ecs, CORE_NS::Entity entity, const BASE_NS::Math::Vec3& eye,
88         const BASE_NS::Math::Vec3& target, const BASE_NS::Math::Vec3& up) = 0;
89 
90     /** Create a light. Creates a new ecs light based on inputs.
91      * For shadow lights a ecs camera is created and sane default values are calculated.
92      * @param ecs Entity component system to contain the light instance.
93      * @param lightComponent A filled up light component struct (will be attached to ECS internally.
94      * @param position Position of the light, defaults to origin.
95      * @param rotation Rotation of the light, defaults to identity.
96      * @return Newly created light entity.
97      */
98     virtual CORE_NS::Entity CreateLight(CORE_NS::IEcs& ecs, const LightComponent& lightComponent,
99         const BASE_NS::Math::Vec3& position, const BASE_NS::Math::Quat& rotation) const = 0;
100 
101     /** Create reflection plane component. Component is added to the given entity. For reflections to work the entity is
102      * expected to have a RenderMeshComponent. The method updates the material of the mesh for planar reflections.
103      * @param ecs Entity component system instance.
104      * @param nodeEntity Scene node entity where to attach.
105      */
106     virtual void CreateReflectionPlaneComponent(CORE_NS::IEcs& ecs, const CORE_NS::Entity& nodeEntity) = 0;
107 
108     /** Creates a new animation for targetEntity which animates the target's joints the same way as animationEntity
109      * animatest the joints of sourceEntity.
110      * @param ecs Entity component system instance.
111      * @param targetEntity Entity which will be the target of the new animation.
112      * @param sourceEntity Entity whos skin will be used for retargetting the animation to targetEntity.
113      * @param animationEntity Entity with a skinning animation.
114      * @return Newly created animation playback.
115      */
116     virtual IAnimationPlayback* RetargetSkinAnimation(CORE_NS::IEcs& ecs, CORE_NS::Entity targetEntity,
117         CORE_NS::Entity sourceEntity, CORE_NS::Entity animationEntity) const = 0;
118 
119     /** Material shader info for default material shader data fetching.
120      */
121     struct MaterialShaderInfo {
122         /** Alpha blend mode */
123         bool alphaBlend { false };
124         /** Cull mode */
125         RENDER_NS::CullModeFlags cullModeFlags { RENDER_NS::CullModeFlagBits::CORE_CULL_MODE_NONE };
126         /** Front face */
127         RENDER_NS::FrontFace frontFace { RENDER_NS::FrontFace::CORE_FRONT_FACE_COUNTER_CLOCKWISE };
128     };
129 
130     /** Returns default material shader built-in data for material component usage
131      * @param ecs Entity component system instance.
132      * @param info Material shader info which is used to fetch default material handles and entities.
133      * @param materialShader Returns material shader with entity references.
134      * @param depthSahder Returns depth shader with entity references.
135      */
136     virtual void GetDefaultMaterialShaderData(CORE_NS::IEcs& ecs, const MaterialShaderInfo& info,
137         MaterialComponent::Shader& materialShader, MaterialComponent::Shader& depthShader) const = 0;
138 
139     /** Returns default material shader data based on render slot name.
140      * NOTE: Alpha blend does not affect this, i.e. we do not flip the flag in graphics state
141      * @param ecs Entity component system instance.
142      * @param info Material shader info which is used to fetch default material handles and entities.
143      * @param renderSlot Name of the render slot.
144      * @param shader Returns material shader with entity references.
145      */
146     virtual void GetDefaultMaterialShaderData(CORE_NS::IEcs& ecs, const ISceneUtil::MaterialShaderInfo& info,
147         const BASE_NS::string_view renderSlot, MaterialComponent::Shader& shader) const = 0;
148 
149     /** Share the sourceEntity's skin with the targetEntity.
150      * @param ecs Entity component system instance.
151      * @param targetEntity Entity whos skin will be modified to use the source joints.
152      * @param sourceEntity Entity whos joints will be applied to target.
153      */
154     virtual void ShareSkin(CORE_NS::IEcs& ecs, CORE_NS::Entity targetEntity, CORE_NS::Entity sourceEntity) const = 0;
155 
156     /** Register a new scene loader. Plugins implementing support for new scene file formats should register an instance
157      * so that it can be discovered with GetSceneLoader.
158      * @param loader Pointer to a new scene loader instance.
159      */
160     virtual void RegisterSceneLoader(const ISceneLoader::Ptr& loader) = 0;
161 
162     /** Unregister a previously registered scene loader. Loaders must be unregistered e.g. when the plugin offering the
163      * instance is unloaded.
164      * @param loader Pointer to a previously registered scene loader instance.
165      */
166     virtual void UnregisterSceneLoader(const ISceneLoader::Ptr& loader) = 0;
167 
168     /** Get a scene loader which can handle the given file. Selection is done based on file extensions. Actual loading
169      * might still fail with the returned loader.
170      * @param uri File URI.
171      * @return Pointer to a scene loader or null if none of the registered loaders are able to handle the file.
172      */
173     virtual ISceneLoader::Ptr GetSceneLoader(BASE_NS::string_view uri) const = 0;
174 
175 protected:
176     ISceneUtil() = default;
177     virtual ~ISceneUtil() = default;
178 };
179 /** @} */
180 CORE3D_END_NAMESPACE()
181 
182 #endif // API_3D_UTIL_SCENE_UTIL_H
183