1/**************************************************************************/
2/* mesh_data_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 "mesh_data_tool.h"
32
33void MeshDataTool::clear() {
34 vertices.clear();
35 edges.clear();
36 faces.clear();
37 material = Ref<Material>();
38 format = 0;
39}
40
41Error MeshDataTool::create_from_surface(const Ref<ArrayMesh> &p_mesh, int p_surface) {
42 ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER);
43 ERR_FAIL_COND_V(p_mesh->surface_get_primitive_type(p_surface) != Mesh::PRIMITIVE_TRIANGLES, ERR_INVALID_PARAMETER);
44
45 Array arrays = p_mesh->surface_get_arrays(p_surface);
46 ERR_FAIL_COND_V(arrays.is_empty(), ERR_INVALID_PARAMETER);
47
48 Vector<Vector3> varray = arrays[Mesh::ARRAY_VERTEX];
49
50 int vcount = varray.size();
51 ERR_FAIL_COND_V(vcount == 0, ERR_INVALID_PARAMETER);
52
53 Vector<int> indices;
54
55 if (arrays[Mesh::ARRAY_INDEX].get_type() != Variant::NIL) {
56 indices = arrays[Mesh::ARRAY_INDEX];
57 } else {
58 //make code simpler
59 indices.resize(vcount);
60 int *iw = indices.ptrw();
61 for (int i = 0; i < vcount; i++) {
62 iw[i] = i;
63 }
64 }
65
66 int icount = indices.size();
67 const int *r = indices.ptr();
68
69 ERR_FAIL_COND_V(icount == 0, ERR_INVALID_PARAMETER);
70 ERR_FAIL_COND_V(icount % 3, ERR_INVALID_PARAMETER);
71 for (int i = 0; i < icount; i++) {
72 ERR_FAIL_INDEX_V(r[i], vcount, ERR_INVALID_PARAMETER);
73 }
74
75 clear();
76 format = p_mesh->surface_get_format(p_surface);
77 material = p_mesh->surface_get_material(p_surface);
78
79 const Vector3 *vr = varray.ptr();
80
81 const Vector3 *nr = nullptr;
82 if (arrays[Mesh::ARRAY_NORMAL].get_type() != Variant::NIL) {
83 nr = arrays[Mesh::ARRAY_NORMAL].operator Vector<Vector3>().ptr();
84 }
85
86 const real_t *ta = nullptr;
87 if (arrays[Mesh::ARRAY_TANGENT].get_type() != Variant::NIL) {
88 ta = arrays[Mesh::ARRAY_TANGENT].operator Vector<real_t>().ptr();
89 }
90
91 const Vector2 *uv = nullptr;
92 if (arrays[Mesh::ARRAY_TEX_UV].get_type() != Variant::NIL) {
93 uv = arrays[Mesh::ARRAY_TEX_UV].operator Vector<Vector2>().ptr();
94 }
95 const Vector2 *uv2 = nullptr;
96 if (arrays[Mesh::ARRAY_TEX_UV2].get_type() != Variant::NIL) {
97 uv2 = arrays[Mesh::ARRAY_TEX_UV2].operator Vector<Vector2>().ptr();
98 }
99
100 const Color *col = nullptr;
101 if (arrays[Mesh::ARRAY_COLOR].get_type() != Variant::NIL) {
102 col = arrays[Mesh::ARRAY_COLOR].operator Vector<Color>().ptr();
103 }
104
105 const int *bo = nullptr;
106 if (arrays[Mesh::ARRAY_BONES].get_type() != Variant::NIL) {
107 bo = arrays[Mesh::ARRAY_BONES].operator Vector<int>().ptr();
108 }
109
110 const float *we = nullptr;
111 if (arrays[Mesh::ARRAY_WEIGHTS].get_type() != Variant::NIL) {
112 we = arrays[Mesh::ARRAY_WEIGHTS].operator Vector<float>().ptr();
113 }
114
115 vertices.resize(vcount);
116
117 for (int i = 0; i < vcount; i++) {
118 Vertex v;
119 v.vertex = vr[i];
120 if (nr) {
121 v.normal = nr[i];
122 }
123 if (ta) {
124 v.tangent = Plane(ta[i * 4 + 0], ta[i * 4 + 1], ta[i * 4 + 2], ta[i * 4 + 3]);
125 }
126 if (uv) {
127 v.uv = uv[i];
128 }
129 if (uv2) {
130 v.uv2 = uv2[i];
131 }
132 if (col) {
133 v.color = col[i];
134 }
135
136 if (we) {
137 v.weights.push_back(we[i * 4 + 0]);
138 v.weights.push_back(we[i * 4 + 1]);
139 v.weights.push_back(we[i * 4 + 2]);
140 v.weights.push_back(we[i * 4 + 3]);
141 }
142
143 if (bo) {
144 v.bones.push_back(bo[i * 4 + 0]);
145 v.bones.push_back(bo[i * 4 + 1]);
146 v.bones.push_back(bo[i * 4 + 2]);
147 v.bones.push_back(bo[i * 4 + 3]);
148 }
149
150 vertices.write[i] = v;
151 }
152
153 HashMap<Point2i, int> edge_indices;
154
155 for (int i = 0; i < icount; i += 3) {
156 Vertex *v[3] = { &vertices.write[r[i + 0]], &vertices.write[r[i + 1]], &vertices.write[r[i + 2]] };
157
158 int fidx = faces.size();
159 Face face;
160
161 for (int j = 0; j < 3; j++) {
162 face.v[j] = r[i + j];
163
164 Point2i edge(r[i + j], r[i + (j + 1) % 3]);
165 if (edge.x > edge.y) {
166 SWAP(edge.x, edge.y);
167 }
168
169 if (edge_indices.has(edge)) {
170 face.edges[j] = edge_indices[edge];
171
172 } else {
173 face.edges[j] = edge_indices.size();
174 edge_indices[edge] = face.edges[j];
175 Edge e;
176 e.vertex[0] = edge.x;
177 e.vertex[1] = edge.y;
178 edges.push_back(e);
179 v[j]->edges.push_back(face.edges[j]);
180 v[(j + 1) % 3]->edges.push_back(face.edges[j]);
181 }
182
183 edges.write[face.edges[j]].faces.push_back(fidx);
184 v[j]->faces.push_back(fidx);
185 }
186
187 faces.push_back(face);
188 }
189
190 return OK;
191}
192
193Error MeshDataTool::commit_to_surface(const Ref<ArrayMesh> &p_mesh) {
194 ERR_FAIL_COND_V(p_mesh.is_null(), ERR_INVALID_PARAMETER);
195 Array arr;
196 arr.resize(Mesh::ARRAY_MAX);
197
198 int vcount = vertices.size();
199
200 Vector<Vector3> v;
201 Vector<Vector3> n;
202 Vector<real_t> t;
203 Vector<Vector2> u;
204 Vector<Vector2> u2;
205 Vector<Color> c;
206 Vector<int> b;
207 Vector<real_t> w;
208 Vector<int> in;
209
210 {
211 v.resize(vcount);
212 Vector3 *vr = v.ptrw();
213
214 Vector3 *nr = nullptr;
215 if (format & Mesh::ARRAY_FORMAT_NORMAL) {
216 n.resize(vcount);
217 nr = n.ptrw();
218 }
219
220 real_t *ta = nullptr;
221 if (format & Mesh::ARRAY_FORMAT_TANGENT) {
222 t.resize(vcount * 4);
223 ta = t.ptrw();
224 }
225
226 Vector2 *uv = nullptr;
227 if (format & Mesh::ARRAY_FORMAT_TEX_UV) {
228 u.resize(vcount);
229 uv = u.ptrw();
230 }
231
232 Vector2 *uv2 = nullptr;
233 if (format & Mesh::ARRAY_FORMAT_TEX_UV2) {
234 u2.resize(vcount);
235 uv2 = u2.ptrw();
236 }
237
238 Color *col = nullptr;
239 if (format & Mesh::ARRAY_FORMAT_COLOR) {
240 c.resize(vcount);
241 col = c.ptrw();
242 }
243
244 int *bo = nullptr;
245 if (format & Mesh::ARRAY_FORMAT_BONES) {
246 b.resize(vcount * 4);
247 bo = b.ptrw();
248 }
249
250 real_t *we = nullptr;
251 if (format & Mesh::ARRAY_FORMAT_WEIGHTS) {
252 w.resize(vcount * 4);
253 we = w.ptrw();
254 }
255
256 for (int i = 0; i < vcount; i++) {
257 const Vertex &vtx = vertices[i];
258
259 vr[i] = vtx.vertex;
260 if (nr) {
261 nr[i] = vtx.normal;
262 }
263 if (ta) {
264 ta[i * 4 + 0] = vtx.tangent.normal.x;
265 ta[i * 4 + 1] = vtx.tangent.normal.y;
266 ta[i * 4 + 2] = vtx.tangent.normal.z;
267 ta[i * 4 + 3] = vtx.tangent.d;
268 }
269 if (uv) {
270 uv[i] = vtx.uv;
271 }
272 if (uv2) {
273 uv2[i] = vtx.uv2;
274 }
275 if (col) {
276 col[i] = vtx.color;
277 }
278
279 if (we) {
280 we[i * 4 + 0] = vtx.weights[0];
281 we[i * 4 + 1] = vtx.weights[1];
282 we[i * 4 + 2] = vtx.weights[2];
283 we[i * 4 + 3] = vtx.weights[3];
284 }
285
286 if (bo) {
287 bo[i * 4 + 0] = vtx.bones[0];
288 bo[i * 4 + 1] = vtx.bones[1];
289 bo[i * 4 + 2] = vtx.bones[2];
290 bo[i * 4 + 3] = vtx.bones[3];
291 }
292 }
293
294 int fc = faces.size();
295 in.resize(fc * 3);
296 int *iw = in.ptrw();
297 for (int i = 0; i < fc; i++) {
298 iw[i * 3 + 0] = faces[i].v[0];
299 iw[i * 3 + 1] = faces[i].v[1];
300 iw[i * 3 + 2] = faces[i].v[2];
301 }
302 }
303
304 arr[Mesh::ARRAY_VERTEX] = v;
305 arr[Mesh::ARRAY_INDEX] = in;
306 if (n.size()) {
307 arr[Mesh::ARRAY_NORMAL] = n;
308 }
309 if (c.size()) {
310 arr[Mesh::ARRAY_COLOR] = c;
311 }
312 if (u.size()) {
313 arr[Mesh::ARRAY_TEX_UV] = u;
314 }
315 if (u2.size()) {
316 arr[Mesh::ARRAY_TEX_UV2] = u2;
317 }
318 if (t.size()) {
319 arr[Mesh::ARRAY_TANGENT] = t;
320 }
321 if (b.size()) {
322 arr[Mesh::ARRAY_BONES] = b;
323 }
324 if (w.size()) {
325 arr[Mesh::ARRAY_WEIGHTS] = w;
326 }
327
328 Ref<ArrayMesh> ncmesh = p_mesh;
329 int sc = ncmesh->get_surface_count();
330 ncmesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, arr);
331 ncmesh->surface_set_material(sc, material);
332
333 return OK;
334}
335
336int MeshDataTool::get_format() const {
337 return format;
338}
339
340int MeshDataTool::get_vertex_count() const {
341 return vertices.size();
342}
343
344int MeshDataTool::get_edge_count() const {
345 return edges.size();
346}
347
348int MeshDataTool::get_face_count() const {
349 return faces.size();
350}
351
352Vector3 MeshDataTool::get_vertex(int p_idx) const {
353 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector3());
354 return vertices[p_idx].vertex;
355}
356
357void MeshDataTool::set_vertex(int p_idx, const Vector3 &p_vertex) {
358 ERR_FAIL_INDEX(p_idx, vertices.size());
359 vertices.write[p_idx].vertex = p_vertex;
360}
361
362Vector3 MeshDataTool::get_vertex_normal(int p_idx) const {
363 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector3());
364 return vertices[p_idx].normal;
365}
366
367void MeshDataTool::set_vertex_normal(int p_idx, const Vector3 &p_normal) {
368 ERR_FAIL_INDEX(p_idx, vertices.size());
369 vertices.write[p_idx].normal = p_normal;
370 format |= Mesh::ARRAY_FORMAT_NORMAL;
371}
372
373Plane MeshDataTool::get_vertex_tangent(int p_idx) const {
374 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Plane());
375 return vertices[p_idx].tangent;
376}
377
378void MeshDataTool::set_vertex_tangent(int p_idx, const Plane &p_tangent) {
379 ERR_FAIL_INDEX(p_idx, vertices.size());
380 vertices.write[p_idx].tangent = p_tangent;
381 format |= Mesh::ARRAY_FORMAT_TANGENT;
382}
383
384Vector2 MeshDataTool::get_vertex_uv(int p_idx) const {
385 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector2());
386 return vertices[p_idx].uv;
387}
388
389void MeshDataTool::set_vertex_uv(int p_idx, const Vector2 &p_uv) {
390 ERR_FAIL_INDEX(p_idx, vertices.size());
391 vertices.write[p_idx].uv = p_uv;
392 format |= Mesh::ARRAY_FORMAT_TEX_UV;
393}
394
395Vector2 MeshDataTool::get_vertex_uv2(int p_idx) const {
396 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector2());
397 return vertices[p_idx].uv2;
398}
399
400void MeshDataTool::set_vertex_uv2(int p_idx, const Vector2 &p_uv2) {
401 ERR_FAIL_INDEX(p_idx, vertices.size());
402 vertices.write[p_idx].uv2 = p_uv2;
403 format |= Mesh::ARRAY_FORMAT_TEX_UV2;
404}
405
406Color MeshDataTool::get_vertex_color(int p_idx) const {
407 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Color());
408 return vertices[p_idx].color;
409}
410
411void MeshDataTool::set_vertex_color(int p_idx, const Color &p_color) {
412 ERR_FAIL_INDEX(p_idx, vertices.size());
413 vertices.write[p_idx].color = p_color;
414 format |= Mesh::ARRAY_FORMAT_COLOR;
415}
416
417Vector<int> MeshDataTool::get_vertex_bones(int p_idx) const {
418 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>());
419 return vertices[p_idx].bones;
420}
421
422void MeshDataTool::set_vertex_bones(int p_idx, const Vector<int> &p_bones) {
423 ERR_FAIL_INDEX(p_idx, vertices.size());
424 ERR_FAIL_COND(p_bones.size() != 4);
425 vertices.write[p_idx].bones = p_bones;
426 format |= Mesh::ARRAY_FORMAT_BONES;
427}
428
429Vector<float> MeshDataTool::get_vertex_weights(int p_idx) const {
430 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<float>());
431 return vertices[p_idx].weights;
432}
433
434void MeshDataTool::set_vertex_weights(int p_idx, const Vector<float> &p_weights) {
435 ERR_FAIL_INDEX(p_idx, vertices.size());
436 ERR_FAIL_COND(p_weights.size() != 4);
437 vertices.write[p_idx].weights = p_weights;
438 format |= Mesh::ARRAY_FORMAT_WEIGHTS;
439}
440
441Variant MeshDataTool::get_vertex_meta(int p_idx) const {
442 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Variant());
443 return vertices[p_idx].meta;
444}
445
446void MeshDataTool::set_vertex_meta(int p_idx, const Variant &p_meta) {
447 ERR_FAIL_INDEX(p_idx, vertices.size());
448 vertices.write[p_idx].meta = p_meta;
449}
450
451Vector<int> MeshDataTool::get_vertex_edges(int p_idx) const {
452 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>());
453 return vertices[p_idx].edges;
454}
455
456Vector<int> MeshDataTool::get_vertex_faces(int p_idx) const {
457 ERR_FAIL_INDEX_V(p_idx, vertices.size(), Vector<int>());
458 return vertices[p_idx].faces;
459}
460
461int MeshDataTool::get_edge_vertex(int p_edge, int p_vertex) const {
462 ERR_FAIL_INDEX_V(p_edge, edges.size(), -1);
463 ERR_FAIL_INDEX_V(p_vertex, 2, -1);
464 return edges[p_edge].vertex[p_vertex];
465}
466
467Vector<int> MeshDataTool::get_edge_faces(int p_edge) const {
468 ERR_FAIL_INDEX_V(p_edge, edges.size(), Vector<int>());
469 return edges[p_edge].faces;
470}
471
472Variant MeshDataTool::get_edge_meta(int p_idx) const {
473 ERR_FAIL_INDEX_V(p_idx, edges.size(), Variant());
474 return edges[p_idx].meta;
475}
476
477void MeshDataTool::set_edge_meta(int p_idx, const Variant &p_meta) {
478 ERR_FAIL_INDEX(p_idx, edges.size());
479 edges.write[p_idx].meta = p_meta;
480}
481
482int MeshDataTool::get_face_vertex(int p_face, int p_vertex) const {
483 ERR_FAIL_INDEX_V(p_face, faces.size(), -1);
484 ERR_FAIL_INDEX_V(p_vertex, 3, -1);
485 return faces[p_face].v[p_vertex];
486}
487
488int MeshDataTool::get_face_edge(int p_face, int p_vertex) const {
489 ERR_FAIL_INDEX_V(p_face, faces.size(), -1);
490 ERR_FAIL_INDEX_V(p_vertex, 3, -1);
491 return faces[p_face].edges[p_vertex];
492}
493
494Variant MeshDataTool::get_face_meta(int p_face) const {
495 ERR_FAIL_INDEX_V(p_face, faces.size(), Variant());
496 return faces[p_face].meta;
497}
498
499void MeshDataTool::set_face_meta(int p_face, const Variant &p_meta) {
500 ERR_FAIL_INDEX(p_face, faces.size());
501 faces.write[p_face].meta = p_meta;
502}
503
504Vector3 MeshDataTool::get_face_normal(int p_face) const {
505 ERR_FAIL_INDEX_V(p_face, faces.size(), Vector3());
506 Vector3 v0 = vertices[faces[p_face].v[0]].vertex;
507 Vector3 v1 = vertices[faces[p_face].v[1]].vertex;
508 Vector3 v2 = vertices[faces[p_face].v[2]].vertex;
509
510 return Plane(v0, v1, v2).normal;
511}
512
513Ref<Material> MeshDataTool::get_material() const {
514 return material;
515}
516
517void MeshDataTool::set_material(const Ref<Material> &p_material) {
518 material = p_material;
519}
520
521void MeshDataTool::_bind_methods() {
522 ClassDB::bind_method(D_METHOD("clear"), &MeshDataTool::clear);
523 ClassDB::bind_method(D_METHOD("create_from_surface", "mesh", "surface"), &MeshDataTool::create_from_surface);
524 ClassDB::bind_method(D_METHOD("commit_to_surface", "mesh"), &MeshDataTool::commit_to_surface);
525
526 ClassDB::bind_method(D_METHOD("get_format"), &MeshDataTool::get_format);
527
528 ClassDB::bind_method(D_METHOD("get_vertex_count"), &MeshDataTool::get_vertex_count);
529 ClassDB::bind_method(D_METHOD("get_edge_count"), &MeshDataTool::get_edge_count);
530 ClassDB::bind_method(D_METHOD("get_face_count"), &MeshDataTool::get_face_count);
531
532 ClassDB::bind_method(D_METHOD("set_vertex", "idx", "vertex"), &MeshDataTool::set_vertex);
533 ClassDB::bind_method(D_METHOD("get_vertex", "idx"), &MeshDataTool::get_vertex);
534
535 ClassDB::bind_method(D_METHOD("set_vertex_normal", "idx", "normal"), &MeshDataTool::set_vertex_normal);
536 ClassDB::bind_method(D_METHOD("get_vertex_normal", "idx"), &MeshDataTool::get_vertex_normal);
537
538 ClassDB::bind_method(D_METHOD("set_vertex_tangent", "idx", "tangent"), &MeshDataTool::set_vertex_tangent);
539 ClassDB::bind_method(D_METHOD("get_vertex_tangent", "idx"), &MeshDataTool::get_vertex_tangent);
540
541 ClassDB::bind_method(D_METHOD("set_vertex_uv", "idx", "uv"), &MeshDataTool::set_vertex_uv);
542 ClassDB::bind_method(D_METHOD("get_vertex_uv", "idx"), &MeshDataTool::get_vertex_uv);
543
544 ClassDB::bind_method(D_METHOD("set_vertex_uv2", "idx", "uv2"), &MeshDataTool::set_vertex_uv2);
545 ClassDB::bind_method(D_METHOD("get_vertex_uv2", "idx"), &MeshDataTool::get_vertex_uv2);
546
547 ClassDB::bind_method(D_METHOD("set_vertex_color", "idx", "color"), &MeshDataTool::set_vertex_color);
548 ClassDB::bind_method(D_METHOD("get_vertex_color", "idx"), &MeshDataTool::get_vertex_color);
549
550 ClassDB::bind_method(D_METHOD("set_vertex_bones", "idx", "bones"), &MeshDataTool::set_vertex_bones);
551 ClassDB::bind_method(D_METHOD("get_vertex_bones", "idx"), &MeshDataTool::get_vertex_bones);
552
553 ClassDB::bind_method(D_METHOD("set_vertex_weights", "idx", "weights"), &MeshDataTool::set_vertex_weights);
554 ClassDB::bind_method(D_METHOD("get_vertex_weights", "idx"), &MeshDataTool::get_vertex_weights);
555
556 ClassDB::bind_method(D_METHOD("set_vertex_meta", "idx", "meta"), &MeshDataTool::set_vertex_meta);
557 ClassDB::bind_method(D_METHOD("get_vertex_meta", "idx"), &MeshDataTool::get_vertex_meta);
558
559 ClassDB::bind_method(D_METHOD("get_vertex_edges", "idx"), &MeshDataTool::get_vertex_edges);
560 ClassDB::bind_method(D_METHOD("get_vertex_faces", "idx"), &MeshDataTool::get_vertex_faces);
561
562 ClassDB::bind_method(D_METHOD("get_edge_vertex", "idx", "vertex"), &MeshDataTool::get_edge_vertex);
563 ClassDB::bind_method(D_METHOD("get_edge_faces", "idx"), &MeshDataTool::get_edge_faces);
564
565 ClassDB::bind_method(D_METHOD("set_edge_meta", "idx", "meta"), &MeshDataTool::set_edge_meta);
566 ClassDB::bind_method(D_METHOD("get_edge_meta", "idx"), &MeshDataTool::get_edge_meta);
567
568 ClassDB::bind_method(D_METHOD("get_face_vertex", "idx", "vertex"), &MeshDataTool::get_face_vertex);
569 ClassDB::bind_method(D_METHOD("get_face_edge", "idx", "edge"), &MeshDataTool::get_face_edge);
570
571 ClassDB::bind_method(D_METHOD("set_face_meta", "idx", "meta"), &MeshDataTool::set_face_meta);
572 ClassDB::bind_method(D_METHOD("get_face_meta", "idx"), &MeshDataTool::get_face_meta);
573
574 ClassDB::bind_method(D_METHOD("get_face_normal", "idx"), &MeshDataTool::get_face_normal);
575
576 ClassDB::bind_method(D_METHOD("set_material", "material"), &MeshDataTool::set_material);
577 ClassDB::bind_method(D_METHOD("get_material"), &MeshDataTool::get_material);
578}
579
580MeshDataTool::MeshDataTool() {
581 clear();
582}
583