1 | /**************************************************************************/ |
2 | /* mesh.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "mesh.h" |
32 | |
33 | #include "core/math/convex_hull.h" |
34 | #include "core/templates/pair.h" |
35 | #include "scene/resources/surface_tool.h" |
36 | |
37 | #include "scene/resources/concave_polygon_shape_3d.h" |
38 | #include "scene/resources/convex_polygon_shape_3d.h" |
39 | |
40 | void MeshConvexDecompositionSettings::set_max_concavity(real_t p_max_concavity) { |
41 | max_concavity = CLAMP(p_max_concavity, 0.001, 1.0); |
42 | } |
43 | |
44 | real_t MeshConvexDecompositionSettings::get_max_concavity() const { |
45 | return max_concavity; |
46 | }; |
47 | |
48 | void MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias(real_t p_symmetry_planes_clipping_bias) { |
49 | symmetry_planes_clipping_bias = CLAMP(p_symmetry_planes_clipping_bias, 0.0, 1.0); |
50 | }; |
51 | |
52 | real_t MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias() const { |
53 | return symmetry_planes_clipping_bias; |
54 | }; |
55 | |
56 | void MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias(real_t p_revolution_axes_clipping_bias) { |
57 | revolution_axes_clipping_bias = CLAMP(p_revolution_axes_clipping_bias, 0.0, 1.0); |
58 | }; |
59 | |
60 | real_t MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias() const { |
61 | return revolution_axes_clipping_bias; |
62 | }; |
63 | |
64 | void MeshConvexDecompositionSettings::set_min_volume_per_convex_hull(real_t p_min_volume_per_convex_hull) { |
65 | min_volume_per_convex_hull = CLAMP(p_min_volume_per_convex_hull, 0.0001, 0.01); |
66 | } |
67 | |
68 | real_t MeshConvexDecompositionSettings::get_min_volume_per_convex_hull() const { |
69 | return min_volume_per_convex_hull; |
70 | } |
71 | |
72 | void MeshConvexDecompositionSettings::set_resolution(uint32_t p_resolution) { |
73 | resolution = p_resolution < 10'000 ? 10'000 : (p_resolution > 100'000 ? 100'000 : p_resolution); |
74 | } |
75 | |
76 | uint32_t MeshConvexDecompositionSettings::get_resolution() const { |
77 | return resolution; |
78 | } |
79 | |
80 | void MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull(uint32_t p_max_num_vertices_per_convex_hull) { |
81 | max_num_vertices_per_convex_hull = p_max_num_vertices_per_convex_hull < 4 ? 4 : (p_max_num_vertices_per_convex_hull > 1024 ? 1024 : p_max_num_vertices_per_convex_hull); |
82 | } |
83 | |
84 | uint32_t MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull() const { |
85 | return max_num_vertices_per_convex_hull; |
86 | } |
87 | |
88 | void MeshConvexDecompositionSettings::set_plane_downsampling(uint32_t p_plane_downsampling) { |
89 | plane_downsampling = p_plane_downsampling < 1 ? 1 : (p_plane_downsampling > 16 ? 16 : p_plane_downsampling); |
90 | } |
91 | |
92 | uint32_t MeshConvexDecompositionSettings::get_plane_downsampling() const { |
93 | return plane_downsampling; |
94 | } |
95 | |
96 | void MeshConvexDecompositionSettings::set_convex_hull_downsampling(uint32_t p_convex_hull_downsampling) { |
97 | convex_hull_downsampling = p_convex_hull_downsampling < 1 ? 1 : (p_convex_hull_downsampling > 16 ? 16 : p_convex_hull_downsampling); |
98 | } |
99 | |
100 | uint32_t MeshConvexDecompositionSettings::get_convex_hull_downsampling() const { |
101 | return convex_hull_downsampling; |
102 | } |
103 | |
104 | void MeshConvexDecompositionSettings::set_normalize_mesh(bool p_normalize_mesh) { |
105 | normalize_mesh = p_normalize_mesh; |
106 | } |
107 | |
108 | bool MeshConvexDecompositionSettings::get_normalize_mesh() const { |
109 | return normalize_mesh; |
110 | } |
111 | |
112 | void MeshConvexDecompositionSettings::set_mode(Mode p_mode) { |
113 | mode = p_mode; |
114 | } |
115 | |
116 | MeshConvexDecompositionSettings::Mode MeshConvexDecompositionSettings::get_mode() const { |
117 | return mode; |
118 | } |
119 | |
120 | void MeshConvexDecompositionSettings::set_convex_hull_approximation(bool p_convex_hull_approximation) { |
121 | convex_hull_approximation = p_convex_hull_approximation; |
122 | } |
123 | |
124 | bool MeshConvexDecompositionSettings::get_convex_hull_approximation() const { |
125 | return convex_hull_approximation; |
126 | } |
127 | |
128 | void MeshConvexDecompositionSettings::set_max_convex_hulls(uint32_t p_max_convex_hulls) { |
129 | max_convex_hulls = p_max_convex_hulls < 1 ? 1 : (p_max_convex_hulls > 32 ? 32 : p_max_convex_hulls); |
130 | } |
131 | |
132 | uint32_t MeshConvexDecompositionSettings::get_max_convex_hulls() const { |
133 | return max_convex_hulls; |
134 | } |
135 | |
136 | void MeshConvexDecompositionSettings::set_project_hull_vertices(bool p_project_hull_vertices) { |
137 | project_hull_vertices = p_project_hull_vertices; |
138 | } |
139 | |
140 | bool MeshConvexDecompositionSettings::get_project_hull_vertices() const { |
141 | return project_hull_vertices; |
142 | } |
143 | |
144 | void MeshConvexDecompositionSettings::_bind_methods() { |
145 | ClassDB::bind_method(D_METHOD("set_max_concavity" , "max_concavity" ), &MeshConvexDecompositionSettings::set_max_concavity); |
146 | ClassDB::bind_method(D_METHOD("get_max_concavity" ), &MeshConvexDecompositionSettings::get_max_concavity); |
147 | |
148 | ClassDB::bind_method(D_METHOD("set_symmetry_planes_clipping_bias" , "symmetry_planes_clipping_bias" ), &MeshConvexDecompositionSettings::set_symmetry_planes_clipping_bias); |
149 | ClassDB::bind_method(D_METHOD("get_symmetry_planes_clipping_bias" ), &MeshConvexDecompositionSettings::get_symmetry_planes_clipping_bias); |
150 | |
151 | ClassDB::bind_method(D_METHOD("set_revolution_axes_clipping_bias" , "revolution_axes_clipping_bias" ), &MeshConvexDecompositionSettings::set_revolution_axes_clipping_bias); |
152 | ClassDB::bind_method(D_METHOD("get_revolution_axes_clipping_bias" ), &MeshConvexDecompositionSettings::get_revolution_axes_clipping_bias); |
153 | |
154 | ClassDB::bind_method(D_METHOD("set_min_volume_per_convex_hull" , "min_volume_per_convex_hull" ), &MeshConvexDecompositionSettings::set_min_volume_per_convex_hull); |
155 | ClassDB::bind_method(D_METHOD("get_min_volume_per_convex_hull" ), &MeshConvexDecompositionSettings::get_min_volume_per_convex_hull); |
156 | |
157 | ClassDB::bind_method(D_METHOD("set_resolution" , "min_volume_per_convex_hull" ), &MeshConvexDecompositionSettings::set_resolution); |
158 | ClassDB::bind_method(D_METHOD("get_resolution" ), &MeshConvexDecompositionSettings::get_resolution); |
159 | |
160 | ClassDB::bind_method(D_METHOD("set_max_num_vertices_per_convex_hull" , "max_num_vertices_per_convex_hull" ), &MeshConvexDecompositionSettings::set_max_num_vertices_per_convex_hull); |
161 | ClassDB::bind_method(D_METHOD("get_max_num_vertices_per_convex_hull" ), &MeshConvexDecompositionSettings::get_max_num_vertices_per_convex_hull); |
162 | |
163 | ClassDB::bind_method(D_METHOD("set_plane_downsampling" , "plane_downsampling" ), &MeshConvexDecompositionSettings::set_plane_downsampling); |
164 | ClassDB::bind_method(D_METHOD("get_plane_downsampling" ), &MeshConvexDecompositionSettings::get_plane_downsampling); |
165 | |
166 | ClassDB::bind_method(D_METHOD("set_convex_hull_downsampling" , "convex_hull_downsampling" ), &MeshConvexDecompositionSettings::set_convex_hull_downsampling); |
167 | ClassDB::bind_method(D_METHOD("get_convex_hull_downsampling" ), &MeshConvexDecompositionSettings::get_convex_hull_downsampling); |
168 | |
169 | ClassDB::bind_method(D_METHOD("set_normalize_mesh" , "normalize_mesh" ), &MeshConvexDecompositionSettings::set_normalize_mesh); |
170 | ClassDB::bind_method(D_METHOD("get_normalize_mesh" ), &MeshConvexDecompositionSettings::get_normalize_mesh); |
171 | |
172 | ClassDB::bind_method(D_METHOD("set_mode" , "mode" ), &MeshConvexDecompositionSettings::set_mode); |
173 | ClassDB::bind_method(D_METHOD("get_mode" ), &MeshConvexDecompositionSettings::get_mode); |
174 | |
175 | ClassDB::bind_method(D_METHOD("set_convex_hull_approximation" , "convex_hull_approximation" ), &MeshConvexDecompositionSettings::set_convex_hull_approximation); |
176 | ClassDB::bind_method(D_METHOD("get_convex_hull_approximation" ), &MeshConvexDecompositionSettings::get_convex_hull_approximation); |
177 | |
178 | ClassDB::bind_method(D_METHOD("set_max_convex_hulls" , "max_convex_hulls" ), &MeshConvexDecompositionSettings::set_max_convex_hulls); |
179 | ClassDB::bind_method(D_METHOD("get_max_convex_hulls" ), &MeshConvexDecompositionSettings::get_max_convex_hulls); |
180 | |
181 | ClassDB::bind_method(D_METHOD("set_project_hull_vertices" , "project_hull_vertices" ), &MeshConvexDecompositionSettings::set_project_hull_vertices); |
182 | ClassDB::bind_method(D_METHOD("get_project_hull_vertices" ), &MeshConvexDecompositionSettings::get_project_hull_vertices); |
183 | |
184 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_concavity" , PROPERTY_HINT_RANGE, "0.001,1.0,0.001" ), "set_max_concavity" , "get_max_concavity" ); |
185 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "symmetry_planes_clipping_bias" , PROPERTY_HINT_RANGE, "0.0,1.0,0.01" ), "set_symmetry_planes_clipping_bias" , "get_symmetry_planes_clipping_bias" ); |
186 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "revolution_axes_clipping_bias" , PROPERTY_HINT_RANGE, "0.0,1.0,0.01" ), "set_revolution_axes_clipping_bias" , "get_revolution_axes_clipping_bias" ); |
187 | ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "min_volume_per_convex_hull" , PROPERTY_HINT_RANGE, "0.0001,0.01,0.0001" ), "set_min_volume_per_convex_hull" , "get_min_volume_per_convex_hull" ); |
188 | ADD_PROPERTY(PropertyInfo(Variant::INT, "resolution" ), "set_resolution" , "get_resolution" ); |
189 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_num_vertices_per_convex_hull" ), "set_max_num_vertices_per_convex_hull" , "get_max_num_vertices_per_convex_hull" ); |
190 | ADD_PROPERTY(PropertyInfo(Variant::INT, "plane_downsampling" , PROPERTY_HINT_RANGE, "1,16,1" ), "set_plane_downsampling" , "get_plane_downsampling" ); |
191 | ADD_PROPERTY(PropertyInfo(Variant::INT, "convex_hull_downsampling" , PROPERTY_HINT_RANGE, "1,16,1" ), "set_convex_hull_downsampling" , "get_convex_hull_downsampling" ); |
192 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalize_mesh" ), "set_normalize_mesh" , "get_normalize_mesh" ); |
193 | ADD_PROPERTY(PropertyInfo(Variant::INT, "mode" , PROPERTY_HINT_ENUM, "Voxel,Tetrahedron" ), "set_mode" , "get_mode" ); |
194 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "convex_hull_approximation" ), "set_convex_hull_approximation" , "get_convex_hull_approximation" ); |
195 | ADD_PROPERTY(PropertyInfo(Variant::INT, "max_convex_hulls" ), "set_max_convex_hulls" , "get_max_convex_hulls" ); |
196 | ADD_PROPERTY(PropertyInfo(Variant::BOOL, "project_hull_vertices" ), "set_project_hull_vertices" , "get_project_hull_vertices" ); |
197 | |
198 | BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_VOXEL); |
199 | BIND_ENUM_CONSTANT(CONVEX_DECOMPOSITION_MODE_TETRAHEDRON); |
200 | } |
201 | |
202 | Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; |
203 | |
204 | int Mesh::get_surface_count() const { |
205 | int ret = 0; |
206 | GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret); |
207 | return ret; |
208 | } |
209 | |
210 | int Mesh::surface_get_array_len(int p_idx) const { |
211 | int ret = 0; |
212 | GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret); |
213 | return ret; |
214 | } |
215 | |
216 | int Mesh::surface_get_array_index_len(int p_idx) const { |
217 | int ret = 0; |
218 | GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret); |
219 | return ret; |
220 | } |
221 | |
222 | Array Mesh::surface_get_arrays(int p_surface) const { |
223 | Array ret; |
224 | GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret); |
225 | return ret; |
226 | } |
227 | |
228 | TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const { |
229 | TypedArray<Array> ret; |
230 | GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret); |
231 | return ret; |
232 | } |
233 | |
234 | Dictionary Mesh::surface_get_lods(int p_surface) const { |
235 | Dictionary ret; |
236 | GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret); |
237 | return ret; |
238 | } |
239 | |
240 | BitField<Mesh::ArrayFormat> Mesh::surface_get_format(int p_idx) const { |
241 | uint32_t ret = 0; |
242 | GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret); |
243 | return ret; |
244 | } |
245 | |
246 | Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { |
247 | uint32_t ret = PRIMITIVE_MAX; |
248 | GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret); |
249 | return (Mesh::PrimitiveType)ret; |
250 | } |
251 | |
252 | void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { |
253 | GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material); |
254 | } |
255 | |
256 | Ref<Material> Mesh::surface_get_material(int p_idx) const { |
257 | Ref<Material> ret; |
258 | GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret); |
259 | return ret; |
260 | } |
261 | |
262 | int Mesh::get_blend_shape_count() const { |
263 | int ret = 0; |
264 | GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret); |
265 | return ret; |
266 | } |
267 | |
268 | StringName Mesh::get_blend_shape_name(int p_index) const { |
269 | StringName ret; |
270 | GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret); |
271 | return ret; |
272 | } |
273 | |
274 | void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) { |
275 | GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name); |
276 | } |
277 | |
278 | AABB Mesh::get_aabb() const { |
279 | AABB ret; |
280 | GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret); |
281 | return ret; |
282 | } |
283 | |
284 | Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { |
285 | if (triangle_mesh.is_valid()) { |
286 | return triangle_mesh; |
287 | } |
288 | |
289 | int faces_size = 0; |
290 | |
291 | for (int i = 0; i < get_surface_count(); i++) { |
292 | switch (surface_get_primitive_type(i)) { |
293 | case PRIMITIVE_TRIANGLES: { |
294 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); |
295 | // Don't error if zero, it's valid (we'll just skip it later). |
296 | ERR_CONTINUE_MSG((len % 3) != 0, vformat("Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLES)." , i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index" : "vertex" , len)); |
297 | faces_size += len; |
298 | } break; |
299 | case PRIMITIVE_TRIANGLE_STRIP: { |
300 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); |
301 | // Don't error if zero, it's valid (we'll just skip it later). |
302 | ERR_CONTINUE_MSG(len != 0 && len < 3, vformat("Ignoring surface %d, incorrect %s count: %d (for PRIMITIVE_TRIANGLE_STRIP)." , i, (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? "index" : "vertex" , len)); |
303 | faces_size += (len == 0) ? 0 : (len - 2) * 3; |
304 | } break; |
305 | default: { |
306 | } break; |
307 | } |
308 | } |
309 | |
310 | if (faces_size == 0) { |
311 | return triangle_mesh; |
312 | } |
313 | |
314 | Vector<Vector3> faces; |
315 | faces.resize(faces_size); |
316 | Vector<int32_t> surface_indices; |
317 | surface_indices.resize(faces_size / 3); |
318 | Vector3 *facesw = faces.ptrw(); |
319 | int32_t *surface_indicesw = surface_indices.ptrw(); |
320 | |
321 | int widx = 0; |
322 | |
323 | for (int i = 0; i < get_surface_count(); i++) { |
324 | Mesh::PrimitiveType primitive = surface_get_primitive_type(i); |
325 | if (primitive != PRIMITIVE_TRIANGLES && primitive != PRIMITIVE_TRIANGLE_STRIP) { |
326 | continue; |
327 | } |
328 | int len = (surface_get_format(i) & ARRAY_FORMAT_INDEX) ? surface_get_array_index_len(i) : surface_get_array_len(i); |
329 | if ((primitive == PRIMITIVE_TRIANGLES && (len == 0 || (len % 3) != 0)) || |
330 | (primitive == PRIMITIVE_TRIANGLE_STRIP && len < 3) || |
331 | (surface_get_format(i) & ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) { |
332 | // Error was already shown, just skip (including zero). |
333 | continue; |
334 | } |
335 | |
336 | Array a = surface_get_arrays(i); |
337 | ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); |
338 | |
339 | int vc = surface_get_array_len(i); |
340 | Vector<Vector3> vertices = a[ARRAY_VERTEX]; |
341 | ERR_FAIL_COND_V(vertices.is_empty(), Ref<TriangleMesh>()); |
342 | const Vector3 *vr = vertices.ptr(); |
343 | |
344 | int32_t from_index = widx / 3; |
345 | |
346 | if (surface_get_format(i) & ARRAY_FORMAT_INDEX) { |
347 | int ic = surface_get_array_index_len(i); |
348 | Vector<int> indices = a[ARRAY_INDEX]; |
349 | const int *ir = indices.ptr(); |
350 | |
351 | if (primitive == PRIMITIVE_TRIANGLES) { |
352 | for (int j = 0; j < ic; j++) { |
353 | int index = ir[j]; |
354 | ERR_FAIL_COND_V(index >= vc, Ref<TriangleMesh>()); |
355 | facesw[widx++] = vr[index]; |
356 | } |
357 | } else { // PRIMITIVE_TRIANGLE_STRIP |
358 | for (int j = 2; j < ic; j++) { |
359 | facesw[widx++] = vr[ir[j - 2]]; |
360 | facesw[widx++] = vr[ir[j - 1]]; |
361 | facesw[widx++] = vr[ir[j]]; |
362 | } |
363 | } |
364 | |
365 | } else { |
366 | if (primitive == PRIMITIVE_TRIANGLES) { |
367 | for (int j = 0; j < vc; j++) { |
368 | facesw[widx++] = vr[j]; |
369 | } |
370 | } else { // PRIMITIVE_TRIANGLE_STRIP |
371 | for (int j = 2; j < vc; j++) { |
372 | facesw[widx++] = vr[j - 2]; |
373 | facesw[widx++] = vr[j - 1]; |
374 | facesw[widx++] = vr[j]; |
375 | } |
376 | } |
377 | } |
378 | |
379 | int32_t to_index = widx / 3; |
380 | |
381 | for (int j = from_index; j < to_index; j++) { |
382 | surface_indicesw[j] = i; |
383 | } |
384 | } |
385 | |
386 | triangle_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); |
387 | triangle_mesh->create(faces); |
388 | |
389 | return triangle_mesh; |
390 | } |
391 | |
392 | Ref<TriangleMesh> Mesh::generate_surface_triangle_mesh(int p_surface) const { |
393 | ERR_FAIL_INDEX_V(p_surface, get_surface_count(), Ref<TriangleMesh>()); |
394 | |
395 | if (surface_triangle_meshes.size() != get_surface_count()) { |
396 | surface_triangle_meshes.resize(get_surface_count()); |
397 | } |
398 | |
399 | if (surface_triangle_meshes[p_surface].is_valid()) { |
400 | return surface_triangle_meshes[p_surface]; |
401 | } |
402 | |
403 | int facecount = 0; |
404 | |
405 | if (surface_get_primitive_type(p_surface) != PRIMITIVE_TRIANGLES) { |
406 | return Ref<TriangleMesh>(); |
407 | } |
408 | |
409 | if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { |
410 | facecount += surface_get_array_index_len(p_surface); |
411 | } else { |
412 | facecount += surface_get_array_len(p_surface); |
413 | } |
414 | |
415 | Vector<Vector3> faces; |
416 | faces.resize(facecount); |
417 | Vector3 *facesw = faces.ptrw(); |
418 | |
419 | Array a = surface_get_arrays(p_surface); |
420 | ERR_FAIL_COND_V(a.is_empty(), Ref<TriangleMesh>()); |
421 | |
422 | int vc = surface_get_array_len(p_surface); |
423 | Vector<Vector3> vertices = a[ARRAY_VERTEX]; |
424 | const Vector3 *vr = vertices.ptr(); |
425 | int widx = 0; |
426 | |
427 | if (surface_get_format(p_surface) & ARRAY_FORMAT_INDEX) { |
428 | int ic = surface_get_array_index_len(p_surface); |
429 | Vector<int> indices = a[ARRAY_INDEX]; |
430 | const int *ir = indices.ptr(); |
431 | |
432 | for (int j = 0; j < ic; j++) { |
433 | int index = ir[j]; |
434 | facesw[widx++] = vr[index]; |
435 | } |
436 | |
437 | } else { |
438 | for (int j = 0; j < vc; j++) { |
439 | facesw[widx++] = vr[j]; |
440 | } |
441 | } |
442 | |
443 | Ref<TriangleMesh> tr_mesh = Ref<TriangleMesh>(memnew(TriangleMesh)); |
444 | tr_mesh->create(faces); |
445 | surface_triangle_meshes.set(p_surface, tr_mesh); |
446 | |
447 | return tr_mesh; |
448 | } |
449 | |
450 | void Mesh::generate_debug_mesh_lines(Vector<Vector3> &r_lines) { |
451 | if (debug_lines.size() > 0) { |
452 | r_lines = debug_lines; |
453 | return; |
454 | } |
455 | |
456 | Ref<TriangleMesh> tm = generate_triangle_mesh(); |
457 | if (tm.is_null()) { |
458 | return; |
459 | } |
460 | |
461 | Vector<int> triangle_indices; |
462 | tm->get_indices(&triangle_indices); |
463 | const int triangles_num = tm->get_triangles().size(); |
464 | Vector<Vector3> vertices = tm->get_vertices(); |
465 | |
466 | debug_lines.resize(tm->get_triangles().size() * 6); // 3 lines x 2 points each line |
467 | |
468 | const int *ind_r = triangle_indices.ptr(); |
469 | const Vector3 *ver_r = vertices.ptr(); |
470 | for (int j = 0, x = 0, i = 0; i < triangles_num; j += 6, x += 3, ++i) { |
471 | // Triangle line 1 |
472 | debug_lines.write[j + 0] = ver_r[ind_r[x + 0]]; |
473 | debug_lines.write[j + 1] = ver_r[ind_r[x + 1]]; |
474 | |
475 | // Triangle line 2 |
476 | debug_lines.write[j + 2] = ver_r[ind_r[x + 1]]; |
477 | debug_lines.write[j + 3] = ver_r[ind_r[x + 2]]; |
478 | |
479 | // Triangle line 3 |
480 | debug_lines.write[j + 4] = ver_r[ind_r[x + 2]]; |
481 | debug_lines.write[j + 5] = ver_r[ind_r[x + 0]]; |
482 | } |
483 | |
484 | r_lines = debug_lines; |
485 | } |
486 | |
487 | void Mesh::generate_debug_mesh_indices(Vector<Vector3> &r_points) { |
488 | Ref<TriangleMesh> tm = generate_triangle_mesh(); |
489 | if (tm.is_null()) { |
490 | return; |
491 | } |
492 | |
493 | Vector<Vector3> vertices = tm->get_vertices(); |
494 | |
495 | int vertices_size = vertices.size(); |
496 | r_points.resize(vertices_size); |
497 | for (int i = 0; i < vertices_size; ++i) { |
498 | r_points.write[i] = vertices[i]; |
499 | } |
500 | } |
501 | |
502 | Vector<Vector3> Mesh::_get_faces() const { |
503 | return Variant(get_faces()); |
504 | } |
505 | |
506 | Vector<Face3> Mesh::get_faces() const { |
507 | Ref<TriangleMesh> tm = generate_triangle_mesh(); |
508 | if (tm.is_valid()) { |
509 | return tm->get_faces(); |
510 | } |
511 | return Vector<Face3>(); |
512 | } |
513 | |
514 | Vector<Face3> Mesh::get_surface_faces(int p_surface) const { |
515 | Ref<TriangleMesh> tm = generate_surface_triangle_mesh(p_surface); |
516 | if (tm.is_valid()) { |
517 | return tm->get_faces(); |
518 | } |
519 | return Vector<Face3>(); |
520 | } |
521 | |
522 | Ref<ConvexPolygonShape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { |
523 | if (p_simplify) { |
524 | Ref<MeshConvexDecompositionSettings> settings = Ref<MeshConvexDecompositionSettings>(); |
525 | settings.instantiate(); |
526 | settings->set_max_convex_hulls(1); |
527 | settings->set_max_concavity(1.0); |
528 | Vector<Ref<Shape3D>> decomposed = convex_decompose(settings); |
529 | if (decomposed.size() == 1) { |
530 | return decomposed[0]; |
531 | } else { |
532 | ERR_PRINT("Convex shape simplification failed, falling back to simpler process." ); |
533 | } |
534 | } |
535 | |
536 | Vector<Vector3> vertices; |
537 | for (int i = 0; i < get_surface_count(); i++) { |
538 | Array a = surface_get_arrays(i); |
539 | ERR_FAIL_COND_V(a.is_empty(), Ref<ConvexPolygonShape3D>()); |
540 | Vector<Vector3> v = a[ARRAY_VERTEX]; |
541 | vertices.append_array(v); |
542 | } |
543 | |
544 | Ref<ConvexPolygonShape3D> shape = memnew(ConvexPolygonShape3D); |
545 | |
546 | if (p_clean) { |
547 | Geometry3D::MeshData md; |
548 | Error err = ConvexHullComputer::convex_hull(vertices, md); |
549 | if (err == OK) { |
550 | shape->set_points(md.vertices); |
551 | return shape; |
552 | } else { |
553 | ERR_PRINT("Convex shape cleaning failed, falling back to simpler process." ); |
554 | } |
555 | } |
556 | |
557 | shape->set_points(vertices); |
558 | return shape; |
559 | } |
560 | |
561 | Ref<ConcavePolygonShape3D> Mesh::create_trimesh_shape() const { |
562 | Vector<Face3> faces = get_faces(); |
563 | if (faces.size() == 0) { |
564 | return Ref<ConcavePolygonShape3D>(); |
565 | } |
566 | |
567 | Vector<Vector3> face_points; |
568 | face_points.resize(faces.size() * 3); |
569 | |
570 | for (int i = 0; i < face_points.size(); i += 3) { |
571 | Face3 f = faces.get(i / 3); |
572 | face_points.set(i, f.vertex[0]); |
573 | face_points.set(i + 1, f.vertex[1]); |
574 | face_points.set(i + 2, f.vertex[2]); |
575 | } |
576 | |
577 | Ref<ConcavePolygonShape3D> shape = memnew(ConcavePolygonShape3D); |
578 | shape->set_faces(face_points); |
579 | return shape; |
580 | } |
581 | |
582 | Ref<Mesh> Mesh::create_outline(float p_margin) const { |
583 | Array arrays; |
584 | int index_accum = 0; |
585 | for (int i = 0; i < get_surface_count(); i++) { |
586 | if (surface_get_primitive_type(i) != PRIMITIVE_TRIANGLES) { |
587 | continue; |
588 | } |
589 | |
590 | Array a = surface_get_arrays(i); |
591 | ERR_FAIL_COND_V(a.is_empty(), Ref<ArrayMesh>()); |
592 | |
593 | if (i == 0) { |
594 | arrays = a; |
595 | Vector<Vector3> v = a[ARRAY_VERTEX]; |
596 | index_accum += v.size(); |
597 | } else { |
598 | int vcount = 0; |
599 | for (int j = 0; j < arrays.size(); j++) { |
600 | if (arrays[j].get_type() == Variant::NIL || a[j].get_type() == Variant::NIL) { |
601 | //mismatch, do not use |
602 | arrays[j] = Variant(); |
603 | continue; |
604 | } |
605 | |
606 | switch (j) { |
607 | case ARRAY_VERTEX: |
608 | case ARRAY_NORMAL: { |
609 | Vector<Vector3> dst = arrays[j]; |
610 | Vector<Vector3> src = a[j]; |
611 | if (j == ARRAY_VERTEX) { |
612 | vcount = src.size(); |
613 | } |
614 | if (dst.size() == 0 || src.size() == 0) { |
615 | arrays[j] = Variant(); |
616 | continue; |
617 | } |
618 | dst.append_array(src); |
619 | arrays[j] = dst; |
620 | } break; |
621 | case ARRAY_TANGENT: |
622 | case ARRAY_BONES: |
623 | case ARRAY_WEIGHTS: { |
624 | Vector<real_t> dst = arrays[j]; |
625 | Vector<real_t> src = a[j]; |
626 | if (dst.size() == 0 || src.size() == 0) { |
627 | arrays[j] = Variant(); |
628 | continue; |
629 | } |
630 | dst.append_array(src); |
631 | arrays[j] = dst; |
632 | |
633 | } break; |
634 | case ARRAY_COLOR: { |
635 | Vector<Color> dst = arrays[j]; |
636 | Vector<Color> src = a[j]; |
637 | if (dst.size() == 0 || src.size() == 0) { |
638 | arrays[j] = Variant(); |
639 | continue; |
640 | } |
641 | dst.append_array(src); |
642 | arrays[j] = dst; |
643 | |
644 | } break; |
645 | case ARRAY_TEX_UV: |
646 | case ARRAY_TEX_UV2: { |
647 | Vector<Vector2> dst = arrays[j]; |
648 | Vector<Vector2> src = a[j]; |
649 | if (dst.size() == 0 || src.size() == 0) { |
650 | arrays[j] = Variant(); |
651 | continue; |
652 | } |
653 | dst.append_array(src); |
654 | arrays[j] = dst; |
655 | |
656 | } break; |
657 | case ARRAY_INDEX: { |
658 | Vector<int> dst = arrays[j]; |
659 | Vector<int> src = a[j]; |
660 | if (dst.size() == 0 || src.size() == 0) { |
661 | arrays[j] = Variant(); |
662 | continue; |
663 | } |
664 | { |
665 | int ss = src.size(); |
666 | int *w = src.ptrw(); |
667 | for (int k = 0; k < ss; k++) { |
668 | w[k] += index_accum; |
669 | } |
670 | } |
671 | dst.append_array(src); |
672 | arrays[j] = dst; |
673 | index_accum += vcount; |
674 | |
675 | } break; |
676 | } |
677 | } |
678 | } |
679 | } |
680 | |
681 | ERR_FAIL_COND_V(arrays.size() != ARRAY_MAX, Ref<ArrayMesh>()); |
682 | |
683 | { |
684 | int *ir = nullptr; |
685 | Vector<int> indices = arrays[ARRAY_INDEX]; |
686 | bool has_indices = false; |
687 | Vector<Vector3> vertices = arrays[ARRAY_VERTEX]; |
688 | int vc = vertices.size(); |
689 | ERR_FAIL_COND_V(!vc, Ref<ArrayMesh>()); |
690 | Vector3 *r = vertices.ptrw(); |
691 | |
692 | if (indices.size()) { |
693 | ERR_FAIL_COND_V(indices.size() % 3 != 0, Ref<ArrayMesh>()); |
694 | vc = indices.size(); |
695 | ir = indices.ptrw(); |
696 | has_indices = true; |
697 | } else { |
698 | // Ensure there are enough vertices to construct at least one triangle. |
699 | ERR_FAIL_COND_V(vertices.size() % 3 != 0, Ref<ArrayMesh>()); |
700 | } |
701 | |
702 | HashMap<Vector3, Vector3> normal_accum; |
703 | |
704 | //fill normals with triangle normals |
705 | for (int i = 0; i < vc; i += 3) { |
706 | Vector3 t[3]; |
707 | |
708 | if (has_indices) { |
709 | t[0] = r[ir[i + 0]]; |
710 | t[1] = r[ir[i + 1]]; |
711 | t[2] = r[ir[i + 2]]; |
712 | } else { |
713 | t[0] = r[i + 0]; |
714 | t[1] = r[i + 1]; |
715 | t[2] = r[i + 2]; |
716 | } |
717 | |
718 | Vector3 n = Plane(t[0], t[1], t[2]).normal; |
719 | |
720 | for (int j = 0; j < 3; j++) { |
721 | HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t[j]); |
722 | if (!E) { |
723 | normal_accum[t[j]] = n; |
724 | } else { |
725 | float d = n.dot(E->value); |
726 | if (d < 1.0) { |
727 | E->value += n * (1.0 - d); |
728 | } |
729 | //E->get()+=n; |
730 | } |
731 | } |
732 | } |
733 | |
734 | //normalize |
735 | |
736 | for (KeyValue<Vector3, Vector3> &E : normal_accum) { |
737 | E.value.normalize(); |
738 | } |
739 | |
740 | //displace normals |
741 | int vc2 = vertices.size(); |
742 | |
743 | for (int i = 0; i < vc2; i++) { |
744 | Vector3 t = r[i]; |
745 | |
746 | HashMap<Vector3, Vector3>::Iterator E = normal_accum.find(t); |
747 | ERR_CONTINUE(!E); |
748 | |
749 | t += E->value * p_margin; |
750 | r[i] = t; |
751 | } |
752 | |
753 | arrays[ARRAY_VERTEX] = vertices; |
754 | |
755 | if (!has_indices) { |
756 | Vector<int> new_indices; |
757 | new_indices.resize(vertices.size()); |
758 | int *iw = new_indices.ptrw(); |
759 | |
760 | for (int j = 0; j < vc2; j += 3) { |
761 | iw[j] = j; |
762 | iw[j + 1] = j + 2; |
763 | iw[j + 2] = j + 1; |
764 | } |
765 | |
766 | arrays[ARRAY_INDEX] = new_indices; |
767 | |
768 | } else { |
769 | for (int j = 0; j < vc; j += 3) { |
770 | SWAP(ir[j + 1], ir[j + 2]); |
771 | } |
772 | arrays[ARRAY_INDEX] = indices; |
773 | } |
774 | } |
775 | |
776 | Ref<ArrayMesh> newmesh = memnew(ArrayMesh); |
777 | newmesh->add_surface_from_arrays(PRIMITIVE_TRIANGLES, arrays); |
778 | return newmesh; |
779 | } |
780 | |
781 | void Mesh::set_lightmap_size_hint(const Size2i &p_size) { |
782 | lightmap_size_hint = p_size; |
783 | } |
784 | |
785 | Size2i Mesh::get_lightmap_size_hint() const { |
786 | return lightmap_size_hint; |
787 | } |
788 | |
789 | Ref<Resource> Mesh::create_placeholder() const { |
790 | Ref<PlaceholderMesh> placeholder; |
791 | placeholder.instantiate(); |
792 | placeholder->set_aabb(get_aabb()); |
793 | return placeholder; |
794 | } |
795 | |
796 | void Mesh::_bind_methods() { |
797 | ClassDB::bind_method(D_METHOD("set_lightmap_size_hint" , "size" ), &Mesh::set_lightmap_size_hint); |
798 | ClassDB::bind_method(D_METHOD("get_lightmap_size_hint" ), &Mesh::get_lightmap_size_hint); |
799 | ClassDB::bind_method(D_METHOD("get_aabb" ), &Mesh::get_aabb); |
800 | ClassDB::bind_method(D_METHOD("get_faces" ), &Mesh::_get_faces); |
801 | |
802 | ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "lightmap_size_hint" ), "set_lightmap_size_hint" , "get_lightmap_size_hint" ); |
803 | |
804 | ClassDB::bind_method(D_METHOD("get_surface_count" ), &Mesh::get_surface_count); |
805 | ClassDB::bind_method(D_METHOD("surface_get_arrays" , "surf_idx" ), &Mesh::surface_get_arrays); |
806 | ClassDB::bind_method(D_METHOD("surface_get_blend_shape_arrays" , "surf_idx" ), &Mesh::surface_get_blend_shape_arrays); |
807 | ClassDB::bind_method(D_METHOD("surface_set_material" , "surf_idx" , "material" ), &Mesh::surface_set_material); |
808 | ClassDB::bind_method(D_METHOD("surface_get_material" , "surf_idx" ), &Mesh::surface_get_material); |
809 | ClassDB::bind_method(D_METHOD("create_placeholder" ), &Mesh::create_placeholder); |
810 | |
811 | BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); |
812 | BIND_ENUM_CONSTANT(PRIMITIVE_LINES); |
813 | BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); |
814 | BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); |
815 | BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); |
816 | |
817 | BIND_ENUM_CONSTANT(ARRAY_VERTEX); |
818 | BIND_ENUM_CONSTANT(ARRAY_NORMAL); |
819 | BIND_ENUM_CONSTANT(ARRAY_TANGENT); |
820 | BIND_ENUM_CONSTANT(ARRAY_COLOR); |
821 | BIND_ENUM_CONSTANT(ARRAY_TEX_UV); |
822 | BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); |
823 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM0); |
824 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM1); |
825 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM2); |
826 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM3); |
827 | BIND_ENUM_CONSTANT(ARRAY_BONES); |
828 | BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); |
829 | BIND_ENUM_CONSTANT(ARRAY_INDEX); |
830 | BIND_ENUM_CONSTANT(ARRAY_MAX); |
831 | |
832 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_UNORM); |
833 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA8_SNORM); |
834 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_HALF); |
835 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_HALF); |
836 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_R_FLOAT); |
837 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RG_FLOAT); |
838 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGB_FLOAT); |
839 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_RGBA_FLOAT); |
840 | BIND_ENUM_CONSTANT(ARRAY_CUSTOM_MAX); |
841 | |
842 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_VERTEX); |
843 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_NORMAL); |
844 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TANGENT); |
845 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_COLOR); |
846 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TEX_UV); |
847 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_TEX_UV2); |
848 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM0); |
849 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM1); |
850 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM2); |
851 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM3); |
852 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_BONES); |
853 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_WEIGHTS); |
854 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_INDEX); |
855 | |
856 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_BLEND_SHAPE_MASK); |
857 | |
858 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_BASE); |
859 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_BITS); |
860 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM0_SHIFT); |
861 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM1_SHIFT); |
862 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM2_SHIFT); |
863 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM3_SHIFT); |
864 | |
865 | BIND_BITFIELD_FLAG(ARRAY_FORMAT_CUSTOM_MASK); |
866 | BIND_BITFIELD_FLAG(ARRAY_COMPRESS_FLAGS_BASE); |
867 | |
868 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_2D_VERTICES); |
869 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_DYNAMIC_UPDATE); |
870 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USE_8_BONE_WEIGHTS); |
871 | BIND_BITFIELD_FLAG(ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY); |
872 | |
873 | BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); |
874 | BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); |
875 | |
876 | GDVIRTUAL_BIND(_get_surface_count) |
877 | GDVIRTUAL_BIND(_surface_get_array_len, "index" ) |
878 | GDVIRTUAL_BIND(_surface_get_array_index_len, "index" ) |
879 | GDVIRTUAL_BIND(_surface_get_arrays, "index" ) |
880 | GDVIRTUAL_BIND(_surface_get_blend_shape_arrays, "index" ) |
881 | GDVIRTUAL_BIND(_surface_get_lods, "index" ) |
882 | GDVIRTUAL_BIND(_surface_get_format, "index" ) |
883 | GDVIRTUAL_BIND(_surface_get_primitive_type, "index" ) |
884 | GDVIRTUAL_BIND(_surface_set_material, "index" , "material" ) |
885 | GDVIRTUAL_BIND(_surface_get_material, "index" ) |
886 | GDVIRTUAL_BIND(_get_blend_shape_count) |
887 | GDVIRTUAL_BIND(_get_blend_shape_name, "index" ) |
888 | GDVIRTUAL_BIND(_set_blend_shape_name, "index" , "name" ) |
889 | GDVIRTUAL_BIND(_get_aabb) |
890 | } |
891 | |
892 | void Mesh::clear_cache() const { |
893 | triangle_mesh.unref(); |
894 | debug_lines.clear(); |
895 | } |
896 | |
897 | Vector<Ref<Shape3D>> Mesh::convex_decompose(const Ref<MeshConvexDecompositionSettings> &p_settings) const { |
898 | ERR_FAIL_NULL_V(convex_decomposition_function, Vector<Ref<Shape3D>>()); |
899 | |
900 | Ref<TriangleMesh> tm = generate_triangle_mesh(); |
901 | ERR_FAIL_COND_V(!tm.is_valid(), Vector<Ref<Shape3D>>()); |
902 | |
903 | const Vector<TriangleMesh::Triangle> &triangles = tm->get_triangles(); |
904 | int triangle_count = triangles.size(); |
905 | |
906 | Vector<uint32_t> indices; |
907 | { |
908 | indices.resize(triangle_count * 3); |
909 | uint32_t *w = indices.ptrw(); |
910 | for (int i = 0; i < triangle_count; i++) { |
911 | for (int j = 0; j < 3; j++) { |
912 | w[i * 3 + j] = triangles[i].indices[j]; |
913 | } |
914 | } |
915 | } |
916 | |
917 | const Vector<Vector3> &vertices = tm->get_vertices(); |
918 | int vertex_count = vertices.size(); |
919 | |
920 | Vector<Vector<Vector3>> decomposed = convex_decomposition_function((real_t *)vertices.ptr(), vertex_count, indices.ptr(), triangle_count, p_settings, nullptr); |
921 | |
922 | Vector<Ref<Shape3D>> ret; |
923 | |
924 | for (int i = 0; i < decomposed.size(); i++) { |
925 | Ref<ConvexPolygonShape3D> shape; |
926 | shape.instantiate(); |
927 | shape->set_points(decomposed[i]); |
928 | ret.push_back(shape); |
929 | } |
930 | |
931 | return ret; |
932 | } |
933 | |
934 | int Mesh::get_builtin_bind_pose_count() const { |
935 | return 0; |
936 | } |
937 | |
938 | Transform3D Mesh::get_builtin_bind_pose(int p_index) const { |
939 | return Transform3D(); |
940 | } |
941 | |
942 | Mesh::Mesh() { |
943 | } |
944 | |
945 | enum OldArrayType { |
946 | OLD_ARRAY_VERTEX, |
947 | OLD_ARRAY_NORMAL, |
948 | OLD_ARRAY_TANGENT, |
949 | OLD_ARRAY_COLOR, |
950 | OLD_ARRAY_TEX_UV, |
951 | OLD_ARRAY_TEX_UV2, |
952 | OLD_ARRAY_BONES, |
953 | OLD_ARRAY_WEIGHTS, |
954 | OLD_ARRAY_INDEX, |
955 | OLD_ARRAY_MAX, |
956 | }; |
957 | |
958 | enum OldArrayFormat { |
959 | /* OLD_ARRAY FORMAT FLAGS */ |
960 | OLD_ARRAY_FORMAT_VERTEX = 1 << OLD_ARRAY_VERTEX, // mandatory |
961 | OLD_ARRAY_FORMAT_NORMAL = 1 << OLD_ARRAY_NORMAL, |
962 | OLD_ARRAY_FORMAT_TANGENT = 1 << OLD_ARRAY_TANGENT, |
963 | OLD_ARRAY_FORMAT_COLOR = 1 << OLD_ARRAY_COLOR, |
964 | OLD_ARRAY_FORMAT_TEX_UV = 1 << OLD_ARRAY_TEX_UV, |
965 | OLD_ARRAY_FORMAT_TEX_UV2 = 1 << OLD_ARRAY_TEX_UV2, |
966 | OLD_ARRAY_FORMAT_BONES = 1 << OLD_ARRAY_BONES, |
967 | OLD_ARRAY_FORMAT_WEIGHTS = 1 << OLD_ARRAY_WEIGHTS, |
968 | OLD_ARRAY_FORMAT_INDEX = 1 << OLD_ARRAY_INDEX, |
969 | |
970 | OLD_ARRAY_COMPRESS_BASE = (OLD_ARRAY_INDEX + 1), |
971 | OLD_ARRAY_COMPRESS_VERTEX = 1 << (OLD_ARRAY_VERTEX + OLD_ARRAY_COMPRESS_BASE), // mandatory |
972 | OLD_ARRAY_COMPRESS_NORMAL = 1 << (OLD_ARRAY_NORMAL + OLD_ARRAY_COMPRESS_BASE), |
973 | OLD_ARRAY_COMPRESS_TANGENT = 1 << (OLD_ARRAY_TANGENT + OLD_ARRAY_COMPRESS_BASE), |
974 | OLD_ARRAY_COMPRESS_COLOR = 1 << (OLD_ARRAY_COLOR + OLD_ARRAY_COMPRESS_BASE), |
975 | OLD_ARRAY_COMPRESS_TEX_UV = 1 << (OLD_ARRAY_TEX_UV + OLD_ARRAY_COMPRESS_BASE), |
976 | OLD_ARRAY_COMPRESS_TEX_UV2 = 1 << (OLD_ARRAY_TEX_UV2 + OLD_ARRAY_COMPRESS_BASE), |
977 | OLD_ARRAY_COMPRESS_BONES = 1 << (OLD_ARRAY_BONES + OLD_ARRAY_COMPRESS_BASE), |
978 | OLD_ARRAY_COMPRESS_WEIGHTS = 1 << (OLD_ARRAY_WEIGHTS + OLD_ARRAY_COMPRESS_BASE), |
979 | OLD_ARRAY_COMPRESS_INDEX = 1 << (OLD_ARRAY_INDEX + OLD_ARRAY_COMPRESS_BASE), |
980 | |
981 | OLD_ARRAY_FLAG_USE_2D_VERTICES = OLD_ARRAY_COMPRESS_INDEX << 1, |
982 | OLD_ARRAY_FLAG_USE_16_BIT_BONES = OLD_ARRAY_COMPRESS_INDEX << 2, |
983 | OLD_ARRAY_FLAG_USE_DYNAMIC_UPDATE = OLD_ARRAY_COMPRESS_INDEX << 3, |
984 | OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION = OLD_ARRAY_COMPRESS_INDEX << 4, |
985 | }; |
986 | |
987 | #ifndef DISABLE_DEPRECATED |
988 | static Array _convert_old_array(const Array &p_old) { |
989 | Array new_array; |
990 | new_array.resize(Mesh::ARRAY_MAX); |
991 | new_array[Mesh::ARRAY_VERTEX] = p_old[OLD_ARRAY_VERTEX]; |
992 | new_array[Mesh::ARRAY_NORMAL] = p_old[OLD_ARRAY_NORMAL]; |
993 | new_array[Mesh::ARRAY_TANGENT] = p_old[OLD_ARRAY_TANGENT]; |
994 | new_array[Mesh::ARRAY_COLOR] = p_old[OLD_ARRAY_COLOR]; |
995 | new_array[Mesh::ARRAY_TEX_UV] = p_old[OLD_ARRAY_TEX_UV]; |
996 | new_array[Mesh::ARRAY_TEX_UV2] = p_old[OLD_ARRAY_TEX_UV2]; |
997 | new_array[Mesh::ARRAY_BONES] = p_old[OLD_ARRAY_BONES]; |
998 | new_array[Mesh::ARRAY_WEIGHTS] = p_old[OLD_ARRAY_WEIGHTS]; |
999 | new_array[Mesh::ARRAY_INDEX] = p_old[OLD_ARRAY_INDEX]; |
1000 | return new_array; |
1001 | } |
1002 | |
1003 | static Mesh::PrimitiveType _old_primitives[7] = { |
1004 | Mesh::PRIMITIVE_POINTS, |
1005 | Mesh::PRIMITIVE_LINES, |
1006 | Mesh::PRIMITIVE_LINE_STRIP, |
1007 | Mesh::PRIMITIVE_LINES, |
1008 | Mesh::PRIMITIVE_TRIANGLES, |
1009 | Mesh::PRIMITIVE_TRIANGLE_STRIP, |
1010 | Mesh::PRIMITIVE_TRIANGLE_STRIP |
1011 | }; |
1012 | #endif // DISABLE_DEPRECATED |
1013 | |
1014 | void _fix_array_compatibility(const Vector<uint8_t> &p_src, uint32_t p_old_format, uint32_t p_new_format, uint32_t p_elements, Vector<uint8_t> &vertex_data, Vector<uint8_t> &attribute_data, Vector<uint8_t> &skin_data) { |
1015 | uint32_t dst_vertex_stride; |
1016 | uint32_t dst_attribute_stride; |
1017 | uint32_t dst_skin_stride; |
1018 | uint32_t dst_offsets[Mesh::ARRAY_MAX]; |
1019 | RenderingServer::get_singleton()->mesh_surface_make_offsets_from_format(p_new_format & (~RS::ARRAY_FORMAT_INDEX), p_elements, 0, dst_offsets, dst_vertex_stride, dst_attribute_stride, dst_skin_stride); |
1020 | |
1021 | vertex_data.resize(dst_vertex_stride * p_elements); |
1022 | attribute_data.resize(dst_attribute_stride * p_elements); |
1023 | skin_data.resize(dst_skin_stride * p_elements); |
1024 | |
1025 | uint8_t *dst_vertex_ptr = vertex_data.ptrw(); |
1026 | uint8_t *dst_attribute_ptr = attribute_data.ptrw(); |
1027 | uint8_t *dst_skin_ptr = skin_data.ptrw(); |
1028 | |
1029 | const uint8_t *src_vertex_ptr = p_src.ptr(); |
1030 | uint32_t src_vertex_stride = p_src.size() / p_elements; |
1031 | |
1032 | uint32_t src_offset = 0; |
1033 | for (uint32_t j = 0; j < OLD_ARRAY_INDEX; j++) { |
1034 | if (!(p_old_format & (1 << j))) { |
1035 | continue; |
1036 | } |
1037 | switch (j) { |
1038 | case OLD_ARRAY_VERTEX: { |
1039 | if (p_old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { |
1040 | if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { |
1041 | for (uint32_t i = 0; i < p_elements; i++) { |
1042 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; |
1043 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; |
1044 | dst[0] = Math::half_to_float(src[0]); |
1045 | dst[1] = Math::half_to_float(src[1]); |
1046 | } |
1047 | src_offset += sizeof(uint16_t) * 2; |
1048 | } else { |
1049 | for (uint32_t i = 0; i < p_elements; i++) { |
1050 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; |
1051 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; |
1052 | dst[0] = src[0]; |
1053 | dst[1] = src[1]; |
1054 | } |
1055 | src_offset += sizeof(float) * 2; |
1056 | } |
1057 | } else { |
1058 | if (p_old_format & OLD_ARRAY_COMPRESS_VERTEX) { |
1059 | for (uint32_t i = 0; i < p_elements; i++) { |
1060 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride]; |
1061 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; |
1062 | dst[0] = Math::half_to_float(src[0]); |
1063 | dst[1] = Math::half_to_float(src[1]); |
1064 | dst[2] = Math::half_to_float(src[2]); |
1065 | } |
1066 | src_offset += sizeof(uint16_t) * 4; //+pad |
1067 | } else { |
1068 | for (uint32_t i = 0; i < p_elements; i++) { |
1069 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride]; |
1070 | float *dst = (float *)&dst_vertex_ptr[i * dst_vertex_stride]; |
1071 | dst[0] = src[0]; |
1072 | dst[1] = src[1]; |
1073 | dst[2] = src[2]; |
1074 | } |
1075 | src_offset += sizeof(float) * 3; |
1076 | } |
1077 | } |
1078 | } break; |
1079 | case OLD_ARRAY_NORMAL: { |
1080 | if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) { |
1081 | if ((p_old_format & OLD_ARRAY_COMPRESS_NORMAL) && (p_old_format & OLD_ARRAY_FORMAT_TANGENT) && (p_old_format & OLD_ARRAY_COMPRESS_TANGENT)) { |
1082 | for (uint32_t i = 0; i < p_elements; i++) { |
1083 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1084 | int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1085 | |
1086 | dst[0] = (int16_t)CLAMP(src[0] / 127.0f * 32767, -32768, 32767); |
1087 | dst[1] = (int16_t)CLAMP(src[1] / 127.0f * 32767, -32768, 32767); |
1088 | } |
1089 | src_offset += sizeof(int8_t) * 2; |
1090 | } else { |
1091 | for (uint32_t i = 0; i < p_elements; i++) { |
1092 | const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1093 | int16_t *dst = (int16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1094 | |
1095 | dst[0] = src[0]; |
1096 | dst[1] = src[1]; |
1097 | } |
1098 | src_offset += sizeof(int16_t) * 2; |
1099 | } |
1100 | } else { // No Octahedral compression |
1101 | if (p_old_format & OLD_ARRAY_COMPRESS_NORMAL) { |
1102 | for (uint32_t i = 0; i < p_elements; i++) { |
1103 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1104 | const Vector3 original_normal(src[0], src[1], src[2]); |
1105 | Vector2 res = original_normal.octahedron_encode(); |
1106 | |
1107 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1108 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); |
1109 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); |
1110 | } |
1111 | src_offset += sizeof(uint8_t) * 4; // 1 byte padding |
1112 | } else { |
1113 | for (uint32_t i = 0; i < p_elements; i++) { |
1114 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1115 | const Vector3 original_normal(src[0], src[1], src[2]); |
1116 | Vector2 res = original_normal.octahedron_encode(); |
1117 | |
1118 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1119 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); |
1120 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); |
1121 | } |
1122 | src_offset += sizeof(float) * 3; |
1123 | } |
1124 | } |
1125 | |
1126 | } break; |
1127 | case OLD_ARRAY_TANGENT: { |
1128 | if (p_old_format & OLD_ARRAY_FLAG_USE_OCTAHEDRAL_COMPRESSION) { |
1129 | if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { // int8 SNORM -> uint16 UNORM |
1130 | for (uint32_t i = 0; i < p_elements; i++) { |
1131 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1132 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; |
1133 | |
1134 | dst[0] = (uint16_t)CLAMP((src[0] / 127.0f * .5f + .5f) * 65535, 0, 65535); |
1135 | dst[1] = (uint16_t)CLAMP((src[1] / 127.0f * .5f + .5f) * 65535, 0, 65535); |
1136 | } |
1137 | src_offset += sizeof(uint8_t) * 2; |
1138 | } else { // int16 SNORM -> uint16 UNORM |
1139 | for (uint32_t i = 0; i < p_elements; i++) { |
1140 | const int16_t *src = (const int16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1141 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_TANGENT]]; |
1142 | |
1143 | dst[0] = (uint16_t)CLAMP((src[0] / 32767.0f * .5f + .5f) * 65535, 0, 65535); |
1144 | dst[1] = (uint16_t)CLAMP((src[1] / 32767.0f * .5f + .5f) * 65535, 0, 65535); |
1145 | } |
1146 | src_offset += sizeof(uint16_t) * 2; |
1147 | } |
1148 | } else { // No Octahedral compression |
1149 | if (p_old_format & OLD_ARRAY_COMPRESS_TANGENT) { |
1150 | for (uint32_t i = 0; i < p_elements; i++) { |
1151 | const int8_t *src = (const int8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1152 | const Vector3 original_tangent(src[0], src[1], src[2]); |
1153 | Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); |
1154 | |
1155 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1156 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); |
1157 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); |
1158 | } |
1159 | src_offset += sizeof(uint8_t) * 4; |
1160 | } else { |
1161 | for (uint32_t i = 0; i < p_elements; i++) { |
1162 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1163 | const Vector3 original_tangent(src[0], src[1], src[2]); |
1164 | Vector2 res = original_tangent.octahedron_tangent_encode(src[3]); |
1165 | |
1166 | uint16_t *dst = (uint16_t *)&dst_vertex_ptr[i * dst_vertex_stride + dst_offsets[Mesh::ARRAY_NORMAL]]; |
1167 | dst[0] = (uint16_t)CLAMP(res.x * 65535, 0, 65535); |
1168 | dst[1] = (uint16_t)CLAMP(res.y * 65535, 0, 65535); |
1169 | } |
1170 | src_offset += sizeof(float) * 4; |
1171 | } |
1172 | } |
1173 | } break; |
1174 | case OLD_ARRAY_COLOR: { |
1175 | if (p_old_format & OLD_ARRAY_COMPRESS_COLOR) { |
1176 | for (uint32_t i = 0; i < p_elements; i++) { |
1177 | const uint32_t *src = (const uint32_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1178 | uint32_t *dst = (uint32_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; |
1179 | |
1180 | *dst = *src; |
1181 | } |
1182 | src_offset += sizeof(uint32_t); |
1183 | } else { |
1184 | for (uint32_t i = 0; i < p_elements; i++) { |
1185 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1186 | uint8_t *dst = (uint8_t *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_COLOR]]; |
1187 | |
1188 | dst[0] = uint8_t(CLAMP(src[0] * 255.0, 0.0, 255.0)); |
1189 | dst[1] = uint8_t(CLAMP(src[1] * 255.0, 0.0, 255.0)); |
1190 | dst[2] = uint8_t(CLAMP(src[2] * 255.0, 0.0, 255.0)); |
1191 | dst[3] = uint8_t(CLAMP(src[3] * 255.0, 0.0, 255.0)); |
1192 | } |
1193 | src_offset += sizeof(float) * 4; |
1194 | } |
1195 | } break; |
1196 | case OLD_ARRAY_TEX_UV: { |
1197 | if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV) { |
1198 | for (uint32_t i = 0; i < p_elements; i++) { |
1199 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1200 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; |
1201 | |
1202 | dst[0] = Math::half_to_float(src[0]); |
1203 | dst[1] = Math::half_to_float(src[1]); |
1204 | } |
1205 | src_offset += sizeof(uint16_t) * 2; |
1206 | } else { |
1207 | for (uint32_t i = 0; i < p_elements; i++) { |
1208 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1209 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV]]; |
1210 | |
1211 | dst[0] = src[0]; |
1212 | dst[1] = src[1]; |
1213 | } |
1214 | src_offset += sizeof(float) * 2; |
1215 | } |
1216 | |
1217 | } break; |
1218 | case OLD_ARRAY_TEX_UV2: { |
1219 | if (p_old_format & OLD_ARRAY_COMPRESS_TEX_UV2) { |
1220 | for (uint32_t i = 0; i < p_elements; i++) { |
1221 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1222 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; |
1223 | |
1224 | dst[0] = Math::half_to_float(src[0]); |
1225 | dst[1] = Math::half_to_float(src[1]); |
1226 | } |
1227 | src_offset += sizeof(uint16_t) * 2; |
1228 | } else { |
1229 | for (uint32_t i = 0; i < p_elements; i++) { |
1230 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1231 | float *dst = (float *)&dst_attribute_ptr[i * dst_attribute_stride + dst_offsets[Mesh::ARRAY_TEX_UV2]]; |
1232 | |
1233 | dst[0] = src[0]; |
1234 | dst[1] = src[1]; |
1235 | } |
1236 | src_offset += sizeof(float) * 2; |
1237 | } |
1238 | } break; |
1239 | case OLD_ARRAY_BONES: { |
1240 | if (p_old_format & OLD_ARRAY_FLAG_USE_16_BIT_BONES) { |
1241 | for (uint32_t i = 0; i < p_elements; i++) { |
1242 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1243 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; |
1244 | |
1245 | dst[0] = src[0]; |
1246 | dst[1] = src[1]; |
1247 | dst[2] = src[2]; |
1248 | dst[3] = src[3]; |
1249 | } |
1250 | src_offset += sizeof(uint16_t) * 4; |
1251 | } else { |
1252 | for (uint32_t i = 0; i < p_elements; i++) { |
1253 | const uint8_t *src = (const uint8_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1254 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_BONES]]; |
1255 | |
1256 | dst[0] = src[0]; |
1257 | dst[1] = src[1]; |
1258 | dst[2] = src[2]; |
1259 | dst[3] = src[3]; |
1260 | } |
1261 | src_offset += sizeof(uint8_t) * 4; |
1262 | } |
1263 | } break; |
1264 | case OLD_ARRAY_WEIGHTS: { |
1265 | if (p_old_format & OLD_ARRAY_COMPRESS_WEIGHTS) { |
1266 | for (uint32_t i = 0; i < p_elements; i++) { |
1267 | const uint16_t *src = (const uint16_t *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1268 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; |
1269 | |
1270 | dst[0] = src[0]; |
1271 | dst[1] = src[1]; |
1272 | dst[2] = src[2]; |
1273 | dst[3] = src[3]; |
1274 | } |
1275 | src_offset += sizeof(uint16_t) * 4; |
1276 | } else { |
1277 | for (uint32_t i = 0; i < p_elements; i++) { |
1278 | const float *src = (const float *)&src_vertex_ptr[i * src_vertex_stride + src_offset]; |
1279 | uint16_t *dst = (uint16_t *)&dst_skin_ptr[i * dst_skin_stride + dst_offsets[Mesh::ARRAY_WEIGHTS]]; |
1280 | |
1281 | dst[0] = uint16_t(CLAMP(src[0] * 65535.0, 0, 65535.0)); |
1282 | dst[1] = uint16_t(CLAMP(src[1] * 65535.0, 0, 65535.0)); |
1283 | dst[2] = uint16_t(CLAMP(src[2] * 65535.0, 0, 65535.0)); |
1284 | dst[3] = uint16_t(CLAMP(src[3] * 65535.0, 0, 65535.0)); |
1285 | } |
1286 | src_offset += sizeof(float) * 4; |
1287 | } |
1288 | } break; |
1289 | default: { |
1290 | } |
1291 | } |
1292 | } |
1293 | } |
1294 | |
1295 | bool ArrayMesh::_set(const StringName &p_name, const Variant &p_value) { |
1296 | String sname = p_name; |
1297 | |
1298 | if (sname.begins_with("surface_" )) { |
1299 | int sl = sname.find("/" ); |
1300 | if (sl == -1) { |
1301 | return false; |
1302 | } |
1303 | int idx = sname.substr(8, sl - 8).to_int(); |
1304 | |
1305 | String what = sname.get_slicec('/', 1); |
1306 | if (what == "material" ) { |
1307 | surface_set_material(idx, p_value); |
1308 | } else if (what == "name" ) { |
1309 | surface_set_name(idx, p_value); |
1310 | } |
1311 | return true; |
1312 | } |
1313 | |
1314 | #ifndef DISABLE_DEPRECATED |
1315 | // Kept for compatibility from 3.x to 4.0. |
1316 | if (!sname.begins_with("surfaces" )) { |
1317 | return false; |
1318 | } |
1319 | |
1320 | WARN_DEPRECATED_MSG(vformat( |
1321 | "Mesh uses old surface format, which is deprecated (and loads slower). Consider re-importing or re-saving the scene. Path: \"%s\"" , |
1322 | get_path())); |
1323 | |
1324 | int idx = sname.get_slicec('/', 1).to_int(); |
1325 | String what = sname.get_slicec('/', 2); |
1326 | |
1327 | if (idx == surfaces.size()) { |
1328 | //create |
1329 | Dictionary d = p_value; |
1330 | ERR_FAIL_COND_V(!d.has("primitive" ), false); |
1331 | |
1332 | if (d.has("arrays" )) { |
1333 | //oldest format (2.x) |
1334 | ERR_FAIL_COND_V(!d.has("morph_arrays" ), false); |
1335 | Array morph_arrays = d["morph_arrays" ]; |
1336 | for (int i = 0; i < morph_arrays.size(); i++) { |
1337 | morph_arrays[i] = _convert_old_array(morph_arrays[i]); |
1338 | } |
1339 | add_surface_from_arrays(_old_primitives[int(d["primitive" ])], _convert_old_array(d["arrays" ]), morph_arrays); |
1340 | |
1341 | } else if (d.has("array_data" )) { |
1342 | //print_line("array data (old style"); |
1343 | //older format (3.x) |
1344 | Vector<uint8_t> array_data = d["array_data" ]; |
1345 | Vector<uint8_t> array_index_data; |
1346 | if (d.has("array_index_data" )) { |
1347 | array_index_data = d["array_index_data" ]; |
1348 | } |
1349 | |
1350 | ERR_FAIL_COND_V(!d.has("format" ), false); |
1351 | uint32_t old_format = d["format" ]; |
1352 | |
1353 | uint32_t primitive = d["primitive" ]; |
1354 | |
1355 | primitive = _old_primitives[primitive]; //compatibility |
1356 | |
1357 | ERR_FAIL_COND_V(!d.has("vertex_count" ), false); |
1358 | int vertex_count = d["vertex_count" ]; |
1359 | |
1360 | uint32_t new_format = ARRAY_FORMAT_VERTEX; |
1361 | |
1362 | if (old_format & OLD_ARRAY_FORMAT_NORMAL) { |
1363 | new_format |= ARRAY_FORMAT_NORMAL; |
1364 | } |
1365 | if (old_format & OLD_ARRAY_FORMAT_TANGENT) { |
1366 | new_format |= ARRAY_FORMAT_TANGENT; |
1367 | } |
1368 | if (old_format & OLD_ARRAY_FORMAT_COLOR) { |
1369 | new_format |= ARRAY_FORMAT_COLOR; |
1370 | } |
1371 | if (old_format & OLD_ARRAY_FORMAT_TEX_UV) { |
1372 | new_format |= ARRAY_FORMAT_TEX_UV; |
1373 | } |
1374 | if (old_format & OLD_ARRAY_FORMAT_TEX_UV2) { |
1375 | new_format |= ARRAY_FORMAT_TEX_UV2; |
1376 | } |
1377 | if (old_format & OLD_ARRAY_FORMAT_BONES) { |
1378 | new_format |= ARRAY_FORMAT_BONES; |
1379 | } |
1380 | if (old_format & OLD_ARRAY_FORMAT_WEIGHTS) { |
1381 | new_format |= ARRAY_FORMAT_WEIGHTS; |
1382 | } |
1383 | if (old_format & OLD_ARRAY_FORMAT_INDEX) { |
1384 | new_format |= ARRAY_FORMAT_INDEX; |
1385 | } |
1386 | if (old_format & OLD_ARRAY_FLAG_USE_2D_VERTICES) { |
1387 | new_format |= OLD_ARRAY_FLAG_USE_2D_VERTICES; |
1388 | } |
1389 | |
1390 | Vector<uint8_t> vertex_array; |
1391 | Vector<uint8_t> attribute_array; |
1392 | Vector<uint8_t> skin_array; |
1393 | |
1394 | _fix_array_compatibility(array_data, old_format, new_format, vertex_count, vertex_array, attribute_array, skin_array); |
1395 | |
1396 | int index_count = 0; |
1397 | if (d.has("index_count" )) { |
1398 | index_count = d["index_count" ]; |
1399 | } |
1400 | |
1401 | Vector<uint8_t> blend_shapes_new; |
1402 | |
1403 | if (d.has("blend_shape_data" )) { |
1404 | Array blend_shape_data = d["blend_shape_data" ]; |
1405 | for (int i = 0; i < blend_shape_data.size(); i++) { |
1406 | Vector<uint8_t> blend_vertex_array; |
1407 | Vector<uint8_t> blend_attribute_array; |
1408 | Vector<uint8_t> blend_skin_array; |
1409 | |
1410 | Vector<uint8_t> shape = blend_shape_data[i]; |
1411 | _fix_array_compatibility(shape, old_format, new_format, vertex_count, blend_vertex_array, blend_attribute_array, blend_skin_array); |
1412 | |
1413 | blend_shapes_new.append_array(blend_vertex_array); |
1414 | } |
1415 | } |
1416 | |
1417 | //clear unused flags |
1418 | print_verbose("Mesh format pre-conversion: " + itos(old_format)); |
1419 | |
1420 | print_verbose("Mesh format post-conversion: " + itos(new_format)); |
1421 | |
1422 | ERR_FAIL_COND_V(!d.has("aabb" ), false); |
1423 | AABB aabb_new = d["aabb" ]; |
1424 | |
1425 | Vector<AABB> bone_aabb; |
1426 | if (d.has("skeleton_aabb" )) { |
1427 | Array baabb = d["skeleton_aabb" ]; |
1428 | bone_aabb.resize(baabb.size()); |
1429 | |
1430 | for (int i = 0; i < baabb.size(); i++) { |
1431 | bone_aabb.write[i] = baabb[i]; |
1432 | } |
1433 | } |
1434 | |
1435 | add_surface(new_format, PrimitiveType(primitive), vertex_array, attribute_array, skin_array, vertex_count, array_index_data, index_count, aabb_new, blend_shapes_new, bone_aabb); |
1436 | |
1437 | } else { |
1438 | ERR_FAIL_V(false); |
1439 | } |
1440 | |
1441 | if (d.has("material" )) { |
1442 | surface_set_material(idx, d["material" ]); |
1443 | } |
1444 | if (d.has("name" )) { |
1445 | surface_set_name(idx, d["name" ]); |
1446 | } |
1447 | |
1448 | return true; |
1449 | } |
1450 | #endif // DISABLE_DEPRECATED |
1451 | |
1452 | return false; |
1453 | } |
1454 | |
1455 | void ArrayMesh::_set_blend_shape_names(const PackedStringArray &p_names) { |
1456 | ERR_FAIL_COND(surfaces.size() > 0); |
1457 | |
1458 | blend_shapes.resize(p_names.size()); |
1459 | for (int i = 0; i < p_names.size(); i++) { |
1460 | blend_shapes.write[i] = p_names[i]; |
1461 | } |
1462 | |
1463 | if (mesh.is_valid()) { |
1464 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); |
1465 | } |
1466 | } |
1467 | |
1468 | PackedStringArray ArrayMesh::_get_blend_shape_names() const { |
1469 | PackedStringArray sarr; |
1470 | sarr.resize(blend_shapes.size()); |
1471 | for (int i = 0; i < blend_shapes.size(); i++) { |
1472 | sarr.write[i] = blend_shapes[i]; |
1473 | } |
1474 | return sarr; |
1475 | } |
1476 | |
1477 | Array ArrayMesh::_get_surfaces() const { |
1478 | if (mesh.is_null()) { |
1479 | return Array(); |
1480 | } |
1481 | |
1482 | Array ret; |
1483 | for (int i = 0; i < surfaces.size(); i++) { |
1484 | RenderingServer::SurfaceData surface = RS::get_singleton()->mesh_get_surface(mesh, i); |
1485 | Dictionary data; |
1486 | data["format" ] = surface.format; |
1487 | data["primitive" ] = surface.primitive; |
1488 | data["vertex_data" ] = surface.vertex_data; |
1489 | data["vertex_count" ] = surface.vertex_count; |
1490 | if (surface.skin_data.size()) { |
1491 | data["skin_data" ] = surface.skin_data; |
1492 | } |
1493 | if (surface.attribute_data.size()) { |
1494 | data["attribute_data" ] = surface.attribute_data; |
1495 | } |
1496 | data["aabb" ] = surface.aabb; |
1497 | if (surface.index_count) { |
1498 | data["index_data" ] = surface.index_data; |
1499 | data["index_count" ] = surface.index_count; |
1500 | }; |
1501 | |
1502 | Array lods; |
1503 | for (int j = 0; j < surface.lods.size(); j++) { |
1504 | lods.push_back(surface.lods[j].edge_length); |
1505 | lods.push_back(surface.lods[j].index_data); |
1506 | } |
1507 | |
1508 | if (lods.size()) { |
1509 | data["lods" ] = lods; |
1510 | } |
1511 | |
1512 | Array bone_aabbs; |
1513 | for (int j = 0; j < surface.bone_aabbs.size(); j++) { |
1514 | bone_aabbs.push_back(surface.bone_aabbs[j]); |
1515 | } |
1516 | if (bone_aabbs.size()) { |
1517 | data["bone_aabbs" ] = bone_aabbs; |
1518 | } |
1519 | |
1520 | if (surface.blend_shape_data.size()) { |
1521 | data["blend_shapes" ] = surface.blend_shape_data; |
1522 | } |
1523 | |
1524 | if (surfaces[i].material.is_valid()) { |
1525 | data["material" ] = surfaces[i].material; |
1526 | } |
1527 | |
1528 | if (!surfaces[i].name.is_empty()) { |
1529 | data["name" ] = surfaces[i].name; |
1530 | } |
1531 | |
1532 | if (surfaces[i].is_2d) { |
1533 | data["2d" ] = true; |
1534 | } |
1535 | |
1536 | ret.push_back(data); |
1537 | } |
1538 | |
1539 | return ret; |
1540 | } |
1541 | |
1542 | void ArrayMesh::_create_if_empty() const { |
1543 | if (!mesh.is_valid()) { |
1544 | mesh = RS::get_singleton()->mesh_create(); |
1545 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); |
1546 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); |
1547 | } |
1548 | } |
1549 | |
1550 | void ArrayMesh::_set_surfaces(const Array &p_surfaces) { |
1551 | Vector<RS::SurfaceData> surface_data; |
1552 | Vector<Ref<Material>> surface_materials; |
1553 | Vector<String> surface_names; |
1554 | Vector<bool> surface_2d; |
1555 | |
1556 | for (int i = 0; i < p_surfaces.size(); i++) { |
1557 | RS::SurfaceData surface; |
1558 | Dictionary d = p_surfaces[i]; |
1559 | ERR_FAIL_COND(!d.has("format" )); |
1560 | ERR_FAIL_COND(!d.has("primitive" )); |
1561 | ERR_FAIL_COND(!d.has("vertex_data" )); |
1562 | ERR_FAIL_COND(!d.has("vertex_count" )); |
1563 | ERR_FAIL_COND(!d.has("aabb" )); |
1564 | surface.format = d["format" ]; |
1565 | surface.primitive = RS::PrimitiveType(int(d["primitive" ])); |
1566 | surface.vertex_data = d["vertex_data" ]; |
1567 | surface.vertex_count = d["vertex_count" ]; |
1568 | if (d.has("attribute_data" )) { |
1569 | surface.attribute_data = d["attribute_data" ]; |
1570 | } |
1571 | if (d.has("skin_data" )) { |
1572 | surface.skin_data = d["skin_data" ]; |
1573 | } |
1574 | surface.aabb = d["aabb" ]; |
1575 | |
1576 | if (d.has("index_data" )) { |
1577 | ERR_FAIL_COND(!d.has("index_count" )); |
1578 | surface.index_data = d["index_data" ]; |
1579 | surface.index_count = d["index_count" ]; |
1580 | } |
1581 | |
1582 | if (d.has("lods" )) { |
1583 | Array lods = d["lods" ]; |
1584 | ERR_FAIL_COND(lods.size() & 1); //must be even |
1585 | for (int j = 0; j < lods.size(); j += 2) { |
1586 | RS::SurfaceData::LOD lod; |
1587 | lod.edge_length = lods[j + 0]; |
1588 | lod.index_data = lods[j + 1]; |
1589 | surface.lods.push_back(lod); |
1590 | } |
1591 | } |
1592 | |
1593 | if (d.has("bone_aabbs" )) { |
1594 | Array bone_aabbs = d["bone_aabbs" ]; |
1595 | for (int j = 0; j < bone_aabbs.size(); j++) { |
1596 | surface.bone_aabbs.push_back(bone_aabbs[j]); |
1597 | } |
1598 | } |
1599 | |
1600 | if (d.has("blend_shapes" )) { |
1601 | surface.blend_shape_data = d["blend_shapes" ]; |
1602 | } |
1603 | |
1604 | Ref<Material> material; |
1605 | if (d.has("material" )) { |
1606 | material = d["material" ]; |
1607 | if (material.is_valid()) { |
1608 | surface.material = material->get_rid(); |
1609 | } |
1610 | } |
1611 | |
1612 | String surf_name; |
1613 | if (d.has("name" )) { |
1614 | surf_name = d["name" ]; |
1615 | } |
1616 | |
1617 | bool _2d = false; |
1618 | if (d.has("2d" )) { |
1619 | _2d = d["2d" ]; |
1620 | } |
1621 | |
1622 | surface_data.push_back(surface); |
1623 | surface_materials.push_back(material); |
1624 | surface_names.push_back(surf_name); |
1625 | surface_2d.push_back(_2d); |
1626 | } |
1627 | |
1628 | if (mesh.is_valid()) { |
1629 | //if mesh exists, it needs to be updated |
1630 | RS::get_singleton()->mesh_clear(mesh); |
1631 | for (int i = 0; i < surface_data.size(); i++) { |
1632 | RS::get_singleton()->mesh_add_surface(mesh, surface_data[i]); |
1633 | } |
1634 | } else { |
1635 | // if mesh does not exist (first time this is loaded, most likely), |
1636 | // we can create it with a single call, which is a lot more efficient and thread friendly |
1637 | mesh = RS::get_singleton()->mesh_create_from_surfaces(surface_data, blend_shapes.size()); |
1638 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); |
1639 | } |
1640 | |
1641 | surfaces.clear(); |
1642 | |
1643 | aabb = AABB(); |
1644 | for (int i = 0; i < surface_data.size(); i++) { |
1645 | Surface s; |
1646 | s.aabb = surface_data[i].aabb; |
1647 | if (i == 0) { |
1648 | aabb = s.aabb; |
1649 | } else { |
1650 | aabb.merge_with(s.aabb); |
1651 | } |
1652 | |
1653 | s.material = surface_materials[i]; |
1654 | s.is_2d = surface_2d[i]; |
1655 | s.name = surface_names[i]; |
1656 | |
1657 | s.format = surface_data[i].format; |
1658 | s.primitive = PrimitiveType(surface_data[i].primitive); |
1659 | s.array_length = surface_data[i].vertex_count; |
1660 | s.index_array_length = surface_data[i].index_count; |
1661 | |
1662 | surfaces.push_back(s); |
1663 | } |
1664 | } |
1665 | |
1666 | bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { |
1667 | if (_is_generated()) { |
1668 | return false; |
1669 | } |
1670 | |
1671 | String sname = p_name; |
1672 | if (sname.begins_with("surface_" )) { |
1673 | int sl = sname.find("/" ); |
1674 | if (sl == -1) { |
1675 | return false; |
1676 | } |
1677 | int idx = sname.substr(8, sl - 8).to_int(); |
1678 | String what = sname.get_slicec('/', 1); |
1679 | if (what == "material" ) { |
1680 | r_ret = surface_get_material(idx); |
1681 | } else if (what == "name" ) { |
1682 | r_ret = surface_get_name(idx); |
1683 | } |
1684 | return true; |
1685 | } |
1686 | |
1687 | return true; |
1688 | } |
1689 | |
1690 | void ArrayMesh::reset_state() { |
1691 | clear_surfaces(); |
1692 | clear_blend_shapes(); |
1693 | |
1694 | aabb = AABB(); |
1695 | blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; |
1696 | custom_aabb = AABB(); |
1697 | } |
1698 | |
1699 | void ArrayMesh::_get_property_list(List<PropertyInfo> *p_list) const { |
1700 | if (_is_generated()) { |
1701 | return; |
1702 | } |
1703 | |
1704 | for (int i = 0; i < surfaces.size(); i++) { |
1705 | p_list->push_back(PropertyInfo(Variant::STRING, "surface_" + itos(i) + "/name" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_EDITOR)); |
1706 | if (surfaces[i].is_2d) { |
1707 | p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i) + "/material" , PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial,ShaderMaterial" , PROPERTY_USAGE_EDITOR)); |
1708 | } else { |
1709 | p_list->push_back(PropertyInfo(Variant::OBJECT, "surface_" + itos(i) + "/material" , PROPERTY_HINT_RESOURCE_TYPE, "BaseMaterial3D,ShaderMaterial" , PROPERTY_USAGE_EDITOR)); |
1710 | } |
1711 | } |
1712 | } |
1713 | |
1714 | void ArrayMesh::_recompute_aabb() { |
1715 | // regenerate AABB |
1716 | aabb = AABB(); |
1717 | |
1718 | for (int i = 0; i < surfaces.size(); i++) { |
1719 | if (i == 0) { |
1720 | aabb = surfaces[i].aabb; |
1721 | } else { |
1722 | aabb.merge_with(surfaces[i].aabb); |
1723 | } |
1724 | } |
1725 | } |
1726 | |
1727 | // TODO: Need to add binding to add_surface using future MeshSurfaceData object. |
1728 | void ArrayMesh::add_surface(BitField<ArrayFormat> p_format, PrimitiveType p_primitive, const Vector<uint8_t> &p_array, const Vector<uint8_t> &p_attribute_array, const Vector<uint8_t> &p_skin_array, int p_vertex_count, const Vector<uint8_t> &p_index_array, int p_index_count, const AABB &p_aabb, const Vector<uint8_t> &p_blend_shape_data, const Vector<AABB> &p_bone_aabbs, const Vector<RS::SurfaceData::LOD> &p_lods) { |
1729 | ERR_FAIL_COND(surfaces.size() == RS::MAX_MESH_SURFACES); |
1730 | _create_if_empty(); |
1731 | |
1732 | Surface s; |
1733 | s.aabb = p_aabb; |
1734 | s.is_2d = p_format & ARRAY_FLAG_USE_2D_VERTICES; |
1735 | s.primitive = p_primitive; |
1736 | s.array_length = p_vertex_count; |
1737 | s.index_array_length = p_index_count; |
1738 | s.format = p_format; |
1739 | |
1740 | surfaces.push_back(s); |
1741 | _recompute_aabb(); |
1742 | |
1743 | RS::SurfaceData sd; |
1744 | sd.format = p_format; |
1745 | sd.primitive = RS::PrimitiveType(p_primitive); |
1746 | sd.aabb = p_aabb; |
1747 | sd.vertex_count = p_vertex_count; |
1748 | sd.vertex_data = p_array; |
1749 | sd.attribute_data = p_attribute_array; |
1750 | sd.skin_data = p_skin_array; |
1751 | sd.index_count = p_index_count; |
1752 | sd.index_data = p_index_array; |
1753 | sd.blend_shape_data = p_blend_shape_data; |
1754 | sd.bone_aabbs = p_bone_aabbs; |
1755 | sd.lods = p_lods; |
1756 | |
1757 | RenderingServer::get_singleton()->mesh_add_surface(mesh, sd); |
1758 | |
1759 | clear_cache(); |
1760 | notify_property_list_changed(); |
1761 | emit_changed(); |
1762 | } |
1763 | |
1764 | void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const TypedArray<Array> &p_blend_shapes, const Dictionary &p_lods, BitField<ArrayFormat> p_flags) { |
1765 | ERR_FAIL_COND(p_blend_shapes.size() != blend_shapes.size()); |
1766 | ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); |
1767 | |
1768 | RS::SurfaceData surface; |
1769 | |
1770 | Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (RenderingServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags); |
1771 | ERR_FAIL_COND(err != OK); |
1772 | |
1773 | /* Debug code. |
1774 | print_line("format: " + itos(surface.format)); |
1775 | print_line("aabb: " + surface.aabb); |
1776 | print_line("array size: " + itos(surface.vertex_data.size())); |
1777 | print_line("vertex count: " + itos(surface.vertex_count)); |
1778 | print_line("index size: " + itos(surface.index_data.size())); |
1779 | print_line("index count: " + itos(surface.index_count)); |
1780 | print_line("primitive: " + itos(surface.primitive)); |
1781 | */ |
1782 | |
1783 | add_surface(surface.format, PrimitiveType(surface.primitive), surface.vertex_data, surface.attribute_data, surface.skin_data, surface.vertex_count, surface.index_data, surface.index_count, surface.aabb, surface.blend_shape_data, surface.bone_aabbs, surface.lods); |
1784 | } |
1785 | |
1786 | Array ArrayMesh::surface_get_arrays(int p_surface) const { |
1787 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); |
1788 | return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); |
1789 | } |
1790 | |
1791 | TypedArray<Array> ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { |
1792 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), TypedArray<Array>()); |
1793 | return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); |
1794 | } |
1795 | |
1796 | Dictionary ArrayMesh::surface_get_lods(int p_surface) const { |
1797 | ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary()); |
1798 | return RenderingServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); |
1799 | } |
1800 | |
1801 | int ArrayMesh::get_surface_count() const { |
1802 | return surfaces.size(); |
1803 | } |
1804 | |
1805 | void ArrayMesh::add_blend_shape(const StringName &p_name) { |
1806 | ERR_FAIL_COND_MSG(surfaces.size(), "Can't add a shape key count if surfaces are already created." ); |
1807 | |
1808 | StringName shape_name = p_name; |
1809 | |
1810 | if (blend_shapes.has(shape_name)) { |
1811 | int count = 2; |
1812 | do { |
1813 | shape_name = String(p_name) + " " + itos(count); |
1814 | count++; |
1815 | } while (blend_shapes.has(shape_name)); |
1816 | } |
1817 | |
1818 | blend_shapes.push_back(shape_name); |
1819 | |
1820 | if (mesh.is_valid()) { |
1821 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); |
1822 | } |
1823 | } |
1824 | |
1825 | int ArrayMesh::get_blend_shape_count() const { |
1826 | return blend_shapes.size(); |
1827 | } |
1828 | |
1829 | StringName ArrayMesh::get_blend_shape_name(int p_index) const { |
1830 | ERR_FAIL_INDEX_V(p_index, blend_shapes.size(), StringName()); |
1831 | return blend_shapes[p_index]; |
1832 | } |
1833 | |
1834 | void ArrayMesh::set_blend_shape_name(int p_index, const StringName &p_name) { |
1835 | ERR_FAIL_INDEX(p_index, blend_shapes.size()); |
1836 | |
1837 | StringName shape_name = p_name; |
1838 | int found = blend_shapes.find(shape_name); |
1839 | if (found != -1 && found != p_index) { |
1840 | int count = 2; |
1841 | do { |
1842 | shape_name = String(p_name) + " " + itos(count); |
1843 | count++; |
1844 | } while (blend_shapes.find(shape_name) != -1); |
1845 | } |
1846 | |
1847 | blend_shapes.write[p_index] = shape_name; |
1848 | } |
1849 | |
1850 | void ArrayMesh::clear_blend_shapes() { |
1851 | ERR_FAIL_COND_MSG(surfaces.size(), "Can't set shape key count if surfaces are already created." ); |
1852 | |
1853 | blend_shapes.clear(); |
1854 | |
1855 | if (mesh.is_valid()) { |
1856 | RS::get_singleton()->mesh_set_blend_shape_count(mesh, 0); |
1857 | } |
1858 | } |
1859 | |
1860 | void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { |
1861 | blend_shape_mode = p_mode; |
1862 | if (mesh.is_valid()) { |
1863 | RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)p_mode); |
1864 | } |
1865 | } |
1866 | |
1867 | ArrayMesh::BlendShapeMode ArrayMesh::get_blend_shape_mode() const { |
1868 | return blend_shape_mode; |
1869 | } |
1870 | |
1871 | int ArrayMesh::surface_get_array_len(int p_idx) const { |
1872 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); |
1873 | return surfaces[p_idx].array_length; |
1874 | } |
1875 | |
1876 | int ArrayMesh::surface_get_array_index_len(int p_idx) const { |
1877 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), -1); |
1878 | return surfaces[p_idx].index_array_length; |
1879 | } |
1880 | |
1881 | BitField<Mesh::ArrayFormat> ArrayMesh::surface_get_format(int p_idx) const { |
1882 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), 0); |
1883 | return surfaces[p_idx].format; |
1884 | } |
1885 | |
1886 | ArrayMesh::PrimitiveType ArrayMesh::surface_get_primitive_type(int p_idx) const { |
1887 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), PRIMITIVE_LINES); |
1888 | return surfaces[p_idx].primitive; |
1889 | } |
1890 | |
1891 | void ArrayMesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { |
1892 | ERR_FAIL_INDEX(p_idx, surfaces.size()); |
1893 | if (surfaces[p_idx].material == p_material) { |
1894 | return; |
1895 | } |
1896 | surfaces.write[p_idx].material = p_material; |
1897 | RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); |
1898 | |
1899 | emit_changed(); |
1900 | } |
1901 | |
1902 | int ArrayMesh::surface_find_by_name(const String &p_name) const { |
1903 | for (int i = 0; i < surfaces.size(); i++) { |
1904 | if (surfaces[i].name == p_name) { |
1905 | return i; |
1906 | } |
1907 | } |
1908 | return -1; |
1909 | } |
1910 | |
1911 | void ArrayMesh::surface_set_name(int p_idx, const String &p_name) { |
1912 | ERR_FAIL_INDEX(p_idx, surfaces.size()); |
1913 | |
1914 | surfaces.write[p_idx].name = p_name; |
1915 | emit_changed(); |
1916 | } |
1917 | |
1918 | String ArrayMesh::surface_get_name(int p_idx) const { |
1919 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), String()); |
1920 | return surfaces[p_idx].name; |
1921 | } |
1922 | |
1923 | void ArrayMesh::surface_update_vertex_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { |
1924 | ERR_FAIL_INDEX(p_surface, surfaces.size()); |
1925 | RS::get_singleton()->mesh_surface_update_vertex_region(mesh, p_surface, p_offset, p_data); |
1926 | emit_changed(); |
1927 | } |
1928 | |
1929 | void ArrayMesh::surface_update_attribute_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { |
1930 | ERR_FAIL_INDEX(p_surface, surfaces.size()); |
1931 | RS::get_singleton()->mesh_surface_update_attribute_region(mesh, p_surface, p_offset, p_data); |
1932 | emit_changed(); |
1933 | } |
1934 | |
1935 | void ArrayMesh::surface_update_skin_region(int p_surface, int p_offset, const Vector<uint8_t> &p_data) { |
1936 | ERR_FAIL_INDEX(p_surface, surfaces.size()); |
1937 | RS::get_singleton()->mesh_surface_update_skin_region(mesh, p_surface, p_offset, p_data); |
1938 | emit_changed(); |
1939 | } |
1940 | |
1941 | void ArrayMesh::surface_set_custom_aabb(int p_idx, const AABB &p_aabb) { |
1942 | ERR_FAIL_INDEX(p_idx, surfaces.size()); |
1943 | surfaces.write[p_idx].aabb = p_aabb; |
1944 | // set custom aabb too? |
1945 | emit_changed(); |
1946 | } |
1947 | |
1948 | Ref<Material> ArrayMesh::surface_get_material(int p_idx) const { |
1949 | ERR_FAIL_INDEX_V(p_idx, surfaces.size(), Ref<Material>()); |
1950 | return surfaces[p_idx].material; |
1951 | } |
1952 | |
1953 | RID ArrayMesh::get_rid() const { |
1954 | _create_if_empty(); |
1955 | return mesh; |
1956 | } |
1957 | |
1958 | AABB ArrayMesh::get_aabb() const { |
1959 | return aabb; |
1960 | } |
1961 | |
1962 | void ArrayMesh::clear_surfaces() { |
1963 | if (!mesh.is_valid()) { |
1964 | return; |
1965 | } |
1966 | RS::get_singleton()->mesh_clear(mesh); |
1967 | surfaces.clear(); |
1968 | aabb = AABB(); |
1969 | } |
1970 | |
1971 | void ArrayMesh::set_custom_aabb(const AABB &p_custom) { |
1972 | _create_if_empty(); |
1973 | custom_aabb = p_custom; |
1974 | RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); |
1975 | emit_changed(); |
1976 | } |
1977 | |
1978 | AABB ArrayMesh::get_custom_aabb() const { |
1979 | return custom_aabb; |
1980 | } |
1981 | |
1982 | void ArrayMesh::regen_normal_maps() { |
1983 | if (surfaces.size() == 0) { |
1984 | return; |
1985 | } |
1986 | Vector<Ref<SurfaceTool>> surfs; |
1987 | for (int i = 0; i < get_surface_count(); i++) { |
1988 | Ref<SurfaceTool> st = memnew(SurfaceTool); |
1989 | st->create_from(Ref<ArrayMesh>(this), i); |
1990 | surfs.push_back(st); |
1991 | } |
1992 | |
1993 | clear_surfaces(); |
1994 | |
1995 | for (int i = 0; i < surfs.size(); i++) { |
1996 | surfs.write[i]->generate_tangents(); |
1997 | surfs.write[i]->commit(Ref<ArrayMesh>(this)); |
1998 | } |
1999 | } |
2000 | |
2001 | //dirty hack |
2002 | bool (*array_mesh_lightmap_unwrap_callback)(float p_texel_size, const float *p_vertices, const float *p_normals, int p_vertex_count, const int *p_indices, int p_index_count, const uint8_t *p_cache_data, bool *r_use_cache, uint8_t **r_mesh_cache, int *r_mesh_cache_size, float **r_uv, int **r_vertex, int *r_vertex_count, int **r_index, int *r_index_count, int *r_size_hint_x, int *r_size_hint_y) = nullptr; |
2003 | |
2004 | struct ArrayMeshLightmapSurface { |
2005 | Ref<Material> material; |
2006 | LocalVector<SurfaceTool::Vertex> vertices; |
2007 | Mesh::PrimitiveType primitive = Mesh::PrimitiveType::PRIMITIVE_MAX; |
2008 | uint32_t format = 0; |
2009 | }; |
2010 | |
2011 | Error ArrayMesh::lightmap_unwrap(const Transform3D &p_base_transform, float p_texel_size) { |
2012 | Vector<uint8_t> null_cache; |
2013 | return lightmap_unwrap_cached(p_base_transform, p_texel_size, null_cache, null_cache, false); |
2014 | } |
2015 | |
2016 | Error ArrayMesh::lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache, bool p_generate_cache) { |
2017 | ERR_FAIL_NULL_V(array_mesh_lightmap_unwrap_callback, ERR_UNCONFIGURED); |
2018 | ERR_FAIL_COND_V_MSG(blend_shapes.size() != 0, ERR_UNAVAILABLE, "Can't unwrap mesh with blend shapes." ); |
2019 | ERR_FAIL_COND_V_MSG(p_texel_size <= 0.0f, ERR_PARAMETER_RANGE_ERROR, "Texel size must be greater than 0." ); |
2020 | |
2021 | LocalVector<float> vertices; |
2022 | LocalVector<float> normals; |
2023 | LocalVector<int> indices; |
2024 | LocalVector<float> uv; |
2025 | LocalVector<Pair<int, int>> uv_indices; |
2026 | |
2027 | Vector<ArrayMeshLightmapSurface> lightmap_surfaces; |
2028 | |
2029 | // Keep only the scale |
2030 | Basis basis = p_base_transform.get_basis(); |
2031 | Vector3 scale = Vector3(basis.get_column(0).length(), basis.get_column(1).length(), basis.get_column(2).length()); |
2032 | |
2033 | Transform3D transform; |
2034 | transform.scale(scale); |
2035 | |
2036 | Basis normal_basis = transform.basis.inverse().transposed(); |
2037 | |
2038 | for (int i = 0; i < get_surface_count(); i++) { |
2039 | ArrayMeshLightmapSurface s; |
2040 | s.primitive = surface_get_primitive_type(i); |
2041 | |
2042 | ERR_FAIL_COND_V_MSG(s.primitive != Mesh::PRIMITIVE_TRIANGLES, ERR_UNAVAILABLE, "Only triangles are supported for lightmap unwrap." ); |
2043 | s.format = surface_get_format(i); |
2044 | ERR_FAIL_COND_V_MSG(!(s.format & ARRAY_FORMAT_NORMAL), ERR_UNAVAILABLE, "Normals are required for lightmap unwrap." ); |
2045 | |
2046 | Array arrays = surface_get_arrays(i); |
2047 | s.material = surface_get_material(i); |
2048 | SurfaceTool::create_vertex_array_from_triangle_arrays(arrays, s.vertices, &s.format); |
2049 | |
2050 | PackedVector3Array rvertices = arrays[Mesh::ARRAY_VERTEX]; |
2051 | int vc = rvertices.size(); |
2052 | |
2053 | PackedVector3Array rnormals = arrays[Mesh::ARRAY_NORMAL]; |
2054 | |
2055 | int vertex_ofs = vertices.size() / 3; |
2056 | |
2057 | vertices.resize((vertex_ofs + vc) * 3); |
2058 | normals.resize((vertex_ofs + vc) * 3); |
2059 | uv_indices.resize(vertex_ofs + vc); |
2060 | |
2061 | for (int j = 0; j < vc; j++) { |
2062 | Vector3 v = transform.xform(rvertices[j]); |
2063 | Vector3 n = normal_basis.xform(rnormals[j]).normalized(); |
2064 | |
2065 | vertices[(j + vertex_ofs) * 3 + 0] = v.x; |
2066 | vertices[(j + vertex_ofs) * 3 + 1] = v.y; |
2067 | vertices[(j + vertex_ofs) * 3 + 2] = v.z; |
2068 | normals[(j + vertex_ofs) * 3 + 0] = n.x; |
2069 | normals[(j + vertex_ofs) * 3 + 1] = n.y; |
2070 | normals[(j + vertex_ofs) * 3 + 2] = n.z; |
2071 | uv_indices[j + vertex_ofs] = Pair<int, int>(i, j); |
2072 | } |
2073 | |
2074 | PackedInt32Array rindices = arrays[Mesh::ARRAY_INDEX]; |
2075 | int ic = rindices.size(); |
2076 | |
2077 | float eps = 1.19209290e-7F; // Taken from xatlas.h |
2078 | if (ic == 0) { |
2079 | for (int j = 0; j < vc / 3; j++) { |
2080 | Vector3 p0 = transform.xform(rvertices[j * 3 + 0]); |
2081 | Vector3 p1 = transform.xform(rvertices[j * 3 + 1]); |
2082 | Vector3 p2 = transform.xform(rvertices[j * 3 + 2]); |
2083 | |
2084 | if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { |
2085 | continue; |
2086 | } |
2087 | |
2088 | indices.push_back(vertex_ofs + j * 3 + 0); |
2089 | indices.push_back(vertex_ofs + j * 3 + 1); |
2090 | indices.push_back(vertex_ofs + j * 3 + 2); |
2091 | } |
2092 | |
2093 | } else { |
2094 | for (int j = 0; j < ic / 3; j++) { |
2095 | Vector3 p0 = transform.xform(rvertices[rindices[j * 3 + 0]]); |
2096 | Vector3 p1 = transform.xform(rvertices[rindices[j * 3 + 1]]); |
2097 | Vector3 p2 = transform.xform(rvertices[rindices[j * 3 + 2]]); |
2098 | |
2099 | if ((p0 - p1).length_squared() < eps || (p1 - p2).length_squared() < eps || (p2 - p0).length_squared() < eps) { |
2100 | continue; |
2101 | } |
2102 | |
2103 | indices.push_back(vertex_ofs + rindices[j * 3 + 0]); |
2104 | indices.push_back(vertex_ofs + rindices[j * 3 + 1]); |
2105 | indices.push_back(vertex_ofs + rindices[j * 3 + 2]); |
2106 | } |
2107 | } |
2108 | |
2109 | lightmap_surfaces.push_back(s); |
2110 | } |
2111 | |
2112 | //unwrap |
2113 | |
2114 | bool use_cache = p_generate_cache; // Used to request cache generation and to know if cache was used |
2115 | uint8_t *gen_cache; |
2116 | int gen_cache_size; |
2117 | float *gen_uvs; |
2118 | int *gen_vertices; |
2119 | int *gen_indices; |
2120 | int gen_vertex_count; |
2121 | int gen_index_count; |
2122 | int size_x; |
2123 | int size_y; |
2124 | |
2125 | bool ok = array_mesh_lightmap_unwrap_callback(p_texel_size, vertices.ptr(), normals.ptr(), vertices.size() / 3, indices.ptr(), indices.size(), p_src_cache.ptr(), &use_cache, &gen_cache, &gen_cache_size, &gen_uvs, &gen_vertices, &gen_vertex_count, &gen_indices, &gen_index_count, &size_x, &size_y); |
2126 | |
2127 | if (!ok) { |
2128 | return ERR_CANT_CREATE; |
2129 | } |
2130 | |
2131 | clear_surfaces(); |
2132 | |
2133 | //create surfacetools for each surface.. |
2134 | LocalVector<Ref<SurfaceTool>> surfaces_tools; |
2135 | |
2136 | for (int i = 0; i < lightmap_surfaces.size(); i++) { |
2137 | Ref<SurfaceTool> st; |
2138 | st.instantiate(); |
2139 | st->begin(Mesh::PRIMITIVE_TRIANGLES); |
2140 | st->set_material(lightmap_surfaces[i].material); |
2141 | surfaces_tools.push_back(st); //stay there |
2142 | } |
2143 | |
2144 | print_verbose("Mesh: Gen indices: " + itos(gen_index_count)); |
2145 | |
2146 | //go through all indices |
2147 | for (int i = 0; i < gen_index_count; i += 3) { |
2148 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 0]], (int)uv_indices.size(), ERR_BUG); |
2149 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 1]], (int)uv_indices.size(), ERR_BUG); |
2150 | ERR_FAIL_INDEX_V(gen_vertices[gen_indices[i + 2]], (int)uv_indices.size(), ERR_BUG); |
2151 | |
2152 | ERR_FAIL_COND_V(uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 1]]].first || uv_indices[gen_vertices[gen_indices[i + 0]]].first != uv_indices[gen_vertices[gen_indices[i + 2]]].first, ERR_BUG); |
2153 | |
2154 | int surface = uv_indices[gen_vertices[gen_indices[i + 0]]].first; |
2155 | |
2156 | for (int j = 0; j < 3; j++) { |
2157 | SurfaceTool::Vertex v = lightmap_surfaces[surface].vertices[uv_indices[gen_vertices[gen_indices[i + j]]].second]; |
2158 | |
2159 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_COLOR) { |
2160 | surfaces_tools[surface]->set_color(v.color); |
2161 | } |
2162 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TEX_UV) { |
2163 | surfaces_tools[surface]->set_uv(v.uv); |
2164 | } |
2165 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_NORMAL) { |
2166 | surfaces_tools[surface]->set_normal(v.normal); |
2167 | } |
2168 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_TANGENT) { |
2169 | Plane t; |
2170 | t.normal = v.tangent; |
2171 | t.d = v.binormal.dot(v.normal.cross(v.tangent)) < 0 ? -1 : 1; |
2172 | surfaces_tools[surface]->set_tangent(t); |
2173 | } |
2174 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_BONES) { |
2175 | surfaces_tools[surface]->set_bones(v.bones); |
2176 | } |
2177 | if (lightmap_surfaces[surface].format & ARRAY_FORMAT_WEIGHTS) { |
2178 | surfaces_tools[surface]->set_weights(v.weights); |
2179 | } |
2180 | |
2181 | Vector2 uv2(gen_uvs[gen_indices[i + j] * 2 + 0], gen_uvs[gen_indices[i + j] * 2 + 1]); |
2182 | surfaces_tools[surface]->set_uv2(uv2); |
2183 | |
2184 | surfaces_tools[surface]->add_vertex(v.vertex); |
2185 | } |
2186 | } |
2187 | |
2188 | //generate surfaces |
2189 | for (unsigned int i = 0; i < surfaces_tools.size(); i++) { |
2190 | surfaces_tools[i]->index(); |
2191 | surfaces_tools[i]->commit(Ref<ArrayMesh>((ArrayMesh *)this), lightmap_surfaces[i].format); |
2192 | } |
2193 | |
2194 | set_lightmap_size_hint(Size2(size_x, size_y)); |
2195 | |
2196 | if (gen_cache_size > 0) { |
2197 | r_dst_cache.resize(gen_cache_size); |
2198 | memcpy(r_dst_cache.ptrw(), gen_cache, gen_cache_size); |
2199 | memfree(gen_cache); |
2200 | } |
2201 | |
2202 | if (!use_cache) { |
2203 | // Cache was not used, free the buffers |
2204 | memfree(gen_vertices); |
2205 | memfree(gen_indices); |
2206 | memfree(gen_uvs); |
2207 | } |
2208 | |
2209 | return OK; |
2210 | } |
2211 | |
2212 | void ArrayMesh::set_shadow_mesh(const Ref<ArrayMesh> &p_mesh) { |
2213 | shadow_mesh = p_mesh; |
2214 | if (shadow_mesh.is_valid()) { |
2215 | RS::get_singleton()->mesh_set_shadow_mesh(mesh, shadow_mesh->get_rid()); |
2216 | } else { |
2217 | RS::get_singleton()->mesh_set_shadow_mesh(mesh, RID()); |
2218 | } |
2219 | } |
2220 | |
2221 | Ref<ArrayMesh> ArrayMesh::get_shadow_mesh() const { |
2222 | return shadow_mesh; |
2223 | } |
2224 | |
2225 | void ArrayMesh::_bind_methods() { |
2226 | ClassDB::bind_method(D_METHOD("add_blend_shape" , "name" ), &ArrayMesh::add_blend_shape); |
2227 | ClassDB::bind_method(D_METHOD("get_blend_shape_count" ), &ArrayMesh::get_blend_shape_count); |
2228 | ClassDB::bind_method(D_METHOD("get_blend_shape_name" , "index" ), &ArrayMesh::get_blend_shape_name); |
2229 | ClassDB::bind_method(D_METHOD("set_blend_shape_name" , "index" , "name" ), &ArrayMesh::set_blend_shape_name); |
2230 | ClassDB::bind_method(D_METHOD("clear_blend_shapes" ), &ArrayMesh::clear_blend_shapes); |
2231 | ClassDB::bind_method(D_METHOD("set_blend_shape_mode" , "mode" ), &ArrayMesh::set_blend_shape_mode); |
2232 | ClassDB::bind_method(D_METHOD("get_blend_shape_mode" ), &ArrayMesh::get_blend_shape_mode); |
2233 | |
2234 | ClassDB::bind_method(D_METHOD("add_surface_from_arrays" , "primitive" , "arrays" , "blend_shapes" , "lods" , "flags" ), &ArrayMesh::add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(0)); |
2235 | ClassDB::bind_method(D_METHOD("clear_surfaces" ), &ArrayMesh::clear_surfaces); |
2236 | ClassDB::bind_method(D_METHOD("surface_update_vertex_region" , "surf_idx" , "offset" , "data" ), &ArrayMesh::surface_update_vertex_region); |
2237 | ClassDB::bind_method(D_METHOD("surface_update_attribute_region" , "surf_idx" , "offset" , "data" ), &ArrayMesh::surface_update_attribute_region); |
2238 | ClassDB::bind_method(D_METHOD("surface_update_skin_region" , "surf_idx" , "offset" , "data" ), &ArrayMesh::surface_update_skin_region); |
2239 | ClassDB::bind_method(D_METHOD("surface_get_array_len" , "surf_idx" ), &ArrayMesh::surface_get_array_len); |
2240 | ClassDB::bind_method(D_METHOD("surface_get_array_index_len" , "surf_idx" ), &ArrayMesh::surface_get_array_index_len); |
2241 | ClassDB::bind_method(D_METHOD("surface_get_format" , "surf_idx" ), &ArrayMesh::surface_get_format); |
2242 | ClassDB::bind_method(D_METHOD("surface_get_primitive_type" , "surf_idx" ), &ArrayMesh::surface_get_primitive_type); |
2243 | ClassDB::bind_method(D_METHOD("surface_find_by_name" , "name" ), &ArrayMesh::surface_find_by_name); |
2244 | ClassDB::bind_method(D_METHOD("surface_set_name" , "surf_idx" , "name" ), &ArrayMesh::surface_set_name); |
2245 | ClassDB::bind_method(D_METHOD("surface_get_name" , "surf_idx" ), &ArrayMesh::surface_get_name); |
2246 | ClassDB::bind_method(D_METHOD("create_trimesh_shape" ), &ArrayMesh::create_trimesh_shape); |
2247 | ClassDB::bind_method(D_METHOD("create_convex_shape" , "clean" , "simplify" ), &ArrayMesh::create_convex_shape, DEFVAL(true), DEFVAL(false)); |
2248 | ClassDB::bind_method(D_METHOD("create_outline" , "margin" ), &ArrayMesh::create_outline); |
2249 | ClassDB::bind_method(D_METHOD("regen_normal_maps" ), &ArrayMesh::regen_normal_maps); |
2250 | ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normal_maps" ), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); |
2251 | ClassDB::bind_method(D_METHOD("lightmap_unwrap" , "transform" , "texel_size" ), &ArrayMesh::lightmap_unwrap); |
2252 | ClassDB::set_method_flags(get_class_static(), _scs_create("lightmap_unwrap" ), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); |
2253 | ClassDB::bind_method(D_METHOD("generate_triangle_mesh" ), &ArrayMesh::generate_triangle_mesh); |
2254 | |
2255 | ClassDB::bind_method(D_METHOD("set_custom_aabb" , "aabb" ), &ArrayMesh::set_custom_aabb); |
2256 | ClassDB::bind_method(D_METHOD("get_custom_aabb" ), &ArrayMesh::get_custom_aabb); |
2257 | |
2258 | ClassDB::bind_method(D_METHOD("set_shadow_mesh" , "mesh" ), &ArrayMesh::set_shadow_mesh); |
2259 | ClassDB::bind_method(D_METHOD("get_shadow_mesh" ), &ArrayMesh::get_shadow_mesh); |
2260 | |
2261 | ClassDB::bind_method(D_METHOD("_set_blend_shape_names" , "blend_shape_names" ), &ArrayMesh::_set_blend_shape_names); |
2262 | ClassDB::bind_method(D_METHOD("_get_blend_shape_names" ), &ArrayMesh::_get_blend_shape_names); |
2263 | |
2264 | ClassDB::bind_method(D_METHOD("_set_surfaces" , "surfaces" ), &ArrayMesh::_set_surfaces); |
2265 | ClassDB::bind_method(D_METHOD("_get_surfaces" ), &ArrayMesh::_get_surfaces); |
2266 | |
2267 | ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "_blend_shape_names" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_blend_shape_names" , "_get_blend_shape_names" ); |
2268 | ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_surfaces" , PROPERTY_HINT_NONE, "" , PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_surfaces" , "_get_surfaces" ); |
2269 | ADD_PROPERTY(PropertyInfo(Variant::INT, "blend_shape_mode" , PROPERTY_HINT_ENUM, "Normalized,Relative" ), "set_blend_shape_mode" , "get_blend_shape_mode" ); |
2270 | ADD_PROPERTY(PropertyInfo(Variant::AABB, "custom_aabb" , PROPERTY_HINT_NONE, "suffix:m" ), "set_custom_aabb" , "get_custom_aabb" ); |
2271 | ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shadow_mesh" , PROPERTY_HINT_RESOURCE_TYPE, "ArrayMesh" ), "set_shadow_mesh" , "get_shadow_mesh" ); |
2272 | } |
2273 | |
2274 | void ArrayMesh::reload_from_file() { |
2275 | RenderingServer::get_singleton()->mesh_clear(mesh); |
2276 | surfaces.clear(); |
2277 | clear_blend_shapes(); |
2278 | clear_cache(); |
2279 | |
2280 | Resource::reload_from_file(); |
2281 | |
2282 | notify_property_list_changed(); |
2283 | } |
2284 | |
2285 | ArrayMesh::ArrayMesh() { |
2286 | //mesh is now created on demand |
2287 | //mesh = RenderingServer::get_singleton()->mesh_create(); |
2288 | } |
2289 | |
2290 | ArrayMesh::~ArrayMesh() { |
2291 | if (mesh.is_valid()) { |
2292 | ERR_FAIL_NULL(RenderingServer::get_singleton()); |
2293 | RenderingServer::get_singleton()->free(mesh); |
2294 | } |
2295 | } |
2296 | /////////////// |
2297 | |
2298 | void PlaceholderMesh::_bind_methods() { |
2299 | ClassDB::bind_method(D_METHOD("set_aabb" , "aabb" ), &PlaceholderMesh::set_aabb); |
2300 | ADD_PROPERTY(PropertyInfo(Variant::AABB, "aabb" , PROPERTY_HINT_NONE, "suffix:m" ), "set_aabb" , "get_aabb" ); |
2301 | } |
2302 | |
2303 | PlaceholderMesh::PlaceholderMesh() { |
2304 | rid = RS::get_singleton()->mesh_create(); |
2305 | } |
2306 | |
2307 | PlaceholderMesh::~PlaceholderMesh() { |
2308 | ERR_FAIL_NULL(RenderingServer::get_singleton()); |
2309 | RS::get_singleton()->free(rid); |
2310 | } |
2311 | |