• 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,const CustomMeshData & data)109 Future<IMesh::Ptr> MeshCreator::Create(const MeshConfig& c, const CustomMeshData& data)
110 {
111     if (auto scene = scene_.lock()) {
112         return scene->AddTask([=] {
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             auto colorData = FillData(data.colors);
127             CORE3D_NS::IMeshBuilder::DataBuffer dummy {};
128 
129             builder->SetVertexData(0, positionData, normalData, uvData, dummy, dummy, colorData);
130             builder->CalculateAABB(0, positionData);
131 
132             auto indexData = FillData(data.indices);
133             builder->SetIndexData(0, indexData);
134 
135             auto ent = builder->CreateMesh(*scene->GetEcsContext().GetNativeEcs());
136             if (!c.name.empty()) {
137                 CORE_NS::GetManager<CORE3D_NS::IUriComponentManager>(*scene->GetEcsContext().GetNativeEcs())
138                     ->Set(ent, { c.name });
139                 CORE_NS::GetManager<CORE3D_NS::INameComponentManager>(*scene->GetEcsContext().GetNativeEcs())
140                     ->Set(ent, { c.name });
141             }
142             return CreateMesh(scene, ent);
143         });
144     }
145     return {};
146 }
CreateCube(const MeshConfig & c,float width,float height,float depth)147 Future<IMesh::Ptr> MeshCreator::CreateCube(const MeshConfig& c, float width, float height, float depth)
148 {
149     if (auto scene = scene_.lock()) {
150         return scene->AddTask([=] {
151             auto& util = scene->GetGraphicsContext().GetMeshUtil();
152             auto ent = util.GenerateCubeMesh(
153                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), width, height, depth);
154             return CreateMesh(scene, ent);
155         });
156     }
157     return {};
158 }
CreatePlane(const MeshConfig & c,float width,float depth)159 Future<IMesh::Ptr> MeshCreator::CreatePlane(const MeshConfig& c, float width, float depth)
160 {
161     if (auto scene = scene_.lock()) {
162         return scene->AddTask([=] {
163             auto& util = scene->GetGraphicsContext().GetMeshUtil();
164             auto ent =
165                 util.GeneratePlaneMesh(*scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), width, depth);
166             return CreateMesh(scene, ent);
167         });
168     }
169     return {};
170 }
CreateSphere(const MeshConfig & c,float radius,uint32_t rings,uint32_t sectors)171 Future<IMesh::Ptr> MeshCreator::CreateSphere(const MeshConfig& c, float radius, uint32_t rings, uint32_t sectors)
172 {
173     if (auto scene = scene_.lock()) {
174         return scene->AddTask([=] {
175             auto& util = scene->GetGraphicsContext().GetMeshUtil();
176             auto ent = util.GenerateSphereMesh(
177                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), radius, rings, sectors);
178             return CreateMesh(scene, ent);
179         });
180     }
181     return {};
182 }
CreateCone(const MeshConfig & c,float radius,float length,uint32_t sectors)183 Future<IMesh::Ptr> MeshCreator::CreateCone(const MeshConfig& c, float radius, float length, uint32_t sectors)
184 {
185     if (auto scene = scene_.lock()) {
186         return scene->AddTask([=] {
187             auto& util = scene->GetGraphicsContext().GetMeshUtil();
188             auto ent = util.GenerateConeMesh(
189                 *scene->GetEcsContext().GetNativeEcs(), c.name, GetMaterial(c), radius, length, sectors);
190             return CreateMesh(scene, ent);
191         });
192     }
193     return {};
194 }
195 
196 SCENE_END_NAMESPACE()