• 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_creator.h"
17 
18 #include <scene/ext/intf_ecs_context.h>
19 #include <scene/ext/util.h>
20 
21 #include <3d/ecs/components/name_component.h>
22 #include <3d/ecs/components/uri_component.h>
23 #include <3d/implementation_uids.h>
24 #include <3d/render/default_material_constants.h>
25 #include <3d/util/intf_mesh_builder.h>
26 #include <3d/util/intf_mesh_util.h>
27 #include <core/plugin/intf_class_factory.h>
28 
SCENE_BEGIN_NAMESPACE()29 SCENE_BEGIN_NAMESPACE()
30 
31 bool MeshCreator::Build(const META_NS::IMetadata::Ptr& d)
32 {
33     IInternalScene::Ptr p;
34     if (Super::Build(d)) {
35         p = GetInterfaceBuildArg<IInternalScene>(d, "Scene");
36         scene_ = p;
37     }
38     return p != nullptr;
39 }
40 
GetMaterial(const MeshConfig & c)41 static CORE_NS::Entity GetMaterial(const MeshConfig& c)
42 {
43     if (auto i = interface_cast<IEcsObjectAccess>(c.material)) {
44         if (auto obj = i->GetEcsObject()) {
45             return obj->GetEntity();
46         }
47     }
48     return {};
49 }
50 
CreateMesh(const IInternalScene::Ptr & scene,CORE_NS::Entity ent)51 static IMesh::Ptr CreateMesh(const IInternalScene::Ptr& scene, CORE_NS::Entity ent)
52 {
53     if (!CORE_NS::EntityUtil::IsValid(ent)) {
54         return nullptr;
55     }
56     auto ecsobj = scene->GetEcsContext().GetEcsObject(ent);
57     if (!ecsobj) {
58         return nullptr;
59     }
60     auto mesh = META_NS::GetObjectRegistry().Create<IMesh>(ClassId::Mesh);
61     if (!mesh) {
62         return nullptr;
63     }
64     if (auto acc = interface_cast<IEcsObjectAccess>(mesh)) {
65         if (!acc->SetEcsObject(ecsobj)) {
66             return nullptr;
67         }
68     }
69     return mesh;
70 }
71 
72 template<typename T>
FillData(const BASE_NS::vector<T> & c)73 constexpr static CORE3D_NS::IMeshBuilder::DataBuffer FillData(const BASE_NS::vector<T>& c) noexcept
74 {
75     using namespace BASE_NS;
76     Format format = BASE_FORMAT_UNDEFINED;
77     if constexpr (is_same_v<T, Math::Vec2>) {
78         format = BASE_FORMAT_R32G32_SFLOAT;
79     } else if constexpr (is_same_v<T, Math::Vec3>) {
80         format = BASE_FORMAT_R32G32B32_SFLOAT;
81     } else if constexpr (is_same_v<T, Math::Vec4>) {
82         format = BASE_FORMAT_R32G32B32A32_SFLOAT;
83     } else if constexpr (is_same_v<T, uint16_t>) {
84         format = BASE_FORMAT_R16_UINT;
85     } else if constexpr (is_same_v<T, uint32_t>) {
86         format = BASE_FORMAT_R32_UINT;
87     }
88     return CORE3D_NS::IMeshBuilder::DataBuffer { format, sizeof(T),
89         { reinterpret_cast<const uint8_t*>(c.data()), c.size() * sizeof(T) } };
90 }
91 
CreateMeshBuilder(RENDER_NS::IRenderContext & context,const CORE3D_NS::IMeshBuilder::Submesh & submesh)92 static CORE3D_NS::IMeshBuilder::Ptr CreateMeshBuilder(
93     RENDER_NS::IRenderContext& context, const CORE3D_NS::IMeshBuilder::Submesh& submesh)
94 {
95     CORE3D_NS::IMeshBuilder::Ptr builder;
96     RENDER_NS::IShaderManager& shaderManager = context.GetDevice().GetShaderManager();
97     const RENDER_NS::VertexInputDeclarationView vertexInputDeclaration =
98         shaderManager.GetVertexInputDeclarationView(shaderManager.GetVertexInputDeclarationHandle(
99             CORE3D_NS::DefaultMaterialShaderConstants::VERTEX_INPUT_DECLARATION_FORWARD));
100     builder = CORE_NS::CreateInstance<CORE3D_NS::IMeshBuilder>(context, CORE3D_NS::UID_MESH_BUILDER);
101     builder->Initialize(vertexInputDeclaration, 1);
102 
103     builder->AddSubmesh(submesh);
104     builder->Allocate();
105 
106     return builder;
107 }
108 
Create(const MeshConfig & c,CustomMeshData d)109 Future<IMesh::Ptr> MeshCreator::Create(const MeshConfig& c, CustomMeshData d)
110 {
111     if (auto scene = scene_.lock()) {
112         return scene->AddTask([=, data = BASE_NS::move(d)] {
113             CORE3D_NS::IMeshBuilder::Submesh submesh;
114             submesh.inputAssembly =
115                 RENDER_NS::GraphicsState::InputAssembly { false, RENDER_NS::PrimitiveTopology(data.topology) };
116             submesh.material = GetMaterial(c);
117             submesh.vertexCount = static_cast<uint32_t>(data.vertices.size());
118             submesh.indexCount = static_cast<uint32_t>(data.indices.size());
119             submesh.colors = true;
120 
121             auto builder = CreateMeshBuilder(scene->GetRenderContext(), submesh);
122 
123             auto positionData = FillData(data.vertices);
124             auto normalData = FillData(data.normals);
125             auto uvData = FillData(data.uvs);
126             // Convert from BASE_NS::Color->BASE_NS::Math::Vec4
127             BASE_NS::vector<BASE_NS::Math::Vec4> colors;
128             colors.reserve(data.colors.size());
129             for (auto&& color : data.colors) {
130                 colors.emplace_back(color.r, color.g, color.b, color.a);
131             }
132             auto colorData = FillData(colors);
133             CORE3D_NS::IMeshBuilder::DataBuffer dummy {};
134 
135             builder->SetVertexData(0, positionData, normalData, uvData, dummy, dummy, colorData);
136             builder->CalculateAABB(0, positionData);
137 
138             auto indexData = FillData(data.indices);
139             builder->SetIndexData(0, indexData);
140 
141             auto ent = builder->CreateMesh(*scene->GetEcsContext().GetNativeEcs());
142             if (!c.name.empty()) {
143                 CORE_NS::GetManager<CORE3D_NS::IUriComponentManager>(*scene->GetEcsContext().GetNativeEcs())
144                     ->Set(ent, { c.name });
145                 CORE_NS::GetManager<CORE3D_NS::INameComponentManager>(*scene->GetEcsContext().GetNativeEcs())
146                     ->Set(ent, { c.name });
147             }
148             return CreateMesh(scene, ent);
149         });
150     }
151     return {};
152 }
CreateCube(const MeshConfig & c,float width,float height,float depth)153 Future<IMesh::Ptr> MeshCreator::CreateCube(const MeshConfig& c, float width, float height, float depth)
154 {
155     if (auto scene = scene_.lock()) {
156         return scene->AddTask([=] {
157             auto& util = scene->GetGraphicsContext().GetMeshUtil();
158             auto ent = util.GenerateCubeMesh(
159                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), width, height, depth);
160             return CreateMesh(scene, ent);
161         });
162     }
163     return {};
164 }
CreatePlane(const MeshConfig & c,float width,float depth)165 Future<IMesh::Ptr> MeshCreator::CreatePlane(const MeshConfig& c, float width, float depth)
166 {
167     if (auto scene = scene_.lock()) {
168         return scene->AddTask([=] {
169             auto& util = scene->GetGraphicsContext().GetMeshUtil();
170             auto ent =
171                 util.GeneratePlaneMesh(*scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), width, depth);
172             return CreateMesh(scene, ent);
173         });
174     }
175     return {};
176 }
CreateSphere(const MeshConfig & c,float radius,uint32_t rings,uint32_t sectors)177 Future<IMesh::Ptr> MeshCreator::CreateSphere(const MeshConfig& c, float radius, uint32_t rings, uint32_t sectors)
178 {
179     if (auto scene = scene_.lock()) {
180         return scene->AddTask([=] {
181             auto& util = scene->GetGraphicsContext().GetMeshUtil();
182             auto ent = util.GenerateSphereMesh(
183                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), radius, rings, sectors);
184             return CreateMesh(scene, ent);
185         });
186     }
187     return {};
188 }
CreateCone(const MeshConfig & c,float radius,float length,uint32_t sectors)189 Future<IMesh::Ptr> MeshCreator::CreateCone(const MeshConfig& c, float radius, float length, uint32_t sectors)
190 {
191     if (auto scene = scene_.lock()) {
192         return scene->AddTask([=] {
193             auto& util = scene->GetGraphicsContext().GetMeshUtil();
194             auto ent = util.GenerateConeMesh(
195                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), radius, length, sectors);
196             return CreateMesh(scene, ent);
197         });
198     }
199     return {};
200 }
201 
202 SCENE_END_NAMESPACE()