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 <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.data()));
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