1/**************************************************************************/
2/* surface_tool.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 "surface_tool.h"
32
33#define EQ_VERTEX_DIST 0.00001
34
35SurfaceTool::OptimizeVertexCacheFunc SurfaceTool::optimize_vertex_cache_func = nullptr;
36SurfaceTool::SimplifyFunc SurfaceTool::simplify_func = nullptr;
37SurfaceTool::SimplifyWithAttribFunc SurfaceTool::simplify_with_attrib_func = nullptr;
38SurfaceTool::SimplifyScaleFunc SurfaceTool::simplify_scale_func = nullptr;
39SurfaceTool::SimplifySloppyFunc SurfaceTool::simplify_sloppy_func = nullptr;
40SurfaceTool::GenerateRemapFunc SurfaceTool::generate_remap_func = nullptr;
41SurfaceTool::RemapVertexFunc SurfaceTool::remap_vertex_func = nullptr;
42SurfaceTool::RemapIndexFunc SurfaceTool::remap_index_func = nullptr;
43
44void SurfaceTool::strip_mesh_arrays(PackedVector3Array &r_vertices, PackedInt32Array &r_indices) {
45 ERR_FAIL_COND_MSG(!generate_remap_func || !remap_vertex_func || !remap_index_func, "Meshoptimizer library is not initialized.");
46
47 Vector<uint32_t> remap;
48 remap.resize(r_vertices.size());
49 uint32_t new_vertex_count = generate_remap_func(remap.ptrw(), (unsigned int *)r_indices.ptr(), r_indices.size(), r_vertices.ptr(), r_vertices.size(), sizeof(Vector3));
50 remap_vertex_func(r_vertices.ptrw(), r_vertices.ptr(), r_vertices.size(), sizeof(Vector3), remap.ptr());
51 r_vertices.resize(new_vertex_count);
52 remap_index_func((unsigned int *)r_indices.ptrw(), (unsigned int *)r_indices.ptr(), r_indices.size(), remap.ptr());
53
54 HashMap<const int *, bool, TriangleHasher, TriangleHasher> found_triangles;
55 int *idx_ptr = r_indices.ptrw();
56
57 int filtered_indices_count = 0;
58 for (int i = 0; i < r_indices.size() / 3; i++) {
59 const int *tri = idx_ptr + (i * 3);
60
61 if (tri[0] == tri[1] || tri[1] == tri[2] || tri[2] == tri[0]) {
62 continue;
63 }
64
65 if (found_triangles.has(tri)) {
66 continue;
67 }
68
69 if (i != filtered_indices_count) {
70 memcpy(idx_ptr + (filtered_indices_count * 3), tri, sizeof(int) * 3);
71 }
72
73 found_triangles[tri] = true;
74 filtered_indices_count++;
75 }
76 r_indices.resize(filtered_indices_count * 3);
77}
78
79bool SurfaceTool::Vertex::operator==(const Vertex &p_vertex) const {
80 if (vertex != p_vertex.vertex) {
81 return false;
82 }
83
84 if (uv != p_vertex.uv) {
85 return false;
86 }
87
88 if (uv2 != p_vertex.uv2) {
89 return false;
90 }
91
92 if (normal != p_vertex.normal) {
93 return false;
94 }
95
96 if (binormal != p_vertex.binormal) {
97 return false;
98 }
99
100 if (color != p_vertex.color) {
101 return false;
102 }
103
104 if (bones.size() != p_vertex.bones.size()) {
105 return false;
106 }
107
108 for (int i = 0; i < bones.size(); i++) {
109 if (bones[i] != p_vertex.bones[i]) {
110 return false;
111 }
112 }
113
114 for (int i = 0; i < weights.size(); i++) {
115 if (weights[i] != p_vertex.weights[i]) {
116 return false;
117 }
118 }
119
120 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
121 if (custom[i] != p_vertex.custom[i]) {
122 return false;
123 }
124 }
125
126 if (smooth_group != p_vertex.smooth_group) {
127 return false;
128 }
129
130 return true;
131}
132
133uint32_t SurfaceTool::VertexHasher::hash(const Vertex &p_vtx) {
134 uint32_t h = hash_djb2_buffer((const uint8_t *)&p_vtx.vertex, sizeof(real_t) * 3);
135 h = hash_djb2_buffer((const uint8_t *)&p_vtx.normal, sizeof(real_t) * 3, h);
136 h = hash_djb2_buffer((const uint8_t *)&p_vtx.binormal, sizeof(real_t) * 3, h);
137 h = hash_djb2_buffer((const uint8_t *)&p_vtx.tangent, sizeof(real_t) * 3, h);
138 h = hash_djb2_buffer((const uint8_t *)&p_vtx.uv, sizeof(real_t) * 2, h);
139 h = hash_djb2_buffer((const uint8_t *)&p_vtx.uv2, sizeof(real_t) * 2, h);
140 h = hash_djb2_buffer((const uint8_t *)&p_vtx.color, sizeof(real_t) * 4, h);
141 h = hash_djb2_buffer((const uint8_t *)p_vtx.bones.ptr(), p_vtx.bones.size() * sizeof(int), h);
142 h = hash_djb2_buffer((const uint8_t *)p_vtx.weights.ptr(), p_vtx.weights.size() * sizeof(float), h);
143 h = hash_djb2_buffer((const uint8_t *)&p_vtx.custom[0], sizeof(Color) * RS::ARRAY_CUSTOM_COUNT, h);
144 h = hash_murmur3_one_32(p_vtx.smooth_group, h);
145 h = hash_fmix32(h);
146 return h;
147}
148
149bool SurfaceTool::SmoothGroupVertex::operator==(const SmoothGroupVertex &p_vertex) const {
150 if (vertex != p_vertex.vertex) {
151 return false;
152 }
153
154 if (smooth_group != p_vertex.smooth_group) {
155 return false;
156 }
157
158 return true;
159}
160
161uint32_t SurfaceTool::SmoothGroupVertexHasher::hash(const SmoothGroupVertex &p_vtx) {
162 uint32_t h = hash_djb2_buffer((const uint8_t *)&p_vtx.vertex, sizeof(real_t) * 3);
163 h = hash_murmur3_one_32(p_vtx.smooth_group, h);
164 h = hash_fmix32(h);
165 return h;
166}
167
168uint32_t SurfaceTool::TriangleHasher::hash(const int *p_triangle) {
169 int t0 = p_triangle[0];
170 int t1 = p_triangle[1];
171 int t2 = p_triangle[2];
172
173 if (t0 > t1) {
174 SWAP(t0, t1);
175 }
176 if (t1 > t2) {
177 SWAP(t1, t2);
178 }
179 if (t0 > t1) {
180 SWAP(t0, t1);
181 }
182
183 return (t0 * 73856093) ^ (t1 * 19349663) ^ (t2 * 83492791);
184}
185
186bool SurfaceTool::TriangleHasher::compare(const int *p_lhs, const int *p_rhs) {
187 int r0 = p_rhs[0];
188 int r1 = p_rhs[1];
189 int r2 = p_rhs[2];
190
191 if (r0 > r1) {
192 SWAP(r0, r1);
193 }
194 if (r1 > r2) {
195 SWAP(r1, r2);
196 }
197 if (r0 > r1) {
198 SWAP(r0, r1);
199 }
200
201 int l0 = p_lhs[0];
202 int l1 = p_lhs[1];
203 int l2 = p_lhs[2];
204
205 if (l0 > l1) {
206 SWAP(l0, l1);
207 }
208 if (l1 > l2) {
209 SWAP(l1, l2);
210 }
211 if (l0 > l1) {
212 SWAP(l0, l1);
213 }
214
215 return l0 == r0 && l1 == r1 && l2 == r2;
216}
217
218void SurfaceTool::begin(Mesh::PrimitiveType p_primitive) {
219 clear();
220
221 primitive = p_primitive;
222 begun = true;
223 first = true;
224}
225
226void SurfaceTool::add_vertex(const Vector3 &p_vertex) {
227 ERR_FAIL_COND(!begun);
228
229 Vertex vtx;
230 vtx.vertex = p_vertex;
231 vtx.color = last_color;
232 vtx.normal = last_normal;
233 vtx.uv = last_uv;
234 vtx.uv2 = last_uv2;
235 vtx.weights = last_weights;
236 vtx.bones = last_bones;
237 vtx.tangent = last_tangent.normal;
238 vtx.binormal = last_normal.cross(last_tangent.normal).normalized() * last_tangent.d;
239 vtx.smooth_group = last_smooth_group;
240
241 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
242 vtx.custom[i] = last_custom[i];
243 }
244
245 const int expected_vertices = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
246
247 if ((format & Mesh::ARRAY_FORMAT_WEIGHTS || format & Mesh::ARRAY_FORMAT_BONES) && (vtx.weights.size() != expected_vertices || vtx.bones.size() != expected_vertices)) {
248 //ensure vertices are the expected amount
249 ERR_FAIL_COND(vtx.weights.size() != vtx.bones.size());
250 if (vtx.weights.size() < expected_vertices) {
251 //less than required, fill
252 for (int i = vtx.weights.size(); i < expected_vertices; i++) {
253 vtx.weights.push_back(0);
254 vtx.bones.push_back(0);
255 }
256 } else if (vtx.weights.size() > expected_vertices) {
257 //more than required, sort, cap and normalize.
258 Vector<WeightSort> weights;
259 for (int i = 0; i < vtx.weights.size(); i++) {
260 WeightSort ws;
261 ws.index = vtx.bones[i];
262 ws.weight = vtx.weights[i];
263 weights.push_back(ws);
264 }
265
266 //sort
267 weights.sort();
268 //cap
269 weights.resize(expected_vertices);
270 //renormalize
271 float total = 0.0;
272 for (int i = 0; i < expected_vertices; i++) {
273 total += weights[i].weight;
274 }
275
276 vtx.weights.resize(expected_vertices);
277 vtx.bones.resize(expected_vertices);
278
279 for (int i = 0; i < expected_vertices; i++) {
280 if (total > 0) {
281 vtx.weights.write[i] = weights[i].weight / total;
282 } else {
283 vtx.weights.write[i] = 0;
284 }
285 vtx.bones.write[i] = weights[i].index;
286 }
287 }
288 }
289
290 vertex_array.push_back(vtx);
291 first = false;
292
293 format |= Mesh::ARRAY_FORMAT_VERTEX;
294}
295
296void SurfaceTool::set_color(Color p_color) {
297 ERR_FAIL_COND(!begun);
298
299 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_COLOR));
300
301 format |= Mesh::ARRAY_FORMAT_COLOR;
302 last_color = p_color;
303}
304
305void SurfaceTool::set_normal(const Vector3 &p_normal) {
306 ERR_FAIL_COND(!begun);
307
308 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_NORMAL));
309
310 format |= Mesh::ARRAY_FORMAT_NORMAL;
311 last_normal = p_normal;
312}
313
314void SurfaceTool::set_tangent(const Plane &p_tangent) {
315 ERR_FAIL_COND(!begun);
316 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TANGENT));
317
318 format |= Mesh::ARRAY_FORMAT_TANGENT;
319 last_tangent = p_tangent;
320}
321
322void SurfaceTool::set_uv(const Vector2 &p_uv) {
323 ERR_FAIL_COND(!begun);
324 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV));
325
326 format |= Mesh::ARRAY_FORMAT_TEX_UV;
327 last_uv = p_uv;
328}
329
330void SurfaceTool::set_uv2(const Vector2 &p_uv2) {
331 ERR_FAIL_COND(!begun);
332 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_TEX_UV2));
333
334 format |= Mesh::ARRAY_FORMAT_TEX_UV2;
335 last_uv2 = p_uv2;
336}
337
338void SurfaceTool::set_custom(int p_channel_index, const Color &p_custom) {
339 ERR_FAIL_INDEX(p_channel_index, RS::ARRAY_CUSTOM_COUNT);
340 ERR_FAIL_COND(!begun);
341 ERR_FAIL_COND(last_custom_format[p_channel_index] == CUSTOM_MAX);
342 static const uint32_t mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 };
343 ERR_FAIL_COND(!first && !(format & mask[p_channel_index]));
344
345 if (first) {
346 format |= mask[p_channel_index];
347 }
348 last_custom[p_channel_index] = p_custom;
349}
350
351void SurfaceTool::set_bones(const Vector<int> &p_bones) {
352 ERR_FAIL_COND(!begun);
353 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_BONES));
354
355 format |= Mesh::ARRAY_FORMAT_BONES;
356 if (skin_weights == SKIN_8_WEIGHTS) {
357 format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
358 }
359 last_bones = p_bones;
360}
361
362void SurfaceTool::set_weights(const Vector<float> &p_weights) {
363 ERR_FAIL_COND(!begun);
364 ERR_FAIL_COND(!first && !(format & Mesh::ARRAY_FORMAT_WEIGHTS));
365
366 format |= Mesh::ARRAY_FORMAT_WEIGHTS;
367 if (skin_weights == SKIN_8_WEIGHTS) {
368 format |= Mesh::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
369 }
370 last_weights = p_weights;
371}
372
373void SurfaceTool::set_smooth_group(uint32_t p_group) {
374 last_smooth_group = p_group;
375}
376
377void SurfaceTool::_add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<Color> &p_colors, const Vector<Vector2> &p_uv2s, const Vector<Vector3> &p_normals, const TypedArray<Plane> &p_tangents) {
378 add_triangle_fan(p_vertices, p_uvs, p_colors, p_uv2s, p_normals, Variant(p_tangents));
379}
380
381void SurfaceTool::add_triangle_fan(const Vector<Vector3> &p_vertices, const Vector<Vector2> &p_uvs, const Vector<Color> &p_colors, const Vector<Vector2> &p_uv2s, const Vector<Vector3> &p_normals, const Vector<Plane> &p_tangents) {
382 ERR_FAIL_COND(!begun);
383 ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES);
384 ERR_FAIL_COND(p_vertices.size() < 3);
385
386#define ADD_POINT(n) \
387 { \
388 if (p_colors.size() > n) \
389 set_color(p_colors[n]); \
390 if (p_uvs.size() > n) \
391 set_uv(p_uvs[n]); \
392 if (p_uv2s.size() > n) \
393 set_uv2(p_uv2s[n]); \
394 if (p_normals.size() > n) \
395 set_normal(p_normals[n]); \
396 if (p_tangents.size() > n) \
397 set_tangent(p_tangents[n]); \
398 add_vertex(p_vertices[n]); \
399 }
400
401 for (int i = 0; i < p_vertices.size() - 2; i++) {
402 ADD_POINT(0);
403 ADD_POINT(i + 1);
404 ADD_POINT(i + 2);
405 }
406
407#undef ADD_POINT
408}
409
410void SurfaceTool::add_index(int p_index) {
411 ERR_FAIL_COND(!begun);
412 ERR_FAIL_COND(p_index < 0);
413
414 format |= Mesh::ARRAY_FORMAT_INDEX;
415 index_array.push_back(p_index);
416}
417
418Array SurfaceTool::commit_to_arrays() {
419 int varr_len = vertex_array.size();
420
421 Array a;
422 a.resize(Mesh::ARRAY_MAX);
423
424 for (int i = 0; i < Mesh::ARRAY_MAX; i++) {
425 if (!(format & (1 << i))) {
426 continue; //not in format
427 }
428
429 switch (i) {
430 case Mesh::ARRAY_VERTEX:
431 case Mesh::ARRAY_NORMAL: {
432 Vector<Vector3> array;
433 array.resize(varr_len);
434 Vector3 *w = array.ptrw();
435
436 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
437 const Vertex &v = vertex_array[idx];
438
439 switch (i) {
440 case Mesh::ARRAY_VERTEX: {
441 w[idx] = v.vertex;
442 } break;
443 case Mesh::ARRAY_NORMAL: {
444 w[idx] = v.normal;
445 } break;
446 }
447 }
448
449 a[i] = array;
450
451 } break;
452
453 case Mesh::ARRAY_TEX_UV:
454 case Mesh::ARRAY_TEX_UV2: {
455 Vector<Vector2> array;
456 array.resize(varr_len);
457 Vector2 *w = array.ptrw();
458
459 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
460 const Vertex &v = vertex_array[idx];
461
462 switch (i) {
463 case Mesh::ARRAY_TEX_UV: {
464 w[idx] = v.uv;
465 } break;
466 case Mesh::ARRAY_TEX_UV2: {
467 w[idx] = v.uv2;
468 } break;
469 }
470 }
471
472 a[i] = array;
473 } break;
474 case Mesh::ARRAY_TANGENT: {
475 Vector<float> array;
476 array.resize(varr_len * 4);
477 float *w = array.ptrw();
478
479 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
480 const Vertex &v = vertex_array[idx];
481
482 w[idx * 4 + 0] = v.tangent.x;
483 w[idx * 4 + 1] = v.tangent.y;
484 w[idx * 4 + 2] = v.tangent.z;
485
486 //float d = v.tangent.dot(v.binormal,v.normal);
487 float d = v.binormal.dot(v.normal.cross(v.tangent));
488 w[idx * 4 + 3] = d < 0 ? -1 : 1;
489 }
490
491 a[i] = array;
492
493 } break;
494 case Mesh::ARRAY_COLOR: {
495 Vector<Color> array;
496 array.resize(varr_len);
497 Color *w = array.ptrw();
498
499 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
500 const Vertex &v = vertex_array[idx];
501
502 w[idx] = v.color;
503 }
504
505 a[i] = array;
506 } break;
507 case Mesh::ARRAY_CUSTOM0:
508 case Mesh::ARRAY_CUSTOM1:
509 case Mesh::ARRAY_CUSTOM2:
510 case Mesh::ARRAY_CUSTOM3: {
511 int fmt = i - Mesh::ARRAY_CUSTOM0;
512 switch (last_custom_format[fmt]) {
513 case CUSTOM_RGBA8_UNORM: {
514 Vector<uint8_t> array;
515 array.resize(varr_len * 4);
516 uint8_t *w = array.ptrw();
517
518 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
519 const Vertex &v = vertex_array[idx];
520
521 const Color &c = v.custom[fmt];
522 w[idx * 4 + 0] = CLAMP(int32_t(c.r * 255.0), 0, 255);
523 w[idx * 4 + 1] = CLAMP(int32_t(c.g * 255.0), 0, 255);
524 w[idx * 4 + 2] = CLAMP(int32_t(c.b * 255.0), 0, 255);
525 w[idx * 4 + 3] = CLAMP(int32_t(c.a * 255.0), 0, 255);
526 }
527
528 a[i] = array;
529 } break;
530 case CUSTOM_RGBA8_SNORM: {
531 Vector<uint8_t> array;
532 array.resize(varr_len * 4);
533 uint8_t *w = array.ptrw();
534
535 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
536 const Vertex &v = vertex_array[idx];
537
538 const Color &c = v.custom[fmt];
539 w[idx * 4 + 0] = uint8_t(int8_t(CLAMP(int32_t(c.r * 127.0), -128, 127)));
540 w[idx * 4 + 1] = uint8_t(int8_t(CLAMP(int32_t(c.g * 127.0), -128, 127)));
541 w[idx * 4 + 2] = uint8_t(int8_t(CLAMP(int32_t(c.b * 127.0), -128, 127)));
542 w[idx * 4 + 3] = uint8_t(int8_t(CLAMP(int32_t(c.a * 127.0), -128, 127)));
543 }
544
545 a[i] = array;
546 } break;
547 case CUSTOM_RG_HALF: {
548 Vector<uint8_t> array;
549 array.resize(varr_len * 4);
550 uint16_t *w = (uint16_t *)array.ptrw();
551
552 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
553 const Vertex &v = vertex_array[idx];
554
555 const Color &c = v.custom[fmt];
556 w[idx * 2 + 0] = Math::make_half_float(c.r);
557 w[idx * 2 + 1] = Math::make_half_float(c.g);
558 }
559
560 a[i] = array;
561 } break;
562 case CUSTOM_RGBA_HALF: {
563 Vector<uint8_t> array;
564 array.resize(varr_len * 8);
565 uint16_t *w = (uint16_t *)array.ptrw();
566
567 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
568 const Vertex &v = vertex_array[idx];
569
570 const Color &c = v.custom[fmt];
571 w[idx * 4 + 0] = Math::make_half_float(c.r);
572 w[idx * 4 + 1] = Math::make_half_float(c.g);
573 w[idx * 4 + 2] = Math::make_half_float(c.b);
574 w[idx * 4 + 3] = Math::make_half_float(c.a);
575 }
576
577 a[i] = array;
578 } break;
579 case CUSTOM_R_FLOAT: {
580 Vector<float> array;
581 array.resize(varr_len);
582 float *w = (float *)array.ptrw();
583
584 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
585 const Vertex &v = vertex_array[idx];
586
587 const Color &c = v.custom[fmt];
588 w[idx] = c.r;
589 }
590
591 a[i] = array;
592 } break;
593 case CUSTOM_RG_FLOAT: {
594 Vector<float> array;
595 array.resize(varr_len * 2);
596 float *w = (float *)array.ptrw();
597
598 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
599 const Vertex &v = vertex_array[idx];
600
601 const Color &c = v.custom[fmt];
602 w[idx * 2 + 0] = c.r;
603 w[idx * 2 + 1] = c.g;
604 }
605
606 a[i] = array;
607 } break;
608 case CUSTOM_RGB_FLOAT: {
609 Vector<float> array;
610 array.resize(varr_len * 3);
611 float *w = (float *)array.ptrw();
612
613 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
614 const Vertex &v = vertex_array[idx];
615
616 const Color &c = v.custom[fmt];
617 w[idx * 3 + 0] = c.r;
618 w[idx * 3 + 1] = c.g;
619 w[idx * 3 + 2] = c.b;
620 }
621
622 a[i] = array;
623 } break;
624 case CUSTOM_RGBA_FLOAT: {
625 Vector<float> array;
626 array.resize(varr_len * 4);
627 float *w = (float *)array.ptrw();
628
629 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
630 const Vertex &v = vertex_array[idx];
631
632 const Color &c = v.custom[fmt];
633 w[idx * 4 + 0] = c.r;
634 w[idx * 4 + 1] = c.g;
635 w[idx * 4 + 2] = c.b;
636 w[idx * 4 + 3] = c.a;
637 }
638
639 a[i] = array;
640 } break;
641 default: {
642 } //unreachable but compiler warning anyway
643 }
644 } break;
645 case Mesh::ARRAY_BONES: {
646 int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
647 Vector<int> array;
648 array.resize(varr_len * count);
649 array.fill(0);
650 int *w = array.ptrw();
651
652 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
653 const Vertex &v = vertex_array[idx];
654
655 if (v.bones.size() != count) {
656 ERR_PRINT_ONCE(vformat("Invalid bones size %d vs count %d", v.bones.size(), count));
657 continue;
658 }
659
660 for (int j = 0; j < count; j++) {
661 w[idx * count + j] = v.bones[j];
662 }
663 }
664
665 a[i] = array;
666
667 } break;
668 case Mesh::ARRAY_WEIGHTS: {
669 Vector<float> array;
670 int count = skin_weights == SKIN_8_WEIGHTS ? 8 : 4;
671
672 array.resize(varr_len * count);
673 array.fill(0.0f);
674 float *w = array.ptrw();
675
676 for (uint32_t idx = 0; idx < vertex_array.size(); idx++) {
677 const Vertex &v = vertex_array[idx];
678
679 if (v.weights.size() != count) {
680 ERR_PRINT_ONCE(vformat("Invalid weight size %d vs count %d", v.weights.size(), count));
681 continue;
682 }
683
684 for (int j = 0; j < count; j++) {
685 w[idx * count + j] = v.weights[j];
686 }
687 }
688
689 a[i] = array;
690
691 } break;
692 case Mesh::ARRAY_INDEX: {
693 ERR_CONTINUE(index_array.size() == 0);
694
695 Vector<int> array;
696 array.resize(index_array.size());
697 int *w = array.ptrw();
698
699 for (uint32_t idx = 0; idx < index_array.size(); idx++) {
700 w[idx] = index_array[idx];
701 }
702
703 a[i] = array;
704 } break;
705
706 default: {
707 }
708 }
709 }
710
711 return a;
712}
713
714Ref<ArrayMesh> SurfaceTool::commit(const Ref<ArrayMesh> &p_existing, uint32_t p_compress_flags) {
715 Ref<ArrayMesh> mesh;
716 if (p_existing.is_valid()) {
717 mesh = p_existing;
718 } else {
719 mesh.instantiate();
720 }
721
722 int varr_len = vertex_array.size();
723
724 if (varr_len == 0) {
725 return mesh;
726 }
727
728 int surface = mesh->get_surface_count();
729
730 Array a = commit_to_arrays();
731
732 uint32_t compress_flags = (p_compress_flags >> RS::ARRAY_COMPRESS_FLAGS_BASE) << RS::ARRAY_COMPRESS_FLAGS_BASE;
733 static const uint32_t shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT };
734 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
735 if (last_custom_format[i] != CUSTOM_MAX) {
736 compress_flags |= last_custom_format[i] << shift[i];
737 }
738 }
739
740 mesh->add_surface_from_arrays(primitive, a, Array(), Dictionary(), compress_flags);
741
742 if (material.is_valid()) {
743 mesh->surface_set_material(surface, material);
744 }
745
746 return mesh;
747}
748
749void SurfaceTool::index() {
750 if (index_array.size()) {
751 return; //already indexed
752 }
753
754 HashMap<Vertex, int, VertexHasher> indices;
755 LocalVector<Vertex> old_vertex_array = vertex_array;
756 vertex_array.clear();
757
758 for (const Vertex &vertex : old_vertex_array) {
759 int *idxptr = indices.getptr(vertex);
760 int idx;
761 if (!idxptr) {
762 idx = indices.size();
763 vertex_array.push_back(vertex);
764 indices[vertex] = idx;
765 } else {
766 idx = *idxptr;
767 }
768
769 index_array.push_back(idx);
770 }
771
772 format |= Mesh::ARRAY_FORMAT_INDEX;
773}
774
775void SurfaceTool::deindex() {
776 if (index_array.size() == 0) {
777 return; //nothing to deindex
778 }
779
780 LocalVector<Vertex> old_vertex_array = vertex_array;
781 vertex_array.clear();
782 for (const int &index : index_array) {
783 ERR_FAIL_COND(uint32_t(index) >= old_vertex_array.size());
784 vertex_array.push_back(old_vertex_array[index]);
785 }
786 format &= ~Mesh::ARRAY_FORMAT_INDEX;
787 index_array.clear();
788}
789
790void SurfaceTool::_create_list(const Ref<Mesh> &p_existing, int p_surface, LocalVector<Vertex> *r_vertex, LocalVector<int> *r_index, uint32_t &lformat) {
791 ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::_create_list() must be a valid object of type Mesh");
792
793 Array arr = p_existing->surface_get_arrays(p_surface);
794 ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX);
795 _create_list_from_arrays(arr, r_vertex, r_index, lformat);
796}
797
798const uint32_t SurfaceTool::custom_mask[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0, Mesh::ARRAY_FORMAT_CUSTOM1, Mesh::ARRAY_FORMAT_CUSTOM2, Mesh::ARRAY_FORMAT_CUSTOM3 };
799const uint32_t SurfaceTool::custom_shift[RS::ARRAY_CUSTOM_COUNT] = { Mesh::ARRAY_FORMAT_CUSTOM0_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM1_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM2_SHIFT, Mesh::ARRAY_FORMAT_CUSTOM3_SHIFT };
800
801void SurfaceTool::create_vertex_array_from_triangle_arrays(const Array &p_arrays, LocalVector<SurfaceTool::Vertex> &ret, uint32_t *r_format) {
802 ret.clear();
803
804 Vector<Vector3> varr = p_arrays[RS::ARRAY_VERTEX];
805 Vector<Vector3> narr = p_arrays[RS::ARRAY_NORMAL];
806 Vector<float> tarr = p_arrays[RS::ARRAY_TANGENT];
807 Vector<Color> carr = p_arrays[RS::ARRAY_COLOR];
808 Vector<Vector2> uvarr = p_arrays[RS::ARRAY_TEX_UV];
809 Vector<Vector2> uv2arr = p_arrays[RS::ARRAY_TEX_UV2];
810 Vector<int> barr = p_arrays[RS::ARRAY_BONES];
811 Vector<float> warr = p_arrays[RS::ARRAY_WEIGHTS];
812 Vector<float> custom_float[RS::ARRAY_CUSTOM_COUNT];
813
814 int vc = varr.size();
815 if (vc == 0) {
816 if (r_format) {
817 *r_format = 0;
818 }
819 return;
820 }
821
822 int lformat = 0;
823 if (varr.size()) {
824 lformat |= RS::ARRAY_FORMAT_VERTEX;
825 }
826 if (narr.size()) {
827 lformat |= RS::ARRAY_FORMAT_NORMAL;
828 }
829 if (tarr.size()) {
830 lformat |= RS::ARRAY_FORMAT_TANGENT;
831 }
832 if (carr.size()) {
833 lformat |= RS::ARRAY_FORMAT_COLOR;
834 }
835 if (uvarr.size()) {
836 lformat |= RS::ARRAY_FORMAT_TEX_UV;
837 }
838 if (uv2arr.size()) {
839 lformat |= RS::ARRAY_FORMAT_TEX_UV2;
840 }
841 int wcount = 0;
842 if (barr.size() && warr.size()) {
843 lformat |= RS::ARRAY_FORMAT_BONES;
844 lformat |= RS::ARRAY_FORMAT_WEIGHTS;
845
846 wcount = barr.size() / varr.size();
847 if (wcount == 8) {
848 lformat |= RS::ARRAY_FLAG_USE_8_BONE_WEIGHTS;
849 }
850 }
851
852 if (warr.size()) {
853 lformat |= RS::ARRAY_FORMAT_WEIGHTS;
854 }
855
856 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
857 ERR_CONTINUE_MSG(p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_BYTE_ARRAY, "Extracting Byte/Half formats is not supported");
858 if (p_arrays[RS::ARRAY_CUSTOM0 + i].get_type() == Variant::PACKED_FLOAT32_ARRAY) {
859 lformat |= custom_mask[i];
860 custom_float[i] = p_arrays[RS::ARRAY_CUSTOM0 + i];
861 int fmt = custom_float[i].size() / varr.size();
862 if (fmt == 1) {
863 lformat |= CUSTOM_R_FLOAT << custom_shift[i];
864 } else if (fmt == 2) {
865 lformat |= CUSTOM_RG_FLOAT << custom_shift[i];
866 } else if (fmt == 3) {
867 lformat |= CUSTOM_RGB_FLOAT << custom_shift[i];
868 } else if (fmt == 4) {
869 lformat |= CUSTOM_RGBA_FLOAT << custom_shift[i];
870 }
871 }
872 }
873
874 for (int i = 0; i < vc; i++) {
875 Vertex v;
876 if (lformat & RS::ARRAY_FORMAT_VERTEX) {
877 v.vertex = varr[i];
878 }
879 if (lformat & RS::ARRAY_FORMAT_NORMAL) {
880 v.normal = narr[i];
881 }
882 if (lformat & RS::ARRAY_FORMAT_TANGENT) {
883 Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]);
884 v.tangent = p.normal;
885 v.binormal = p.normal.cross(v.tangent).normalized() * p.d;
886 }
887 if (lformat & RS::ARRAY_FORMAT_COLOR) {
888 v.color = carr[i];
889 }
890 if (lformat & RS::ARRAY_FORMAT_TEX_UV) {
891 v.uv = uvarr[i];
892 }
893 if (lformat & RS::ARRAY_FORMAT_TEX_UV2) {
894 v.uv2 = uv2arr[i];
895 }
896 if (lformat & RS::ARRAY_FORMAT_BONES) {
897 Vector<int> b;
898 b.resize(wcount);
899 for (int j = 0; j < wcount; j++) {
900 b.write[j] = barr[i * wcount + j];
901 }
902 v.bones = b;
903 }
904 if (lformat & RS::ARRAY_FORMAT_WEIGHTS) {
905 Vector<float> w;
906 w.resize(wcount);
907 for (int j = 0; j < wcount; j++) {
908 w.write[j] = warr[i * wcount + j];
909 }
910 v.weights = w;
911 }
912
913 for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
914 if (lformat & custom_mask[j]) {
915 int cc = custom_float[j].size() / varr.size();
916 for (int k = 0; k < cc; k++) {
917 v.custom[j][k] = custom_float[j][i * cc + k];
918 }
919 }
920 }
921
922 ret.push_back(v);
923 }
924
925 if (r_format) {
926 *r_format = lformat;
927 }
928}
929
930void SurfaceTool::_create_list_from_arrays(Array arr, LocalVector<Vertex> *r_vertex, LocalVector<int> *r_index, uint32_t &lformat) {
931 create_vertex_array_from_triangle_arrays(arr, *r_vertex, &lformat);
932 ERR_FAIL_COND(r_vertex->size() == 0);
933
934 //indices
935 r_index->clear();
936
937 Vector<int> idx = arr[RS::ARRAY_INDEX];
938 int is = idx.size();
939 if (is) {
940 lformat |= RS::ARRAY_FORMAT_INDEX;
941 const int *iarr = idx.ptr();
942 for (int i = 0; i < is; i++) {
943 r_index->push_back(iarr[i]);
944 }
945 }
946}
947
948void SurfaceTool::create_from_triangle_arrays(const Array &p_arrays) {
949 clear();
950 primitive = Mesh::PRIMITIVE_TRIANGLES;
951 _create_list_from_arrays(p_arrays, &vertex_array, &index_array, format);
952
953 for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
954 if (format & custom_mask[j]) {
955 last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
956 }
957 }
958}
959
960void SurfaceTool::create_from(const Ref<Mesh> &p_existing, int p_surface) {
961 ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::create_from() must be a valid object of type Mesh");
962
963 clear();
964 primitive = p_existing->surface_get_primitive_type(p_surface);
965 _create_list(p_existing, p_surface, &vertex_array, &index_array, format);
966 material = p_existing->surface_get_material(p_surface);
967
968 for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
969 if (format & custom_mask[j]) {
970 last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
971 }
972 }
973}
974
975void SurfaceTool::create_from_blend_shape(const Ref<Mesh> &p_existing, int p_surface, const String &p_blend_shape_name) {
976 ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::create_from_blend_shape() must be a valid object of type Mesh");
977
978 clear();
979 primitive = p_existing->surface_get_primitive_type(p_surface);
980 Array arr = p_existing->surface_get_blend_shape_arrays(p_surface);
981 Array blend_shape_names;
982 int32_t shape_idx = -1;
983 for (int32_t i = 0; i < p_existing->get_blend_shape_count(); i++) {
984 String name = p_existing->get_blend_shape_name(i);
985 if (name == p_blend_shape_name) {
986 shape_idx = i;
987 break;
988 }
989 }
990 ERR_FAIL_COND(shape_idx == -1);
991 ERR_FAIL_COND(shape_idx >= arr.size());
992 Array blendshape_mesh_arrays = arr[shape_idx];
993 ERR_FAIL_COND(blendshape_mesh_arrays.size() != RS::ARRAY_MAX);
994
995 Array source_mesh_arrays = p_existing->surface_get_arrays(p_surface);
996 ERR_FAIL_COND(source_mesh_arrays.size() != RS::ARRAY_MAX);
997
998 // Copy BlendShape vertex data over while keeping e.g. bones, weights, index from existing mesh intact.
999 source_mesh_arrays[RS::ARRAY_VERTEX] = blendshape_mesh_arrays[RS::ARRAY_VERTEX];
1000 source_mesh_arrays[RS::ARRAY_NORMAL] = blendshape_mesh_arrays[RS::ARRAY_NORMAL];
1001 source_mesh_arrays[RS::ARRAY_TANGENT] = blendshape_mesh_arrays[RS::ARRAY_TANGENT];
1002
1003 _create_list_from_arrays(source_mesh_arrays, &vertex_array, &index_array, format);
1004
1005 material = p_existing->surface_get_material(p_surface);
1006 format = p_existing->surface_get_format(p_surface);
1007
1008 for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
1009 if (format & custom_mask[j]) {
1010 last_custom_format[j] = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
1011 }
1012 }
1013}
1014
1015void SurfaceTool::append_from(const Ref<Mesh> &p_existing, int p_surface, const Transform3D &p_xform) {
1016 ERR_FAIL_NULL_MSG(p_existing, "First argument in SurfaceTool::append_from() must be a valid object of type Mesh");
1017
1018 if (vertex_array.size() == 0) {
1019 primitive = p_existing->surface_get_primitive_type(p_surface);
1020 format = 0;
1021 }
1022
1023 uint32_t nformat = 0;
1024 LocalVector<Vertex> nvertices;
1025 LocalVector<int> nindices;
1026 _create_list(p_existing, p_surface, &nvertices, &nindices, nformat);
1027 format |= nformat;
1028
1029 for (int j = 0; j < RS::ARRAY_CUSTOM_COUNT; j++) {
1030 if (format & custom_mask[j]) {
1031 CustomFormat new_format = (CustomFormat)((format >> custom_shift[j]) & RS::ARRAY_FORMAT_CUSTOM_MASK);
1032 last_custom_format[j] = new_format;
1033 }
1034 }
1035 int vfrom = vertex_array.size();
1036
1037 for (Vertex &v : nvertices) {
1038 v.vertex = p_xform.xform(v.vertex);
1039 if (nformat & RS::ARRAY_FORMAT_NORMAL) {
1040 v.normal = p_xform.basis.xform(v.normal);
1041 }
1042 if (nformat & RS::ARRAY_FORMAT_TANGENT) {
1043 v.tangent = p_xform.basis.xform(v.tangent);
1044 v.binormal = p_xform.basis.xform(v.binormal);
1045 }
1046
1047 vertex_array.push_back(v);
1048 }
1049
1050 for (const int &index : nindices) {
1051 int dst_index = index + vfrom;
1052 index_array.push_back(dst_index);
1053 }
1054 if (index_array.size() % 3) {
1055 WARN_PRINT("SurfaceTool: Index array not a multiple of 3.");
1056 }
1057}
1058
1059//mikktspace callbacks
1060namespace {
1061struct TangentGenerationContextUserData {
1062 LocalVector<SurfaceTool::Vertex> *vertices;
1063 LocalVector<int> *indices;
1064};
1065} // namespace
1066
1067int SurfaceTool::mikktGetNumFaces(const SMikkTSpaceContext *pContext) {
1068 TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData);
1069
1070 if (triangle_data.indices->size() > 0) {
1071 return triangle_data.indices->size() / 3;
1072 } else {
1073 return triangle_data.vertices->size() / 3;
1074 }
1075}
1076
1077int SurfaceTool::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) {
1078 return 3; //always 3
1079}
1080
1081void SurfaceTool::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) {
1082 TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData);
1083 Vector3 v;
1084 if (triangle_data.indices->size() > 0) {
1085 uint32_t index = triangle_data.indices->operator[](iFace * 3 + iVert);
1086 if (index < triangle_data.vertices->size()) {
1087 v = triangle_data.vertices->operator[](index).vertex;
1088 }
1089 } else {
1090 v = triangle_data.vertices->operator[](iFace * 3 + iVert).vertex;
1091 }
1092
1093 fvPosOut[0] = v.x;
1094 fvPosOut[1] = v.y;
1095 fvPosOut[2] = v.z;
1096}
1097
1098void SurfaceTool::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) {
1099 TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData);
1100 Vector3 v;
1101 if (triangle_data.indices->size() > 0) {
1102 uint32_t index = triangle_data.indices->operator[](iFace * 3 + iVert);
1103 if (index < triangle_data.vertices->size()) {
1104 v = triangle_data.vertices->operator[](index).normal;
1105 }
1106 } else {
1107 v = triangle_data.vertices->operator[](iFace * 3 + iVert).normal;
1108 }
1109
1110 fvNormOut[0] = v.x;
1111 fvNormOut[1] = v.y;
1112 fvNormOut[2] = v.z;
1113}
1114
1115void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) {
1116 TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData);
1117 Vector2 v;
1118 if (triangle_data.indices->size() > 0) {
1119 uint32_t index = triangle_data.indices->operator[](iFace * 3 + iVert);
1120 if (index < triangle_data.vertices->size()) {
1121 v = triangle_data.vertices->operator[](index).uv;
1122 }
1123 } else {
1124 v = triangle_data.vertices->operator[](iFace * 3 + iVert).uv;
1125 }
1126
1127 fvTexcOut[0] = v.x;
1128 fvTexcOut[1] = v.y;
1129}
1130
1131void SurfaceTool::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT,
1132 const tbool bIsOrientationPreserving, const int iFace, const int iVert) {
1133 TangentGenerationContextUserData &triangle_data = *reinterpret_cast<TangentGenerationContextUserData *>(pContext->m_pUserData);
1134 Vertex *vtx = nullptr;
1135 if (triangle_data.indices->size() > 0) {
1136 uint32_t index = triangle_data.indices->operator[](iFace * 3 + iVert);
1137 if (index < triangle_data.vertices->size()) {
1138 vtx = &triangle_data.vertices->operator[](index);
1139 }
1140 } else {
1141 vtx = &triangle_data.vertices->operator[](iFace * 3 + iVert);
1142 }
1143
1144 if (vtx != nullptr) {
1145 vtx->tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]);
1146 vtx->binormal = Vector3(-fvBiTangent[0], -fvBiTangent[1], -fvBiTangent[2]); // for some reason these are reversed, something with the coordinate system in Godot
1147 }
1148}
1149
1150void SurfaceTool::generate_tangents() {
1151 ERR_FAIL_COND(!(format & Mesh::ARRAY_FORMAT_TEX_UV));
1152 ERR_FAIL_COND(!(format & Mesh::ARRAY_FORMAT_NORMAL));
1153
1154 SMikkTSpaceInterface mkif;
1155 mkif.m_getNormal = mikktGetNormal;
1156 mkif.m_getNumFaces = mikktGetNumFaces;
1157 mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace;
1158 mkif.m_getPosition = mikktGetPosition;
1159 mkif.m_getTexCoord = mikktGetTexCoord;
1160 mkif.m_setTSpace = mikktSetTSpaceDefault;
1161 mkif.m_setTSpaceBasic = nullptr;
1162
1163 SMikkTSpaceContext msc;
1164 msc.m_pInterface = &mkif;
1165
1166 TangentGenerationContextUserData triangle_data;
1167 triangle_data.vertices = &vertex_array;
1168 for (Vertex &vertex : vertex_array) {
1169 vertex.binormal = Vector3();
1170 vertex.tangent = Vector3();
1171 }
1172 triangle_data.indices = &index_array;
1173 msc.m_pUserData = &triangle_data;
1174
1175 bool res = genTangSpaceDefault(&msc);
1176
1177 ERR_FAIL_COND(!res);
1178 format |= Mesh::ARRAY_FORMAT_TANGENT;
1179}
1180
1181void SurfaceTool::generate_normals(bool p_flip) {
1182 ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES);
1183
1184 bool was_indexed = index_array.size();
1185
1186 deindex();
1187
1188 ERR_FAIL_COND((vertex_array.size() % 3) != 0);
1189
1190 HashMap<SmoothGroupVertex, Vector3, SmoothGroupVertexHasher> smooth_hash;
1191
1192 for (uint32_t vi = 0; vi < vertex_array.size(); vi += 3) {
1193 Vertex *v = &vertex_array[vi];
1194
1195 Vector3 normal;
1196 if (!p_flip) {
1197 normal = Plane(v[0].vertex, v[1].vertex, v[2].vertex).normal;
1198 } else {
1199 normal = Plane(v[2].vertex, v[1].vertex, v[0].vertex).normal;
1200 }
1201
1202 for (int i = 0; i < 3; i++) {
1203 // Add face normal to smooth vertex influence if vertex is member of a smoothing group
1204 if (v[i].smooth_group != UINT32_MAX) {
1205 Vector3 *lv = smooth_hash.getptr(v[i]);
1206 if (!lv) {
1207 smooth_hash.insert(v[i], normal);
1208 } else {
1209 (*lv) += normal;
1210 }
1211 } else {
1212 v[i].normal = normal;
1213 }
1214 }
1215 }
1216
1217 for (Vertex &vertex : vertex_array) {
1218 if (vertex.smooth_group != UINT32_MAX) {
1219 Vector3 *lv = smooth_hash.getptr(vertex);
1220 if (!lv) {
1221 vertex.normal = Vector3();
1222 } else {
1223 vertex.normal = lv->normalized();
1224 }
1225 }
1226 }
1227
1228 format |= Mesh::ARRAY_FORMAT_NORMAL;
1229
1230 if (was_indexed) {
1231 index();
1232 }
1233}
1234
1235void SurfaceTool::set_material(const Ref<Material> &p_material) {
1236 material = p_material;
1237}
1238
1239Ref<Material> SurfaceTool::get_material() const {
1240 return material;
1241}
1242
1243void SurfaceTool::clear() {
1244 begun = false;
1245 primitive = Mesh::PRIMITIVE_LINES;
1246 format = 0;
1247 last_bones.clear();
1248 last_weights.clear();
1249 index_array.clear();
1250 vertex_array.clear();
1251 material.unref();
1252 last_smooth_group = 0;
1253 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
1254 last_custom_format[i] = CUSTOM_MAX;
1255 }
1256 skin_weights = SKIN_4_WEIGHTS;
1257}
1258
1259void SurfaceTool::set_skin_weight_count(SkinWeightCount p_weights) {
1260 ERR_FAIL_COND(begun);
1261 skin_weights = p_weights;
1262}
1263SurfaceTool::SkinWeightCount SurfaceTool::get_skin_weight_count() const {
1264 return skin_weights;
1265}
1266
1267void SurfaceTool::set_custom_format(int p_channel_index, CustomFormat p_format) {
1268 ERR_FAIL_INDEX(p_channel_index, RS::ARRAY_CUSTOM_COUNT);
1269 ERR_FAIL_COND(!begun);
1270 ERR_FAIL_INDEX(p_format, CUSTOM_MAX + 1);
1271 last_custom_format[p_channel_index] = p_format;
1272}
1273
1274Mesh::PrimitiveType SurfaceTool::get_primitive_type() const {
1275 return primitive;
1276}
1277SurfaceTool::CustomFormat SurfaceTool::get_custom_format(int p_channel_index) const {
1278 ERR_FAIL_INDEX_V(p_channel_index, RS::ARRAY_CUSTOM_COUNT, CUSTOM_MAX);
1279 return last_custom_format[p_channel_index];
1280}
1281void SurfaceTool::optimize_indices_for_cache() {
1282 ERR_FAIL_NULL(optimize_vertex_cache_func);
1283 ERR_FAIL_COND(index_array.size() == 0);
1284 ERR_FAIL_COND(primitive != Mesh::PRIMITIVE_TRIANGLES);
1285 ERR_FAIL_COND(index_array.size() % 3 != 0);
1286
1287 LocalVector old_index_array = index_array;
1288 memset(index_array.ptr(), 0, index_array.size() * sizeof(int));
1289 optimize_vertex_cache_func((unsigned int *)index_array.ptr(), (unsigned int *)old_index_array.ptr(), old_index_array.size(), vertex_array.size());
1290}
1291
1292AABB SurfaceTool::get_aabb() const {
1293 ERR_FAIL_COND_V(vertex_array.size() == 0, AABB());
1294
1295 AABB aabb;
1296 for (uint32_t i = 0; i < vertex_array.size(); i++) {
1297 if (i == 0) {
1298 aabb.position = vertex_array[i].vertex;
1299 } else {
1300 aabb.expand_to(vertex_array[i].vertex);
1301 }
1302 }
1303
1304 return aabb;
1305}
1306Vector<int> SurfaceTool::generate_lod(float p_threshold, int p_target_index_count) {
1307 WARN_DEPRECATED_MSG(R"*(The "SurfaceTool.generate_lod()" method is deprecated. Consider using "ImporterMesh.generate_lods()" instead.)*");
1308
1309 Vector<int> lod;
1310
1311 ERR_FAIL_NULL_V(simplify_func, lod);
1312 ERR_FAIL_COND_V(p_target_index_count < 0, lod);
1313 ERR_FAIL_COND_V(vertex_array.size() == 0, lod);
1314 ERR_FAIL_COND_V(index_array.size() == 0, lod);
1315 ERR_FAIL_COND_V(index_array.size() % 3 != 0, lod);
1316 ERR_FAIL_COND_V(index_array.size() < (unsigned int)p_target_index_count, lod);
1317
1318 lod.resize(index_array.size());
1319 LocalVector<float> vertices; //uses floats
1320 vertices.resize(vertex_array.size() * 3);
1321 for (uint32_t i = 0; i < vertex_array.size(); i++) {
1322 vertices[i * 3 + 0] = vertex_array[i].vertex.x;
1323 vertices[i * 3 + 1] = vertex_array[i].vertex.y;
1324 vertices[i * 3 + 2] = vertex_array[i].vertex.z;
1325 }
1326
1327 float error;
1328 const int simplify_options = SIMPLIFY_LOCK_BORDER;
1329 uint32_t index_count = simplify_func((unsigned int *)lod.ptrw(), (unsigned int *)index_array.ptr(), index_array.size(), vertices.ptr(), vertex_array.size(), sizeof(float) * 3, p_target_index_count, p_threshold, simplify_options, &error);
1330 ERR_FAIL_COND_V(index_count == 0, lod);
1331 lod.resize(index_count);
1332
1333 return lod;
1334}
1335
1336void SurfaceTool::_bind_methods() {
1337 ClassDB::bind_method(D_METHOD("set_skin_weight_count", "count"), &SurfaceTool::set_skin_weight_count);
1338 ClassDB::bind_method(D_METHOD("get_skin_weight_count"), &SurfaceTool::get_skin_weight_count);
1339
1340 ClassDB::bind_method(D_METHOD("set_custom_format", "channel_index", "format"), &SurfaceTool::set_custom_format);
1341 ClassDB::bind_method(D_METHOD("get_custom_format", "channel_index"), &SurfaceTool::get_custom_format);
1342
1343 ClassDB::bind_method(D_METHOD("begin", "primitive"), &SurfaceTool::begin);
1344
1345 ClassDB::bind_method(D_METHOD("add_vertex", "vertex"), &SurfaceTool::add_vertex);
1346 ClassDB::bind_method(D_METHOD("set_color", "color"), &SurfaceTool::set_color);
1347 ClassDB::bind_method(D_METHOD("set_normal", "normal"), &SurfaceTool::set_normal);
1348 ClassDB::bind_method(D_METHOD("set_tangent", "tangent"), &SurfaceTool::set_tangent);
1349 ClassDB::bind_method(D_METHOD("set_uv", "uv"), &SurfaceTool::set_uv);
1350 ClassDB::bind_method(D_METHOD("set_uv2", "uv2"), &SurfaceTool::set_uv2);
1351 ClassDB::bind_method(D_METHOD("set_bones", "bones"), &SurfaceTool::set_bones);
1352 ClassDB::bind_method(D_METHOD("set_weights", "weights"), &SurfaceTool::set_weights);
1353 ClassDB::bind_method(D_METHOD("set_custom", "channel_index", "custom_color"), &SurfaceTool::set_custom);
1354 ClassDB::bind_method(D_METHOD("set_smooth_group", "index"), &SurfaceTool::set_smooth_group);
1355
1356 ClassDB::bind_method(D_METHOD("add_triangle_fan", "vertices", "uvs", "colors", "uv2s", "normals", "tangents"), &SurfaceTool::_add_triangle_fan, DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Color>()), DEFVAL(Vector<Vector2>()), DEFVAL(Vector<Vector3>()), DEFVAL(TypedArray<Plane>()));
1357
1358 ClassDB::bind_method(D_METHOD("add_index", "index"), &SurfaceTool::add_index);
1359
1360 ClassDB::bind_method(D_METHOD("index"), &SurfaceTool::index);
1361 ClassDB::bind_method(D_METHOD("deindex"), &SurfaceTool::deindex);
1362 ClassDB::bind_method(D_METHOD("generate_normals", "flip"), &SurfaceTool::generate_normals, DEFVAL(false));
1363 ClassDB::bind_method(D_METHOD("generate_tangents"), &SurfaceTool::generate_tangents);
1364
1365 ClassDB::bind_method(D_METHOD("optimize_indices_for_cache"), &SurfaceTool::optimize_indices_for_cache);
1366
1367 ClassDB::bind_method(D_METHOD("get_aabb"), &SurfaceTool::get_aabb);
1368 ClassDB::bind_method(D_METHOD("generate_lod", "nd_threshold", "target_index_count"), &SurfaceTool::generate_lod, DEFVAL(3));
1369
1370 ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material);
1371 ClassDB::bind_method(D_METHOD("get_primitive_type"), &SurfaceTool::get_primitive_type);
1372
1373 ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear);
1374
1375 ClassDB::bind_method(D_METHOD("create_from", "existing", "surface"), &SurfaceTool::create_from);
1376 ClassDB::bind_method(D_METHOD("create_from_blend_shape", "existing", "surface", "blend_shape"), &SurfaceTool::create_from_blend_shape);
1377 ClassDB::bind_method(D_METHOD("append_from", "existing", "surface", "transform"), &SurfaceTool::append_from);
1378 ClassDB::bind_method(D_METHOD("commit", "existing", "flags"), &SurfaceTool::commit, DEFVAL(Variant()), DEFVAL(0));
1379 ClassDB::bind_method(D_METHOD("commit_to_arrays"), &SurfaceTool::commit_to_arrays);
1380
1381 BIND_ENUM_CONSTANT(CUSTOM_RGBA8_UNORM);
1382 BIND_ENUM_CONSTANT(CUSTOM_RGBA8_SNORM);
1383 BIND_ENUM_CONSTANT(CUSTOM_RG_HALF);
1384 BIND_ENUM_CONSTANT(CUSTOM_RGBA_HALF);
1385 BIND_ENUM_CONSTANT(CUSTOM_R_FLOAT);
1386 BIND_ENUM_CONSTANT(CUSTOM_RG_FLOAT);
1387 BIND_ENUM_CONSTANT(CUSTOM_RGB_FLOAT);
1388 BIND_ENUM_CONSTANT(CUSTOM_RGBA_FLOAT);
1389 BIND_ENUM_CONSTANT(CUSTOM_MAX);
1390 BIND_ENUM_CONSTANT(SKIN_4_WEIGHTS);
1391 BIND_ENUM_CONSTANT(SKIN_8_WEIGHTS);
1392}
1393
1394SurfaceTool::SurfaceTool() {
1395 for (int i = 0; i < RS::ARRAY_CUSTOM_COUNT; i++) {
1396 last_custom_format[i] = CUSTOM_MAX;
1397 }
1398}
1399