• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "mesh.h"
17 
18 #include <3d/ecs/components/mesh_component.h>
19 #include <3d/util/intf_picking.h>
20 
SCENE_BEGIN_NAMESPACE()21 SCENE_BEGIN_NAMESPACE()
22 
23 void Mesh::SetInternalMesh(IInternalMesh::Ptr m)
24 {
25     mesh_ = std::move(m);
26 }
27 
OnPropertyChanged(const META_NS::IProperty & p)28 void Mesh::OnPropertyChanged(const META_NS::IProperty& p)
29 {
30     if (p.GetName() == "MaterialOverride") {
31         OnMaterialOverrideChanged();
32     }
33 }
34 
GetMeshEcsObject() const35 IEcsObject::Ptr Mesh::GetMeshEcsObject() const
36 {
37     auto comp = interface_cast<IEcsObjectAccess>(mesh_);
38     return comp ? comp->GetEcsObject() : nullptr;
39 }
40 
GetSubmeshes() const41 Future<BASE_NS::vector<ISubMesh::Ptr>> Mesh::GetSubmeshes() const
42 {
43     if (auto obj = GetMeshEcsObject()) {
44         if (auto scene = obj->GetScene()) {
45             return scene->AddTask([=] {
46                 BASE_NS::vector<ISubMesh::Ptr> res;
47                 for (auto&& v : mesh_->SubMeshes()->GetValue()) {
48                     auto sm = META_NS::GetObjectRegistry().Create<ISubMesh>(ClassId::SubMesh);
49                     if (auto i = interface_cast<IInternalSubMesh>(sm)) {
50                         if (i->SetSubMesh(scene->GetEcsContext(), v)) {
51                             res.push_back(BASE_NS::move(sm));
52                         } else {
53                             CORE_LOG_E("Failed to create submesh");
54                         }
55                     }
56                 }
57                 return res;
58             });
59         }
60     }
61     return Future<BASE_NS::vector<ISubMesh::Ptr>> {};
62 }
63 
SetSubmeshes(const BASE_NS::vector<ISubMesh::Ptr> & submeshes)64 Future<bool> Mesh::SetSubmeshes(const BASE_NS::vector<ISubMesh::Ptr>& submeshes)
65 {
66     const auto obj = GetMeshEcsObject();
67     if (!mesh_ || !obj) {
68         CORE_LOG_E("Unable to set submeshes: Mesh is uninitialized");
69         return Future<bool> {};
70     }
71     auto scene = obj->GetScene();
72     if (!scene) {
73         CORE_LOG_E("Unable to set submeshes: Invalid object");
74         return {};
75     }
76     const auto manager = obj->GetEngineValueManager();
77     if (!manager) {
78         CORE_LOG_E("Unable to set submeshes: No engine value manager");
79         return Future<bool> {};
80     }
81 
82     auto componentSubmeshes = ConstructComponentSubmeshes(submeshes);
83     ApplyMaterialOverride(componentSubmeshes, true);
84     mesh_->SubMeshes()->SetValue(componentSubmeshes);
85 
86     CORE3D_NS::MinAndMax minMax;
87     for (const auto& submesh : componentSubmeshes) {
88         minMax.minAABB = min(minMax.minAABB, submesh.aabbMin);
89         minMax.maxAABB = max(minMax.maxAABB, submesh.aabbMax);
90     }
91     mesh_->AABBMin()->SetValue(minMax.minAABB);
92     mesh_->AABBMax()->SetValue(minMax.maxAABB);
93 
94     return scene->AddTask([=]() -> bool {
95         if (auto s = obj->GetScene()) {
96             s->SyncProperty(mesh_->AABBMin(), META_NS::EngineSyncDirection::TO_ENGINE);
97             s->SyncProperty(mesh_->AABBMax(), META_NS::EngineSyncDirection::TO_ENGINE);
98             s->SyncProperty(mesh_->SubMeshes(), META_NS::EngineSyncDirection::TO_ENGINE);
99         }
100         return true;
101     });
102 }
103 
ConstructComponentSubmeshes(const BASE_NS::vector<ISubMesh::Ptr> & submeshes) const104 BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh> Mesh::ConstructComponentSubmeshes(
105     const BASE_NS::vector<ISubMesh::Ptr>& submeshes) const
106 {
107     BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh> componentSubmeshes;
108     componentSubmeshes.reserve(submeshes.size());
109     for (auto&& submesh : submeshes) {
110         if (const auto internalSubMesh = interface_cast<IInternalSubMesh>(submesh)) {
111             componentSubmeshes.emplace_back(internalSubMesh->GetSubMesh());
112         }
113     }
114     return componentSubmeshes;
115 }
116 
ApplyMaterialOverride(BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh> & submeshes,bool forceStore)117 void Mesh::ApplyMaterialOverride(BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh>& submeshes, bool forceStore)
118 {
119     const auto materialOverride = interface_cast<IEcsObjectAccess>(MaterialOverride()->GetValue());
120     if (!materialOverride) {
121         return;
122     }
123     std::unique_lock lock { mutex_ };
124     const auto materialOverrideEntity = materialOverride->GetEcsObject()->GetEntity();
125     bool store = forceStore || submeshMaterials_.empty();
126     submeshMaterials_.resize(submeshes.size());
127     size_t i = 0;
128     for (auto&& submesh : submeshes) {
129         if (store) {
130             submeshMaterials_.at(i) = submesh.material;
131         }
132         submesh.material = materialOverrideEntity;
133         i++;
134     }
135 }
136 
RestoreOriginalMaterials(BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh> & submeshes)137 void Mesh::RestoreOriginalMaterials(BASE_NS::vector<CORE3D_NS::MeshComponent::Submesh>& submeshes)
138 {
139     std::unique_lock lock { mutex_ };
140     if (!submeshMaterials_.empty()) {
141         if (submeshes.size() != submeshMaterials_.size()) {
142             CORE_LOG_W("submesh size not matching saved submesh materials?!");
143         }
144         size_t i = 0;
145         for (auto&& submesh : submeshes) {
146             submesh.material = submeshMaterials_.at(i);
147             ++i;
148         }
149         submeshMaterials_.clear();
150     }
151 }
152 
OnMaterialOverrideChanged()153 void Mesh::OnMaterialOverrideChanged()
154 {
155     auto material = META_NS::GetValue(MaterialOverride());
156     auto p = mesh_->SubMeshes().GetLockedAccess();
157     auto values = p->GetValue();
158     if (material) {
159         ApplyMaterialOverride(values);
160     } else {
161         RestoreOriginalMaterials(values);
162     }
163     p->SetValue(values);
164 }
165 
SetEcsObject(const IEcsObject::Ptr & obj)166 bool Mesh::SetEcsObject(const IEcsObject::Ptr& obj)
167 {
168     if (Super::SetEcsObject(obj)) {
169         if (auto att = GetSelf<META_NS::IAttach>()) {
170             if (auto attc = att->GetAttachmentContainer(false)) {
171                 if (auto c = attc->FindByName<IInternalMesh>("MeshComponent")) {
172                     SetInternalMesh(c);
173                 }
174             }
175         }
176         if (!mesh_) {
177             auto p = META_NS::GetObjectRegistry().Create<IInternalMesh>(ClassId::MeshComponent);
178             if (auto acc = interface_cast<IEcsObjectAccess>(p)) {
179                 if (acc->SetEcsObject(obj)) {
180                     SetInternalMesh(p);
181                     if (auto scene = obj->GetScene()) {
182                         meshEntity_ = scene->GetEcsContext().GetEntityReference(obj->GetEntity());
183                     }
184                 }
185             }
186         }
187     }
188     return mesh_ != nullptr;
189 }
190 
CreateEntity(const IInternalScene::Ptr & scene)191 CORE_NS::Entity Mesh::CreateEntity(const IInternalScene::Ptr& scene)
192 {
193     const auto& ecs = scene->GetEcsContext().GetNativeEcs();
194     const auto meshManager = CORE_NS::GetManager<CORE3D_NS::IMeshComponentManager>(*ecs);
195     if (!meshManager) {
196         return {};
197     }
198     auto ent = ecs->GetEntityManager().Create();
199     meshManager->Create(ent);
200     return ent;
201 }
202 
203 SCENE_END_NAMESPACE()