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 #include "morphing_system.h"
17 
18 #include <PropertyTools/property_api_impl.inl>
19 #include <PropertyTools/property_macros.h>
20 #include <algorithm>
21 
22 #include <3d/ecs/components/mesh_component.h>
23 #include <3d/ecs/components/morph_component.h>
24 #include <3d/ecs/components/node_component.h>
25 #include <3d/ecs/components/render_handle_component.h>
26 #include <3d/ecs/components/render_mesh_component.h>
27 #include <3d/ecs/systems/intf_render_preprocessor_system.h>
28 #include <3d/render/intf_render_data_store_morph.h>
29 #include <core/ecs/intf_ecs.h>
30 #include <core/implementation_uids.h>
31 #include <core/intf_engine.h>
32 #include <core/log.h>
33 #include <core/namespace.h>
34 #include <core/plugin/intf_plugin_register.h>
35 #include <core/property/property_types.h>
36 #include <render/datastore/intf_render_data_store_manager.h>
37 #include <render/implementation_uids.h>
38 #include <render/intf_render_context.h>
39 
40 #include "property/property_handle.h"
41 
42 CORE_BEGIN_NAMESPACE()
43 DECLARE_PROPERTY_TYPE(RENDER_NS::IRenderDataStoreManager*);
44 CORE_END_NAMESPACE()
45 
46 CORE3D_BEGIN_NAMESPACE()
47 using namespace BASE_NS;
48 using namespace CORE_NS;
49 using namespace RENDER_NS;
50 
51 namespace {
52 BEGIN_PROPERTY(IMorphingSystem::Properties, ComponentMetadata)
53     DECL_PROPERTY2(IMorphingSystem::Properties, dataStoreName, "RenderDataStoreMorph", 0)
54 END_PROPERTY();
55 
GetBuffer(const MeshComponent::Submesh::BufferAccess & bufferAccess,const IRenderHandleComponentManager & bufferManager)56 RenderVertexBuffer GetBuffer(
57     const MeshComponent::Submesh::BufferAccess& bufferAccess, const IRenderHandleComponentManager& bufferManager)
58 {
59     if (EntityUtil::IsValid(bufferAccess.buffer)) {
60         return { bufferManager.GetRenderHandleReference(bufferAccess.buffer), bufferAccess.offset,
61             bufferAccess.byteSize };
62     }
63     return {};
64 }
65 
AddMorphSubmesh(IRenderDataStoreMorph & dataStore,const MeshComponent::Submesh & submeshDesc,const MeshComponent & desc,RenderDataMorph::Submesh & submesh,const IRenderHandleComponentManager & bufferManager)66 void AddMorphSubmesh(IRenderDataStoreMorph& dataStore, const MeshComponent::Submesh& submeshDesc,
67     const MeshComponent& desc, RenderDataMorph::Submesh& submesh, const IRenderHandleComponentManager& bufferManager)
68 {
69     submesh.vertexCount = submeshDesc.vertexCount;
70 
71     submesh.vertexBuffers[0U] = GetBuffer(submeshDesc.bufferAccess[MeshComponent::Submesh::DM_VB_POS], bufferManager);
72     submesh.vertexBuffers[1U] = GetBuffer(submeshDesc.bufferAccess[MeshComponent::Submesh::DM_VB_NOR], bufferManager);
73     submesh.vertexBuffers[2U] = GetBuffer(submeshDesc.bufferAccess[MeshComponent::Submesh::DM_VB_TAN], bufferManager);
74 
75     submesh.vertexBufferCount = 3U; // 3: count of vertex buffer
76 
77     submesh.morphTargetBuffer = GetBuffer(submeshDesc.morphTargetBuffer, bufferManager);
78 
79     submesh.morphTargetCount = submeshDesc.morphTargetCount;
80 
81     // don't touch submesh.activeTargets as it's same for each submesh
82     dataStore.AddSubmesh(submesh);
83 }
84 } // namespace
85 
MorphingSystem(IEcs & ecs)86 MorphingSystem::MorphingSystem(IEcs& ecs)
87     : active_(true), ecs_(ecs), dataStore_(nullptr), nodeManager_(*GetManager<INodeComponentManager>(ecs)),
88       meshManager_(*GetManager<IMeshComponentManager>(ecs)), morphManager_(*GetManager<IMorphComponentManager>(ecs)),
89       renderMeshManager_(*GetManager<IRenderMeshComponentManager>(ecs)),
90       gpuHandleManager_(*GetManager<IRenderHandleComponentManager>(ecs)),
91       MORPHING_SYSTEM_PROPERTIES(&properties_, ComponentMetadata)
92 {
93     if (IEngine* engine = ecs_.GetClassFactory().GetInterface<IEngine>(); engine) {
94         renderContext_ = GetInstance<IRenderContext>(*engine->GetInterface<IClassRegister>(), UID_RENDER_CONTEXT);
95     }
96 }
97 
~MorphingSystem()98 MorphingSystem::~MorphingSystem() {}
99 
SetActive(bool state)100 void MorphingSystem::SetActive(bool state)
101 {
102     active_ = state;
103 }
104 
IsActive() const105 bool MorphingSystem::IsActive() const
106 {
107     return active_;
108 }
109 
Initialize()110 void MorphingSystem::Initialize()
111 {
112     if (renderContext_) {
113         if (IRenderPreprocessorSystem* rps = GetSystem<IRenderPreprocessorSystem>(ecs_); rps) {
114             const auto in = ScopedHandle<IRenderPreprocessorSystem::Properties>(rps->GetProperties());
115             properties_.dataStoreName = in->dataStoreMorph;
116         } else {
117             CORE_LOG_E("DEPRECATED USAGE: RenderPreprocessorSystem not found. Add system to system graph.");
118         }
119 
120         SetDataStore(renderContext_->GetRenderDataStoreManager(), properties_.dataStoreName);
121     }
122     ecs_.AddListener(static_cast<IEcs::EntityListener&>(*this));
123     ecs_.AddListener(morphManager_, *this);
124     nodeQuery_.SetEcsListenersEnabled(true);
125     ComponentQuery::Operation operations[] = { { nodeManager_, ComponentQuery::Operation::Method::REQUIRE } };
126     nodeQuery_.SetupQuery(renderMeshManager_, operations, true);
127 }
128 
Uninitialize()129 void MorphingSystem::Uninitialize()
130 {
131     ecs_.RemoveListener(static_cast<IEcs::EntityListener&>(*this));
132     ecs_.RemoveListener(morphManager_, *this);
133     nodeQuery_.SetEcsListenersEnabled(false);
134 }
135 
SetDataStore(IRenderDataStoreManager & manager,const string_view name)136 void MorphingSystem::SetDataStore(IRenderDataStoreManager& manager, const string_view name)
137 {
138     if (!name.empty()) {
139         dataStore_ = static_cast<IRenderDataStoreMorph*>(manager.GetRenderDataStore(properties_.dataStoreName.data()));
140     } else {
141         dataStore_ = nullptr;
142     }
143 }
144 
GetName() const145 string_view MorphingSystem::GetName() const
146 {
147     return CORE3D_NS::GetName(this);
148 }
149 
GetUid() const150 Uid MorphingSystem::GetUid() const
151 {
152     return UID;
153 }
154 
GetProperties()155 IPropertyHandle* MorphingSystem::GetProperties()
156 {
157     return MORPHING_SYSTEM_PROPERTIES.GetData();
158 }
159 
GetProperties() const160 const IPropertyHandle* MorphingSystem::GetProperties() const
161 {
162     return MORPHING_SYSTEM_PROPERTIES.GetData();
163 }
164 
SetProperties(const IPropertyHandle & data)165 void MorphingSystem::SetProperties(const IPropertyHandle& data)
166 {
167     if (data.Owner() != &MORPHING_SYSTEM_PROPERTIES) {
168         return;
169     }
170 
171     if (const auto in = ScopedHandle<const IMorphingSystem::Properties>(&data); in) {
172         properties_.dataStoreName = in->dataStoreName;
173         if (renderContext_) {
174             SetDataStore(renderContext_->GetRenderDataStoreManager(), properties_.dataStoreName);
175         }
176     }
177 }
178 
GetECS() const179 const IEcs& MorphingSystem::GetECS() const
180 {
181     return ecs_;
182 }
183 
OnEntityEvent(const IEntityManager::EventType type,const array_view<const Entity> entities)184 void MorphingSystem::OnEntityEvent(const IEntityManager::EventType type, const array_view<const Entity> entities)
185 {
186     if (type == IEntityManager::EventType::DESTROYED) {
187         // remove entities that were destroyed
188         for (auto e : entities) {
189             dirty_.erase(e);
190         }
191     }
192 }
193 
OnComponentEvent(const ComponentListener::EventType type,const IComponentManager & componentManager,const array_view<const Entity> entities)194 void MorphingSystem::OnComponentEvent(const ComponentListener::EventType type,
195     const IComponentManager& componentManager, const array_view<const Entity> entities)
196 {
197     if (type == ComponentListener::EventType::DESTROYED) {
198         // morph component removed..
199         for (auto e : entities) {
200             reset_.push_back(e);
201             dirty_.erase(e);
202         }
203     }
204 }
205 
Morph(const MeshComponent & mesh,const MorphComponent & mc,bool dirty)206 bool MorphingSystem::Morph(const MeshComponent& mesh, const MorphComponent& mc, bool dirty)
207 {
208     // update active targets here once per mesh and the same will be reused for each submesh
209     auto& activeTargets = currentMorphSubmesh_.activeTargets;
210     activeTargets.clear();
211     const auto& weights = mc.morphWeights;
212     activeTargets.reserve(weights.size());
213     for (size_t ti = 0; ti < weights.size(); ti++) {
214         if (weights[ti] > 0.0f) {
215             activeTargets.push_back({ static_cast<uint32_t>(ti), weights[ti] });
216         }
217     }
218 
219     // sort according to weight (highest influence first)
220     std::sort(activeTargets.begin(), activeTargets.end(),
221         [](auto const& lhs, auto const& rhs) { return (lhs.weight > rhs.weight); });
222 
223     if ((!activeTargets.empty()) || (dirty)) {
224         for (const auto& submesh : mesh.submeshes) {
225             if (submesh.morphTargetCount > 0U) {
226                 AddMorphSubmesh(*dataStore_, submesh, mesh, currentMorphSubmesh_, gpuHandleManager_);
227             }
228         }
229     }
230     return !activeTargets.empty();
231 }
232 
Update(bool frameRenderingQueued,uint64_t,uint64_t)233 bool MorphingSystem::Update(bool frameRenderingQueued, uint64_t, uint64_t)
234 {
235     if (!active_) {
236         return false;
237     }
238     if (dataStore_ == nullptr) {
239 #if (CORE3D_VALIDATION_ENABLED == 1)
240         CORE_LOG_ONCE_W("ms_data_stores_not_found", "CORE3D_VALIDATION: morphing render data store not found");
241 #endif
242         return false;
243     }
244 
245     auto generation = morphManager_.GetGenerationCounter();
246     if (generation == lastGeneration_) {
247         // no change to components.
248         return false;
249     }
250     lastGeneration_ = generation;
251 
252     nodeQuery_.Execute();
253 
254     RenderDataMorph::Submesh renderData;
255 
256     // Actual processing follows..
257     auto& entityManager = ecs_.GetEntityManager();
258     for (IComponentManager::ComponentId i = 0; i < morphManager_.GetComponentCount(); i++) {
259         const Entity id = morphManager_.GetEntity(i);
260         if (entityManager.IsAlive(id)) {
261             if (auto* row = nodeQuery_.FindResultRow(id); row) {
262                 if (nodeManager_.Read(row->components[1])->effectivelyEnabled) {
263                     // This should be true. (there is a render mesh for this entity)
264                     if (const ScopedHandle<const RenderMeshComponent> renderMeshData =
265                             renderMeshManager_.Read(row->components[0]);
266                         renderMeshData) {
267                         if (const ScopedHandle<const MeshComponent> meshData = meshManager_.Read(renderMeshData->mesh);
268                             meshData) {
269                             const ScopedHandle<const MorphComponent> morphData = morphManager_.Read(i);
270                             dirty_[id] = Morph(*meshData, *morphData, dirty_[id]);
271                         }
272                     }
273                 }
274             }
275         }
276     }
277     // no active targets for the removed morph components
278     currentMorphSubmesh_.activeTargets.clear();
279     for (auto id : reset_) {
280         // reset the render mesh of removed component..
281         // This should be true. (there is a render mesh for this entity)
282         if (const auto renderMeshId = renderMeshManager_.GetComponentId(id);
283             renderMeshId != IComponentManager::INVALID_COMPONENT_ID) {
284             const RenderMeshComponent renderMeshComponent = renderMeshManager_.Get(renderMeshId);
285             if (const auto meshData = meshManager_.Read(renderMeshComponent.mesh); meshData) {
286                 const auto& mesh = *meshData;
287                 for (const auto& submesh : mesh.submeshes) {
288                     if (submesh.morphTargetCount > 0U) {
289                         AddMorphSubmesh(*dataStore_, submesh, mesh, currentMorphSubmesh_, gpuHandleManager_);
290                     }
291                 }
292             }
293         }
294     }
295     reset_.clear();
296 
297     return true;
298 }
299 
IMorphingSystemInstance(IEcs & ecs)300 ISystem* IMorphingSystemInstance(IEcs& ecs)
301 {
302     return new MorphingSystem(ecs);
303 }
IMorphingSystemDestroy(ISystem * instance)304 void IMorphingSystemDestroy(ISystem* instance)
305 {
306     delete static_cast<MorphingSystem*>(instance);
307 }
308 
309 CORE3D_END_NAMESPACE()
310