• 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 #include "MeshJS.h"
16 
17 #include <meta/api/make_callback.h>
18 #include <meta/interface/intf_task_queue.h>
19 #include <meta/interface/intf_task_queue_registry.h>
20 #include <scene/interface/intf_camera.h>
21 #include <scene/interface/intf_scene.h>
22 #include <scene/interface/intf_mesh.h>
23 
24 #include "SceneJS.h"
GetInstanceImpl(uint32_t id)25 void* MeshJS::GetInstanceImpl(uint32_t id)
26 {
27     if (id == MeshJS::ID)
28         return this;
29     return SceneResourceImpl::GetInstanceImpl(id);
30 }
DisposeNative(void * scn)31 void MeshJS::DisposeNative(void* scn)
32 {
33     if (disposed_) {
34         return;
35     }
36     disposed_ = true;
37 
38     LOG_V("MeshJS::DisposeNative");
39     if (auto* sceneJS = static_cast<SceneJS*>(scn)) {
40         sceneJS->ReleaseStrongDispose(reinterpret_cast<uintptr_t>(&scene_));
41     }
42     subs_.clear();
43     scene_.Reset();
44 }
Init(napi_env env,napi_value exports)45 void MeshJS::Init(napi_env env, napi_value exports)
46 {
47     BASE_NS::vector<napi_property_descriptor> node_props;
48     SceneResourceImpl::GetPropertyDescs(node_props);
49 
50     using namespace NapiApi;
51     node_props.push_back(GetProperty<Object, MeshJS, &MeshJS::GetSubmesh>("subMeshes"));
52     node_props.push_back(GetProperty<Object, MeshJS, &MeshJS::GetAABB>("aabb"));
53     node_props.push_back(
54         GetSetProperty<Object, MeshJS, &MeshJS::GetMaterialOverride, &MeshJS::SetMaterialOverride>("materialOverride"));
55 
56     napi_value func;
57     auto status = napi_define_class(env, "Mesh", NAPI_AUTO_LENGTH, BaseObject::ctor<MeshJS>(), nullptr,
58         node_props.size(), node_props.data(), &func);
59 
60     NapiApi::MyInstanceState* mis;
61     GetInstanceData(env, (void**)&mis);
62     mis->StoreCtor("Mesh", func);
63 }
64 
MeshJS(napi_env e,napi_callback_info i)65 MeshJS::MeshJS(napi_env e, napi_callback_info i) : BaseObject<MeshJS>(e, i), SceneResourceImpl(SceneResourceImpl::MESH)
66 {
67     NapiApi::FunctionContext<NapiApi::Object, NapiApi::Object> fromJs(e, i);
68     if (!fromJs) {
69         // okay internal create. we will receive the object after.
70         return;
71     }
72     scene_ = fromJs.Arg<0>().valueOrDefault();
73     if (!GetNativeMeta<SCENE_NS::IScene>(scene_.GetObject())) {
74         LOG_F("INVALID SCENE!");
75     }
76     {
77         // add the dispose hook to scene. (so that the geometry node is disposed when scene is disposed)
78         NapiApi::Object meJs(fromJs.This());
79         NapiApi::Object scene = fromJs.Arg<0>();
80         if (auto sceneJS = GetJsWrapper<SceneJS>(scene)) {
81             sceneJS->StrongDisposeHook(reinterpret_cast<uintptr_t>(&scene_), meJs);
82         }
83     }
84 }
~MeshJS()85 MeshJS::~MeshJS()
86 {
87     LOG_V("MeshJS -- ");
88 }
Finalize(napi_env env)89 void MeshJS::Finalize(napi_env env)
90 {
91     DisposeNative(GetJsWrapper<SceneJS>(scene_.GetObject()));
92     BaseObject::Finalize(env);
93 }
UpdateSubmesh(uint32_t index,SCENE_NS::ISubMesh::Ptr newSubmesh)94 bool MeshJS::UpdateSubmesh(uint32_t index, SCENE_NS::ISubMesh::Ptr newSubmesh)
95 {
96     if (index < subs_.size()) {
97         subs_[index] = newSubmesh;
98         if (auto mesh = interface_pointer_cast<SCENE_NS::IMesh>(GetNativeObject())) {
99             return mesh->SetSubmeshes(subs_).GetResult();
100         }
101     }
102     return false;
103 }
104 
GetSubmesh(NapiApi::FunctionContext<> & ctx)105 napi_value MeshJS::GetSubmesh(NapiApi::FunctionContext<>& ctx)
106 {
107     if (!validateSceneRef()) {
108         return ctx.GetUndefined();
109     }
110     auto node = interface_pointer_cast<SCENE_NS::IMesh>(GetThisNativeObject(ctx));
111     if (!node) {
112         // return undefined.. as no actual node.
113         return ctx.GetUndefined();
114     }
115 
116     subs_ = node->GetSubmeshes().GetResult();
117 
118     NapiApi::Env env(ctx.Env());
119     napi_value tmp;
120     auto status = napi_create_array_with_length(env, subs_.size(), &tmp);
121     uint32_t i = 0;
122     for (const auto& subMesh : subs_) {
123         napi_value args[] = { scene_.GetValue(), ctx.This().ToNapiValue(), env.GetNumber(i) };
124 
125         auto subobj = interface_pointer_cast<META_NS::IObject>(subMesh);
126         auto val = CreateFromNativeInstance(ctx.Env(), subobj, true, BASE_NS::countof(args), args);
127         status = napi_set_element(ctx.Env(), tmp, i++, val.ToNapiValue());
128     }
129 
130     return tmp;
131 }
132 
GetAABB(NapiApi::FunctionContext<> & ctx)133 napi_value MeshJS::GetAABB(NapiApi::FunctionContext<>& ctx)
134 {
135     if (!validateSceneRef()) {
136         return ctx.GetUndefined();
137     }
138     auto node = interface_pointer_cast<SCENE_NS::IMesh>(GetThisNativeObject(ctx));
139     if (!node) {
140         // return undefined.. as no actual node.
141         return ctx.GetUndefined();
142     }
143     BASE_NS::Math::Vec3 aabmin;
144     BASE_NS::Math::Vec3 aabmax;
145     aabmin = node->AABBMin()->GetValue();
146     aabmax = node->AABBMax()->GetValue();
147     NapiApi::Env env(ctx.Env());
148     NapiApi::Object res(env);
149 
150     NapiApi::Object min(env);
151     min.Set("x", NapiApi::Value<float> { env, aabmin.x });
152     min.Set("y", NapiApi::Value<float> { env, aabmin.y });
153     min.Set("z", NapiApi::Value<float> { env, aabmin.z });
154     res.Set("aabbMin", min);
155 
156     NapiApi::Object max(env);
157     max.Set("x", NapiApi::Value<float> { env, aabmax.x });
158     max.Set("y", NapiApi::Value<float> { env, aabmax.y });
159     max.Set("z", NapiApi::Value<float> { env, aabmax.z });
160     res.Set("aabbMax", max);
161     return res.ToNapiValue();
162 }
163 
GetMaterialOverride(NapiApi::FunctionContext<> & ctx)164 napi_value MeshJS::GetMaterialOverride(NapiApi::FunctionContext<>& ctx)
165 {
166     if (!validateSceneRef()) {
167         return ctx.GetUndefined();
168     }
169     auto sm = interface_pointer_cast<SCENE_NS::IMesh>(GetThisNativeObject(ctx));
170     if (!sm) {
171         // return undefined.. as submesh bound.
172         return ctx.GetUndefined();
173     }
174     META_NS::IObject::Ptr obj;
175     auto material = sm->MaterialOverride()->GetValue();
176     obj = interface_pointer_cast<META_NS::IObject>(material);
177 
178     if (obj == nullptr) {
179         return ctx.GetUndefined();
180     }
181     if (auto cached = FetchJsObj(obj)) {
182         // always return the same js object.
183         return cached.ToNapiValue();
184     }
185     napi_value args[] = { ctx.This().ToNapiValue() };
186     return CreateFromNativeInstance(
187         ctx.Env(), obj, false /*these are owned by the scene*/, BASE_NS::countof(args), args)
188         .ToNapiValue();
189 }
190 
SetMaterialOverride(NapiApi::FunctionContext<NapiApi::Object> & ctx)191 void MeshJS::SetMaterialOverride(NapiApi::FunctionContext<NapiApi::Object>& ctx)
192 {
193     if (!validateSceneRef()) {
194         return;
195     }
196     auto sm = interface_pointer_cast<SCENE_NS::IMesh>(GetThisNativeObject(ctx));
197     if (!sm) {
198         return;
199     }
200     NapiApi::Object obj = ctx.Arg<0>();
201     auto new_material = GetNativeMeta<SCENE_NS::IMaterial>(obj);
202     sm->MaterialOverride()->SetValue(new_material);
203 }
204