Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/resources/3d/primitive_meshes.h
21793 views
1
/**************************************************************************/
2
/* primitive_meshes.h */
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
#pragma once
32
33
#include "scene/resources/curve.h"
34
#include "scene/resources/font.h"
35
#include "scene/resources/mesh.h"
36
#include "servers/text/text_server.h"
37
38
///@TODO probably should change a few integers to unsigned integers...
39
40
/**
41
Base class for all the classes in this file, handles a number of code functions that are shared among all meshes.
42
This class is set apart that it assumes a single surface is always generated for our mesh.
43
*/
44
45
class PrimitiveMesh : public Mesh {
46
GDCLASS(PrimitiveMesh, Mesh);
47
48
private:
49
RID mesh;
50
mutable AABB aabb;
51
AABB custom_aabb;
52
53
mutable int array_len = 0;
54
mutable int index_array_len = 0;
55
56
Ref<Material> material;
57
bool flip_faces = false;
58
59
bool add_uv2 = false;
60
float uv2_padding = 2.0;
61
62
// make sure we do an update after we've finished constructing our object
63
mutable bool pending_request = true;
64
void _update() const;
65
66
protected:
67
// assume primitive triangles as the type, correct for all but one and it will change this :)
68
Mesh::PrimitiveType primitive_type = Mesh::PRIMITIVE_TRIANGLES;
69
70
// Copy of our texel_size project setting.
71
float texel_size = 0.2;
72
73
static void _bind_methods();
74
75
virtual void _create_mesh_array(Array &p_arr) const {}
76
GDVIRTUAL0RC(Array, _create_mesh_array)
77
78
Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;
79
float get_lightmap_texel_size() const;
80
virtual void _update_lightmap_size() {}
81
82
void _on_settings_changed();
83
84
public:
85
virtual int get_surface_count() const override;
86
virtual int surface_get_array_len(int p_idx) const override;
87
virtual int surface_get_array_index_len(int p_idx) const override;
88
virtual Array surface_get_arrays(int p_surface) const override;
89
virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override;
90
virtual Dictionary surface_get_lods(int p_surface) const override;
91
virtual BitField<ArrayFormat> surface_get_format(int p_idx) const override;
92
virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const override;
93
virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;
94
virtual Ref<Material> surface_get_material(int p_idx) const override;
95
virtual int get_blend_shape_count() const override;
96
virtual StringName get_blend_shape_name(int p_index) const override;
97
virtual void set_blend_shape_name(int p_index, const StringName &p_name) override;
98
virtual AABB get_aabb() const override;
99
virtual RID get_rid() const override;
100
101
void set_material(const Ref<Material> &p_material);
102
Ref<Material> get_material() const;
103
104
Array get_mesh_arrays() const;
105
106
void set_custom_aabb(const AABB &p_custom);
107
AABB get_custom_aabb() const;
108
109
void set_flip_faces(bool p_enable);
110
bool get_flip_faces() const;
111
112
void set_add_uv2(bool p_enable);
113
bool get_add_uv2() const { return add_uv2; }
114
115
void set_uv2_padding(float p_padding);
116
float get_uv2_padding() const { return uv2_padding; }
117
118
void request_update();
119
120
PrimitiveMesh();
121
~PrimitiveMesh();
122
};
123
124
/**
125
Mesh for a simple capsule
126
*/
127
class CapsuleMesh : public PrimitiveMesh {
128
GDCLASS(CapsuleMesh, PrimitiveMesh);
129
130
private:
131
float radius = 0.5;
132
float height = 2.0;
133
int radial_segments = 64;
134
int rings = 8;
135
136
protected:
137
static void _bind_methods();
138
virtual void _create_mesh_array(Array &p_arr) const override;
139
140
virtual void _update_lightmap_size() override;
141
142
public:
143
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 8, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
144
145
void set_radius(const float p_radius);
146
float get_radius() const;
147
148
void set_height(const float p_height);
149
float get_height() const;
150
151
void set_radial_segments(const int p_segments);
152
int get_radial_segments() const;
153
154
void set_rings(const int p_rings);
155
int get_rings() const;
156
};
157
158
/**
159
A box
160
*/
161
class BoxMesh : public PrimitiveMesh {
162
GDCLASS(BoxMesh, PrimitiveMesh);
163
164
private:
165
Vector3 size = Vector3(1, 1, 1);
166
int subdivide_w = 0;
167
int subdivide_h = 0;
168
int subdivide_d = 0;
169
170
protected:
171
static void _bind_methods();
172
virtual void _create_mesh_array(Array &p_arr) const override;
173
174
virtual void _update_lightmap_size() override;
175
176
public:
177
static void create_mesh_array(Array &p_arr, Vector3 size, int subdivide_w = 0, int subdivide_h = 0, int subdivide_d = 0, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
178
179
void set_size(const Vector3 &p_size);
180
Vector3 get_size() const;
181
182
void set_subdivide_width(const int p_divisions);
183
int get_subdivide_width() const;
184
185
void set_subdivide_height(const int p_divisions);
186
int get_subdivide_height() const;
187
188
void set_subdivide_depth(const int p_divisions);
189
int get_subdivide_depth() const;
190
};
191
192
/**
193
A cylinder
194
*/
195
196
class CylinderMesh : public PrimitiveMesh {
197
GDCLASS(CylinderMesh, PrimitiveMesh);
198
199
private:
200
float top_radius = 0.5;
201
float bottom_radius = 0.5;
202
float height = 2.0;
203
int radial_segments = 64;
204
int rings = 4;
205
bool cap_top = true;
206
bool cap_bottom = true;
207
208
protected:
209
static void _bind_methods();
210
virtual void _create_mesh_array(Array &p_arr) const override;
211
212
virtual void _update_lightmap_size() override;
213
214
public:
215
static void create_mesh_array(Array &p_arr, float top_radius, float bottom_radius, float height, int radial_segments = 64, int rings = 4, bool cap_top = true, bool cap_bottom = true, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
216
217
void set_top_radius(const float p_radius);
218
float get_top_radius() const;
219
220
void set_bottom_radius(const float p_radius);
221
float get_bottom_radius() const;
222
223
void set_height(const float p_height);
224
float get_height() const;
225
226
void set_radial_segments(const int p_segments);
227
int get_radial_segments() const;
228
229
void set_rings(const int p_rings);
230
int get_rings() const;
231
232
void set_cap_top(bool p_cap_top);
233
bool is_cap_top() const;
234
235
void set_cap_bottom(bool p_cap_bottom);
236
bool is_cap_bottom() const;
237
};
238
239
/*
240
A flat rectangle, can be used as quad or heightmap.
241
*/
242
class PlaneMesh : public PrimitiveMesh {
243
GDCLASS(PlaneMesh, PrimitiveMesh);
244
245
public:
246
enum Orientation {
247
FACE_X,
248
FACE_Y,
249
FACE_Z,
250
};
251
252
private:
253
Size2 size = Size2(2.0, 2.0);
254
int subdivide_w = 0;
255
int subdivide_d = 0;
256
Vector3 center_offset;
257
Orientation orientation = FACE_Y;
258
259
protected:
260
static void _bind_methods();
261
virtual void _create_mesh_array(Array &p_arr) const override;
262
263
virtual void _update_lightmap_size() override;
264
265
public:
266
void set_size(const Size2 &p_size);
267
Size2 get_size() const;
268
269
void set_subdivide_width(const int p_divisions);
270
int get_subdivide_width() const;
271
272
void set_subdivide_depth(const int p_divisions);
273
int get_subdivide_depth() const;
274
275
void set_center_offset(const Vector3 p_offset);
276
Vector3 get_center_offset() const;
277
278
void set_orientation(const Orientation p_orientation);
279
Orientation get_orientation() const;
280
};
281
282
VARIANT_ENUM_CAST(PlaneMesh::Orientation)
283
284
/*
285
A flat rectangle, inherits from PlaneMesh but defaults to facing the Z-plane.
286
*/
287
class QuadMesh : public PlaneMesh {
288
GDCLASS(QuadMesh, PlaneMesh);
289
290
public:
291
QuadMesh() {
292
set_orientation(FACE_Z);
293
set_size(Size2(1, 1));
294
}
295
};
296
297
/**
298
A prism shapen, handy for ramps, triangles, etc.
299
*/
300
class PrismMesh : public PrimitiveMesh {
301
GDCLASS(PrismMesh, PrimitiveMesh);
302
303
private:
304
float left_to_right = 0.5;
305
Vector3 size = Vector3(1.0, 1.0, 1.0);
306
int subdivide_w = 0;
307
int subdivide_h = 0;
308
int subdivide_d = 0;
309
310
protected:
311
static void _bind_methods();
312
virtual void _create_mesh_array(Array &p_arr) const override;
313
314
virtual void _update_lightmap_size() override;
315
316
public:
317
void set_left_to_right(const float p_left_to_right);
318
float get_left_to_right() const;
319
320
void set_size(const Vector3 &p_size);
321
Vector3 get_size() const;
322
323
void set_subdivide_width(const int p_divisions);
324
int get_subdivide_width() const;
325
326
void set_subdivide_height(const int p_divisions);
327
int get_subdivide_height() const;
328
329
void set_subdivide_depth(const int p_divisions);
330
int get_subdivide_depth() const;
331
};
332
333
/**
334
A sphere..
335
*/
336
class SphereMesh : public PrimitiveMesh {
337
GDCLASS(SphereMesh, PrimitiveMesh);
338
339
private:
340
float radius = 0.5;
341
float height = 1.0;
342
int radial_segments = 64;
343
int rings = 32;
344
bool is_hemisphere = false;
345
346
protected:
347
static void _bind_methods();
348
virtual void _create_mesh_array(Array &p_arr) const override;
349
350
virtual void _update_lightmap_size() override;
351
352
public:
353
static void create_mesh_array(Array &p_arr, float radius, float height, int radial_segments = 64, int rings = 32, bool is_hemisphere = false, bool p_add_uv2 = false, const float p_uv2_padding = 1.0);
354
355
void set_radius(const float p_radius);
356
float get_radius() const;
357
358
void set_height(const float p_height);
359
float get_height() const;
360
361
void set_radial_segments(const int p_radial_segments);
362
int get_radial_segments() const;
363
364
void set_rings(const int p_rings);
365
int get_rings() const;
366
367
void set_is_hemisphere(const bool p_is_hemisphere);
368
bool get_is_hemisphere() const;
369
};
370
371
/**
372
Big donut
373
*/
374
class TorusMesh : public PrimitiveMesh {
375
GDCLASS(TorusMesh, PrimitiveMesh);
376
377
private:
378
float inner_radius = 0.5;
379
float outer_radius = 1.0;
380
int rings = 64;
381
int ring_segments = 32;
382
383
protected:
384
static void _bind_methods();
385
virtual void _create_mesh_array(Array &p_arr) const override;
386
387
virtual void _update_lightmap_size() override;
388
389
public:
390
void set_inner_radius(const float p_inner_radius);
391
float get_inner_radius() const;
392
393
void set_outer_radius(const float p_outer_radius);
394
float get_outer_radius() const;
395
396
void set_rings(const int p_rings);
397
int get_rings() const;
398
399
void set_ring_segments(const int p_ring_segments);
400
int get_ring_segments() const;
401
};
402
403
/**
404
A single point for use in particle systems
405
*/
406
407
class PointMesh : public PrimitiveMesh {
408
GDCLASS(PointMesh, PrimitiveMesh)
409
410
protected:
411
virtual void _create_mesh_array(Array &p_arr) const override;
412
413
public:
414
PointMesh();
415
};
416
417
class TubeTrailMesh : public PrimitiveMesh {
418
GDCLASS(TubeTrailMesh, PrimitiveMesh);
419
420
private:
421
float radius = 0.5;
422
int radial_steps = 8;
423
int sections = 5;
424
float section_length = 0.2;
425
int section_rings = 3;
426
bool cap_top = true;
427
bool cap_bottom = true;
428
429
Ref<Curve> curve;
430
431
void _curve_changed();
432
433
protected:
434
static void _bind_methods();
435
virtual void _create_mesh_array(Array &p_arr) const override;
436
437
public:
438
void set_radius(const float p_radius);
439
float get_radius() const;
440
441
void set_radial_steps(const int p_radial_steps);
442
int get_radial_steps() const;
443
444
void set_sections(const int p_sections);
445
int get_sections() const;
446
447
void set_section_length(float p_sectionlength);
448
float get_section_length() const;
449
450
void set_section_rings(const int p_section_rings);
451
int get_section_rings() const;
452
453
void set_cap_top(bool p_cap_top);
454
bool is_cap_top() const;
455
456
void set_cap_bottom(bool p_cap_bottom);
457
bool is_cap_bottom() const;
458
459
void set_curve(const Ref<Curve> &p_curve);
460
Ref<Curve> get_curve() const;
461
462
virtual int get_builtin_bind_pose_count() const override;
463
virtual Transform3D get_builtin_bind_pose(int p_index) const override;
464
465
TubeTrailMesh();
466
};
467
468
class RibbonTrailMesh : public PrimitiveMesh {
469
GDCLASS(RibbonTrailMesh, PrimitiveMesh);
470
471
public:
472
enum Shape {
473
SHAPE_FLAT,
474
SHAPE_CROSS
475
};
476
477
private:
478
float size = 1.0;
479
int sections = 5;
480
float section_length = 0.2;
481
int section_segments = 3;
482
483
Shape shape = SHAPE_CROSS;
484
485
Ref<Curve> curve;
486
487
void _curve_changed();
488
489
protected:
490
static void _bind_methods();
491
virtual void _create_mesh_array(Array &p_arr) const override;
492
493
public:
494
void set_shape(Shape p_shape);
495
Shape get_shape() const;
496
497
void set_size(const float p_size);
498
float get_size() const;
499
500
void set_sections(const int p_sections);
501
int get_sections() const;
502
503
void set_section_length(float p_sectionlength);
504
float get_section_length() const;
505
506
void set_section_segments(const int p_section_segments);
507
int get_section_segments() const;
508
509
void set_curve(const Ref<Curve> &p_curve);
510
Ref<Curve> get_curve() const;
511
512
virtual int get_builtin_bind_pose_count() const override;
513
virtual Transform3D get_builtin_bind_pose(int p_index) const override;
514
515
RibbonTrailMesh();
516
};
517
518
/**
519
Text...
520
*/
521
522
class TextMesh : public PrimitiveMesh {
523
GDCLASS(TextMesh, PrimitiveMesh);
524
525
private:
526
struct ContourPoint {
527
Vector2 point;
528
bool sharp = false;
529
530
ContourPoint() {}
531
ContourPoint(const Vector2 &p_pt, bool p_sharp) {
532
point = p_pt;
533
sharp = p_sharp;
534
}
535
};
536
537
struct ContourInfo {
538
real_t length = 0.0;
539
bool ccw = true;
540
ContourInfo() {}
541
ContourInfo(real_t p_len, bool p_ccw) {
542
length = p_len;
543
ccw = p_ccw;
544
}
545
};
546
547
struct GlyphMeshKey {
548
uint64_t font_id;
549
uint32_t gl_id;
550
551
bool operator==(const GlyphMeshKey &p_b) const {
552
return (font_id == p_b.font_id) && (gl_id == p_b.gl_id);
553
}
554
555
GlyphMeshKey(uint64_t p_font_id, uint32_t p_gl_id) {
556
font_id = p_font_id;
557
gl_id = p_gl_id;
558
}
559
};
560
561
struct GlyphMeshKeyHasher {
562
_FORCE_INLINE_ static uint32_t hash(const GlyphMeshKey &p_a) {
563
return hash_murmur3_buffer(&p_a, sizeof(GlyphMeshKey));
564
}
565
};
566
567
struct GlyphMeshData {
568
Vector<Vector2> triangles;
569
Vector<Vector<ContourPoint>> contours;
570
Vector<ContourInfo> contours_info;
571
Vector2 min_p = Vector2(Math::INF, Math::INF);
572
Vector2 max_p = Vector2(-Math::INF, -Math::INF);
573
};
574
mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache;
575
576
RID text_rid;
577
mutable Vector<RID> lines_rid;
578
579
String text;
580
String xl_text;
581
582
int font_size = 16;
583
Ref<Font> font_override;
584
585
TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;
586
BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;
587
float width = 500.0;
588
float line_spacing = 0.f;
589
Point2 lbl_offset;
590
591
HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;
592
VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;
593
bool uppercase = false;
594
String language;
595
TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;
596
TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;
597
Array st_args;
598
599
real_t depth = 0.05;
600
real_t pixel_size = 0.01;
601
real_t curve_step = 0.5;
602
603
mutable bool dirty_lines = true;
604
mutable bool dirty_text = true;
605
mutable bool dirty_font = true;
606
mutable bool dirty_cache = true;
607
608
void _generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_glyph) const;
609
void _font_changed();
610
611
protected:
612
static void _bind_methods();
613
void _notification(int p_what);
614
615
virtual void _create_mesh_array(Array &p_arr) const override;
616
617
public:
618
GDVIRTUAL2RC(TypedArray<Vector3i>, _structured_text_parser, Array, String)
619
620
TextMesh();
621
~TextMesh();
622
623
void set_horizontal_alignment(HorizontalAlignment p_alignment);
624
HorizontalAlignment get_horizontal_alignment() const;
625
626
void set_vertical_alignment(VerticalAlignment p_alignment);
627
VerticalAlignment get_vertical_alignment() const;
628
629
void set_text(const String &p_string);
630
String get_text() const;
631
632
void set_font(const Ref<Font> &p_font);
633
Ref<Font> get_font() const;
634
Ref<Font> _get_font_or_default() const;
635
636
void set_font_size(int p_size);
637
int get_font_size() const;
638
639
void set_line_spacing(float p_size);
640
float get_line_spacing() const;
641
642
void set_autowrap_mode(TextServer::AutowrapMode p_mode);
643
TextServer::AutowrapMode get_autowrap_mode() const;
644
645
void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);
646
BitField<TextServer::JustificationFlag> get_justification_flags() const;
647
648
void set_text_direction(TextServer::Direction p_text_direction);
649
TextServer::Direction get_text_direction() const;
650
651
void set_language(const String &p_language);
652
String get_language() const;
653
654
void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);
655
TextServer::StructuredTextParser get_structured_text_bidi_override() const;
656
657
void set_structured_text_bidi_override_options(const Array &p_args);
658
Array get_structured_text_bidi_override_options() const;
659
660
void set_uppercase(bool p_uppercase);
661
bool is_uppercase() const;
662
663
void set_width(real_t p_width);
664
real_t get_width() const;
665
666
void set_depth(real_t p_depth);
667
real_t get_depth() const;
668
669
void set_curve_step(real_t p_step);
670
real_t get_curve_step() const;
671
672
void set_pixel_size(real_t p_amount);
673
real_t get_pixel_size() const;
674
675
void set_offset(const Point2 &p_offset);
676
Point2 get_offset() const;
677
};
678
679
VARIANT_ENUM_CAST(RibbonTrailMesh::Shape)
680
681