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 SCENEPLUGINAPI_MESH_H
17 #define SCENEPLUGINAPI_MESH_H
18 
19 #include <scene_plugin/api/material.h>
20 #include <scene_plugin/api/mesh_uid.h>
21 #include <scene_plugin/interface/intf_scene.h>
22 
23 #include <meta/api/internal/object_api.h>
SCENE_BEGIN_NAMESPACE()24 SCENE_BEGIN_NAMESPACE()
25 
26 class SubMesh final : public META_NS::Internal::ObjectInterfaceAPI<SubMesh, ClassId::SubMesh> {
27     META_API(SubMesh)
28     META_API_OBJECT_CONVERTIBLE(ISubMesh)
29     META_API_CACHE_INTERFACE(ISubMesh, SubMesh)
30 public:
31     // ToDo: The properties mirror the values from entity system, but setting the values
32     // needs to happen using setter methods below (even the properties are not marked
33     // ReadOnly
34     META_API_INTERFACE_PROPERTY_CACHED(SubMesh, Material, SCENE_NS::IMaterial::Ptr)
35     META_API_INTERFACE_PROPERTY_CACHED(SubMesh, AABBMin, BASE_NS::Math::Vec3)
36     META_API_INTERFACE_PROPERTY_CACHED(SubMesh, AABBMax, BASE_NS::Math::Vec3)
37     META_API_INTERFACE_PROPERTY_CACHED(SubMesh, RenderSortLayerOrder, uint8_t)
38 
39     /**
40      * @brief Within a render slot, a layer can define a sort layer order for a submesh.
41      * There are 0-63 values available. Default id value is 32.
42      * 0 first, 63 last
43      * 1. Typical use case is to set render sort layer to objects which render with depth test without depth write.
44      * 2. Typical use case is to always render character and/or camera object first to cull large parts of the view.
45      * 3. Sort e.g. plane layers.
46      * @param index The selected submesh index.
47      * @param value The layer order number.
48      */
49     void SetRenderSortLayerOrder(uint8_t order)
50     {
51         if (auto submesh = META_API_CACHED_INTERFACE(SubMesh)) {
52             submesh->SetRenderSortLayerOrder(order);
53         }
54     }
55 
56     /**
57      * @brief Set axis aligned bounding box min to the submesh.
58      */
59     void SetAABBMin(const BASE_NS::Math::Vec3& min)
60     {
61         if (auto submesh = META_API_CACHED_INTERFACE(SubMesh)) {
62             submesh->SetAABBMin(min);
63         }
64     }
65 
66     /**
67      * @brief Set axis aligned bounding box max to the submesh.
68      */
69     void SetAABBMax(const BASE_NS::Math::Vec3& max)
70     {
71         if (auto submesh = META_API_CACHED_INTERFACE(SubMesh)) {
72             submesh->SetAABBMax(max);
73         }
74     }
75 
76     /**
77      * @brief Set material to the submesh.
78      */
79     void SetMaterial(SCENE_NS::IMaterial::Ptr material)
80     {
81         if (auto submesh = META_API_CACHED_INTERFACE(SubMesh)) {
82             submesh->SetMaterial(material);
83         }
84     }
85 };
86 
87 /**
88  * @brief Mesh class wraps IMesh interface. It keeps the referenced object alive using strong ref.
89  *        The construction of the object is asynchronous, the properties of the engine may not be available
90  *        right after the object instantiation, but OnLoaded() event can be used to observe the state changes.
91  *        Mesh object may not implement Node interfaces on Engine side, so container operations and
92  *        transform operations are not applicable as such.
93  */
94 class Mesh final : public META_NS::Internal::ObjectInterfaceAPI<Mesh, ClassId::Mesh> {
95     META_API(Mesh)
META_API_OBJECT_CONVERTIBLE(IMesh)96     META_API_OBJECT_CONVERTIBLE(IMesh)
97     META_API_CACHE_INTERFACE(IMesh, Mesh)
98     META_API_OBJECT_CONVERTIBLE(INode)
99     META_API_CACHE_INTERFACE(INode, Node)
100 public:
101     // From Node
102     META_API_INTERFACE_PROPERTY_CACHED(Node, Name, BASE_NS::string)
103     META_API_INTERFACE_READONLY_ARRAY_PROPERTY_CACHED(Mesh, SubMeshes, SCENE_NS::ISubMesh::Ptr)
104     META_API_INTERFACE_READONLY_PROPERTY_CACHED(Mesh, AABBMin, BASE_NS::Math::Vec3)
105     META_API_INTERFACE_READONLY_PROPERTY_CACHED(Mesh, AABBMax, BASE_NS::Math::Vec3)
106 
107 public:
108     /**
109      * @brief Construct Mesh instance from INode strong pointer.
110      * @param node the object pointed by interface is kept alive
111      */
112     explicit Mesh(const INode::Ptr& node)
113     {
114         Initialize(interface_pointer_cast<META_NS::IObject>(node));
115     }
116 
117     /**
118      * @brief Construct Mesh instance from IMesh strong pointer.
119      * @param node the object pointed by interface is kept alive
120      */
Mesh(const IMesh::Ptr & node)121     Mesh(const IMesh::Ptr& node)
122     {
123         Initialize(interface_pointer_cast<META_NS::IObject>(node));
124     }
125 
126     /**
127      * @brief Gets OnLoaded event from INode-interface
128      * @return INode::OnLoaded
129      */
OnLoaded()130     auto OnLoaded()
131     {
132         return META_API_CACHED_INTERFACE(Node)->OnLoaded();
133     }
134 
135     /**
136      * @brief Runs a callback once the mesh is loaded. If mesh is already initialized, callback will not run.
137      * @param callback Code to run, if strong reference is passed, it will keep the instance alive
138      *                 causing engine to report memory leak on application exit.
139      * @return reference to this instance of Mesh.
140      */
141     template<class Callback>
OnLoaded(Callback && callback)142     auto& OnLoaded(Callback&& callback)
143     {
144         OnLoaded()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>(callback));
145         return *this;
146     }
147 
148     /**
149      * @brief Get the material from the selected submesh. The returned object is constructed asynchronously.
150      * @param index The selected submesh index.
151      * @return If the given index is valid, an object referencing the selected material.
152      */
GetMaterial(size_t index)153     Material GetMaterial(size_t index)
154     {
155         IMaterial::Ptr ret {};
156         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
157             ret = mesh->GetMaterial(index);
158         }
159         return Material(ret);
160     }
161 
162     /**
163      * @brief Set given material for all the submeshes.
164      * @material The material to be set.
165      */
SetMaterial(const IMaterial::Ptr material)166     void SetMaterial(const IMaterial::Ptr material)
167     {
168         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
169             mesh->SetMaterial(-1, material);
170         }
171     }
172 
173     /**
174      * @brief Set material for the spesific submesh.
175      * @material The material to be set.
176      * @param index The selected submesh index.
177      */
SetMaterial(size_t index,const IMaterial::Ptr material)178     void SetMaterial(size_t index, const IMaterial::Ptr material)
179     {
180         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
181             mesh->SetMaterial(index, material);
182         }
183     }
184 
185     /**
186      * @brief Within a render slot, a layer can define a sort layer order for a submesh.
187      * There are 0-63 values available. Default id value is 32.
188      * 0 first, 63 last
189      * 1. Typical use case is to set render sort layer to objects which render with depth test without depth write.
190      * 2. Typical use case is to always render character and/or camera object first to cull large parts of the view.
191      * 3. Sort e.g. plane layers.     * @param index The selected submesh index.
192      * @param index The selected submesh index.
193      * @param value The layer order number.
194      */
SetRenderSortLayerOrder(size_t index,uint8_t value)195     void SetRenderSortLayerOrder(size_t index, uint8_t value)
196     {
197         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
198             mesh->SetRenderSortLayerOrder(index, value);
199         }
200     }
201 
202     /**
203      * @brief Get render sort layer order for selected submesh
204      * @return The layer order for selected index, if the index is not present, returns 0u.
205      */
GetRenderSortLayerOrder(size_t index)206     uint8_t GetRenderSortLayerOrder(size_t index) const
207     {
208         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
209             return mesh->GetRenderSortLayerOrder(index);
210         }
211         return 0u;
212     }
213 
214     /**
215      * @brief Update mesh data from the arrays. 16 bit indices.
216      * @param arrays defining the mesh, see MeshGeometryArray.
217      */
UpdateMeshFromArraysI16(MeshGeometryArrayPtr<uint16_t> arrays)218     void UpdateMeshFromArraysI16(MeshGeometryArrayPtr<uint16_t> arrays)
219     {
220         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
221             mesh->UpdateMeshFromArraysI16(arrays);
222         }
223     }
224 
225     /**
226      * @brief Update mesh data from the arrays. 32 bit indices.
227      * @param arrays defining the mesh, see MeshGeometryArray.
228      */
UpdateMeshFromArraysI32(MeshGeometryArrayPtr<uint32_t> arrays)229     void UpdateMeshFromArraysI32(MeshGeometryArrayPtr<uint32_t> arrays)
230     {
231         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
232             mesh->UpdateMeshFromArraysI32(arrays);
233         }
234     }
235 
236     /**
237      * @brief Add submesh data from the arrays. 16 bit indices.
238      * @param arrays defining the mesh, see MeshGeometryArray.
239      */
AddSubmeshesFromArrayI16(MeshGeometryArrayPtr<uint16_t> arrays)240     void AddSubmeshesFromArrayI16(MeshGeometryArrayPtr<uint16_t> arrays)
241     {
242         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
243             mesh->AddSubmeshesFromArrayI16(arrays);
244         }
245     }
246 
247     /**
248      * @brief Add submesh data from the arrays. 32 bit indices.
249      * @param arrays defining the mesh, see MeshGeometryArray.
250      */
AddSubmeshesFromArraysI32(MeshGeometryArrayPtr<uint32_t> arrays)251     void AddSubmeshesFromArraysI32(MeshGeometryArrayPtr<uint32_t> arrays)
252     {
253         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
254             mesh->AddSubmeshesFromArraysI32(arrays);
255         }
256     }
257 
258     /**
259      * @brief Copy the contents of the submesh into this mesh instance.
260      */
CloneSubmesh(ISubMesh::Ptr submesh)261     void CloneSubmesh(ISubMesh::Ptr submesh)
262     {
263         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
264             mesh->CloneSubmesh(submesh);
265         }
266     }
267 
268     /**
269      * @brief Remove the submesh from this mesh instance.
270      */
RemoveSubMesh(size_t index)271     void RemoveSubMesh(size_t index)
272     {
273         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
274             mesh->RemoveSubMesh(index);
275         }
276     }
277 
278     /**
279      * @brief Remove all the submeshes from this mesh instance.
280      */
RemoveAllSubmeshes()281     void RemoveAllSubmeshes()
282     {
283         if (auto mesh = META_API_CACHED_INTERFACE(Mesh)) {
284             mesh->RemoveAllSubmeshes();
285         }
286     }
287 };
288 
289 class MultiMeshProxy final : public META_NS::Internal::ObjectInterfaceAPI<MultiMeshProxy, ClassId::MultiMeshProxy> {
290     META_API(MultiMeshProxy)
META_API_OBJECT_CONVERTIBLE(IMultiMeshProxy)291     META_API_OBJECT_CONVERTIBLE(IMultiMeshProxy)
292     META_API_CACHE_INTERFACE(IMultiMeshProxy, MultiMeshProxy)
293 public:
294     META_API_INTERFACE_PROPERTY_CACHED(MultiMeshProxy, MaterialOverride, SCENE_NS::IMaterial::Ptr)
295     META_API_INTERFACE_PROPERTY_CACHED(MultiMeshProxy, Mesh, SCENE_NS::IMesh::Ptr)
296     META_API_INTERFACE_PROPERTY_CACHED(MultiMeshProxy, VisibleInstanceCount, size_t)
297     META_API_INTERFACE_ARRAY_PROPERTY_CACHED(MultiMeshProxy, CustomData, BASE_NS::Math::Vec4)
298     META_API_INTERFACE_ARRAY_PROPERTY_CACHED(MultiMeshProxy, Transforms, BASE_NS::Math::Mat4X4)
299 
300     /**
301      * @brief Set the capacity of the proxy and reset properties to the whole batch
302      */
303     void SetInstanceCount(size_t count)
304     {
305         if (auto mmesh = META_API_CACHED_INTERFACE(MultiMeshProxy)) {
306             mmesh->SetInstanceCount(count);
307         }
308     }
309 };
310 
311 SCENE_END_NAMESPACE()
312 
313 #endif // SCENEPLUGINAPI_MESH_H
314