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