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