Path: blob/master/scene/resources/3d/primitive_meshes.h
9898 views
/**************************************************************************/1/* primitive_meshes.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "scene/resources/font.h"33#include "scene/resources/mesh.h"34#include "servers/text_server.h"3536///@TODO probably should change a few integers to unsigned integers...3738/**39Base class for all the classes in this file, handles a number of code functions that are shared among all meshes.40This class is set apart that it assumes a single surface is always generated for our mesh.41*/4243class PrimitiveMesh : public Mesh {44GDCLASS(PrimitiveMesh, Mesh);4546private:47RID mesh;48mutable AABB aabb;49AABB custom_aabb;5051mutable int array_len = 0;52mutable int index_array_len = 0;5354Ref<Material> material;55bool flip_faces = false;5657bool add_uv2 = false;58float uv2_padding = 2.0;5960// make sure we do an update after we've finished constructing our object61mutable bool pending_request = true;62void _update() const;6364protected:65// assume primitive triangles as the type, correct for all but one and it will change this :)66Mesh::PrimitiveType primitive_type = Mesh::PRIMITIVE_TRIANGLES;6768// Copy of our texel_size project setting.69float texel_size = 0.2;7071static void _bind_methods();7273virtual void _create_mesh_array(Array &p_arr) const {}74GDVIRTUAL0RC(Array, _create_mesh_array)7576Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;77float get_lightmap_texel_size() const;78virtual void _update_lightmap_size() {}7980void _on_settings_changed();8182public:83virtual int get_surface_count() const override;84virtual int surface_get_array_len(int p_idx) const override;85virtual int surface_get_array_index_len(int p_idx) const override;86virtual Array surface_get_arrays(int p_surface) const override;87virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override;88virtual Dictionary surface_get_lods(int p_surface) const override;89virtual BitField<ArrayFormat> surface_get_format(int p_idx) const override;90virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const override;91virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;92virtual Ref<Material> surface_get_material(int p_idx) const override;93virtual int get_blend_shape_count() const override;94virtual StringName get_blend_shape_name(int p_index) const override;95virtual void set_blend_shape_name(int p_index, const StringName &p_name) override;96virtual AABB get_aabb() const override;97virtual RID get_rid() const override;9899void set_material(const Ref<Material> &p_material);100Ref<Material> get_material() const;101102Array get_mesh_arrays() const;103104void set_custom_aabb(const AABB &p_custom);105AABB get_custom_aabb() const;106107void set_flip_faces(bool p_enable);108bool get_flip_faces() const;109110void set_add_uv2(bool p_enable);111bool get_add_uv2() const { return add_uv2; }112113void set_uv2_padding(float p_padding);114float get_uv2_padding() const { return uv2_padding; }115116void request_update();117118PrimitiveMesh();119~PrimitiveMesh();120};121122/**123Mesh for a simple capsule124*/125class CapsuleMesh : public PrimitiveMesh {126GDCLASS(CapsuleMesh, PrimitiveMesh);127128private:129float radius = 0.5;130float height = 2.0;131int radial_segments = 64;132int rings = 8;133134protected:135static void _bind_methods();136virtual void _create_mesh_array(Array &p_arr) const override;137138virtual void _update_lightmap_size() override;139140public:141static 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);142143void set_radius(const float p_radius);144float get_radius() const;145146void set_height(const float p_height);147float get_height() const;148149void set_radial_segments(const int p_segments);150int get_radial_segments() const;151152void set_rings(const int p_rings);153int get_rings() const;154};155156/**157A box158*/159class BoxMesh : public PrimitiveMesh {160GDCLASS(BoxMesh, PrimitiveMesh);161162private:163Vector3 size = Vector3(1, 1, 1);164int subdivide_w = 0;165int subdivide_h = 0;166int subdivide_d = 0;167168protected:169static void _bind_methods();170virtual void _create_mesh_array(Array &p_arr) const override;171172virtual void _update_lightmap_size() override;173174public:175static 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);176177void set_size(const Vector3 &p_size);178Vector3 get_size() const;179180void set_subdivide_width(const int p_divisions);181int get_subdivide_width() const;182183void set_subdivide_height(const int p_divisions);184int get_subdivide_height() const;185186void set_subdivide_depth(const int p_divisions);187int get_subdivide_depth() const;188};189190/**191A cylinder192*/193194class CylinderMesh : public PrimitiveMesh {195GDCLASS(CylinderMesh, PrimitiveMesh);196197private:198float top_radius = 0.5;199float bottom_radius = 0.5;200float height = 2.0;201int radial_segments = 64;202int rings = 4;203bool cap_top = true;204bool cap_bottom = true;205206protected:207static void _bind_methods();208virtual void _create_mesh_array(Array &p_arr) const override;209210virtual void _update_lightmap_size() override;211212public:213static 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);214215void set_top_radius(const float p_radius);216float get_top_radius() const;217218void set_bottom_radius(const float p_radius);219float get_bottom_radius() const;220221void set_height(const float p_height);222float get_height() const;223224void set_radial_segments(const int p_segments);225int get_radial_segments() const;226227void set_rings(const int p_rings);228int get_rings() const;229230void set_cap_top(bool p_cap_top);231bool is_cap_top() const;232233void set_cap_bottom(bool p_cap_bottom);234bool is_cap_bottom() const;235};236237/*238A flat rectangle, can be used as quad or heightmap.239*/240class PlaneMesh : public PrimitiveMesh {241GDCLASS(PlaneMesh, PrimitiveMesh);242243public:244enum Orientation {245FACE_X,246FACE_Y,247FACE_Z,248};249250private:251Size2 size = Size2(2.0, 2.0);252int subdivide_w = 0;253int subdivide_d = 0;254Vector3 center_offset;255Orientation orientation = FACE_Y;256257protected:258static void _bind_methods();259virtual void _create_mesh_array(Array &p_arr) const override;260261virtual void _update_lightmap_size() override;262263public:264void set_size(const Size2 &p_size);265Size2 get_size() const;266267void set_subdivide_width(const int p_divisions);268int get_subdivide_width() const;269270void set_subdivide_depth(const int p_divisions);271int get_subdivide_depth() const;272273void set_center_offset(const Vector3 p_offset);274Vector3 get_center_offset() const;275276void set_orientation(const Orientation p_orientation);277Orientation get_orientation() const;278};279280VARIANT_ENUM_CAST(PlaneMesh::Orientation)281282/*283A flat rectangle, inherits from PlaneMesh but defaults to facing the Z-plane.284*/285class QuadMesh : public PlaneMesh {286GDCLASS(QuadMesh, PlaneMesh);287288public:289QuadMesh() {290set_orientation(FACE_Z);291set_size(Size2(1, 1));292}293};294295/**296A prism shapen, handy for ramps, triangles, etc.297*/298class PrismMesh : public PrimitiveMesh {299GDCLASS(PrismMesh, PrimitiveMesh);300301private:302float left_to_right = 0.5;303Vector3 size = Vector3(1.0, 1.0, 1.0);304int subdivide_w = 0;305int subdivide_h = 0;306int subdivide_d = 0;307308protected:309static void _bind_methods();310virtual void _create_mesh_array(Array &p_arr) const override;311312virtual void _update_lightmap_size() override;313314public:315void set_left_to_right(const float p_left_to_right);316float get_left_to_right() const;317318void set_size(const Vector3 &p_size);319Vector3 get_size() const;320321void set_subdivide_width(const int p_divisions);322int get_subdivide_width() const;323324void set_subdivide_height(const int p_divisions);325int get_subdivide_height() const;326327void set_subdivide_depth(const int p_divisions);328int get_subdivide_depth() const;329};330331/**332A sphere..333*/334class SphereMesh : public PrimitiveMesh {335GDCLASS(SphereMesh, PrimitiveMesh);336337private:338float radius = 0.5;339float height = 1.0;340int radial_segments = 64;341int rings = 32;342bool is_hemisphere = false;343344protected:345static void _bind_methods();346virtual void _create_mesh_array(Array &p_arr) const override;347348virtual void _update_lightmap_size() override;349350public:351static 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);352353void set_radius(const float p_radius);354float get_radius() const;355356void set_height(const float p_height);357float get_height() const;358359void set_radial_segments(const int p_radial_segments);360int get_radial_segments() const;361362void set_rings(const int p_rings);363int get_rings() const;364365void set_is_hemisphere(const bool p_is_hemisphere);366bool get_is_hemisphere() const;367};368369/**370Big donut371*/372class TorusMesh : public PrimitiveMesh {373GDCLASS(TorusMesh, PrimitiveMesh);374375private:376float inner_radius = 0.5;377float outer_radius = 1.0;378int rings = 64;379int ring_segments = 32;380381protected:382static void _bind_methods();383virtual void _create_mesh_array(Array &p_arr) const override;384385virtual void _update_lightmap_size() override;386387public:388void set_inner_radius(const float p_inner_radius);389float get_inner_radius() const;390391void set_outer_radius(const float p_outer_radius);392float get_outer_radius() const;393394void set_rings(const int p_rings);395int get_rings() const;396397void set_ring_segments(const int p_ring_segments);398int get_ring_segments() const;399};400401/**402A single point for use in particle systems403*/404405class PointMesh : public PrimitiveMesh {406GDCLASS(PointMesh, PrimitiveMesh)407408protected:409virtual void _create_mesh_array(Array &p_arr) const override;410411public:412PointMesh();413};414415class TubeTrailMesh : public PrimitiveMesh {416GDCLASS(TubeTrailMesh, PrimitiveMesh);417418private:419float radius = 0.5;420int radial_steps = 8;421int sections = 5;422float section_length = 0.2;423int section_rings = 3;424bool cap_top = true;425bool cap_bottom = true;426427Ref<Curve> curve;428429void _curve_changed();430431protected:432static void _bind_methods();433virtual void _create_mesh_array(Array &p_arr) const override;434435public:436void set_radius(const float p_radius);437float get_radius() const;438439void set_radial_steps(const int p_radial_steps);440int get_radial_steps() const;441442void set_sections(const int p_sections);443int get_sections() const;444445void set_section_length(float p_sectionlength);446float get_section_length() const;447448void set_section_rings(const int p_section_rings);449int get_section_rings() const;450451void set_cap_top(bool p_cap_top);452bool is_cap_top() const;453454void set_cap_bottom(bool p_cap_bottom);455bool is_cap_bottom() const;456457void set_curve(const Ref<Curve> &p_curve);458Ref<Curve> get_curve() const;459460virtual int get_builtin_bind_pose_count() const override;461virtual Transform3D get_builtin_bind_pose(int p_index) const override;462463TubeTrailMesh();464};465466class RibbonTrailMesh : public PrimitiveMesh {467GDCLASS(RibbonTrailMesh, PrimitiveMesh);468469public:470enum Shape {471SHAPE_FLAT,472SHAPE_CROSS473};474475private:476float size = 1.0;477int sections = 5;478float section_length = 0.2;479int section_segments = 3;480481Shape shape = SHAPE_CROSS;482483Ref<Curve> curve;484485void _curve_changed();486487protected:488static void _bind_methods();489virtual void _create_mesh_array(Array &p_arr) const override;490491public:492void set_shape(Shape p_shape);493Shape get_shape() const;494495void set_size(const float p_size);496float get_size() const;497498void set_sections(const int p_sections);499int get_sections() const;500501void set_section_length(float p_sectionlength);502float get_section_length() const;503504void set_section_segments(const int p_section_segments);505int get_section_segments() const;506507void set_curve(const Ref<Curve> &p_curve);508Ref<Curve> get_curve() const;509510virtual int get_builtin_bind_pose_count() const override;511virtual Transform3D get_builtin_bind_pose(int p_index) const override;512513RibbonTrailMesh();514};515516/**517Text...518*/519520class TextMesh : public PrimitiveMesh {521GDCLASS(TextMesh, PrimitiveMesh);522523private:524struct ContourPoint {525Vector2 point;526bool sharp = false;527528ContourPoint() {}529ContourPoint(const Vector2 &p_pt, bool p_sharp) {530point = p_pt;531sharp = p_sharp;532}533};534535struct ContourInfo {536real_t length = 0.0;537bool ccw = true;538ContourInfo() {}539ContourInfo(real_t p_len, bool p_ccw) {540length = p_len;541ccw = p_ccw;542}543};544545struct GlyphMeshKey {546uint64_t font_id;547uint32_t gl_id;548549bool operator==(const GlyphMeshKey &p_b) const {550return (font_id == p_b.font_id) && (gl_id == p_b.gl_id);551}552553GlyphMeshKey(uint64_t p_font_id, uint32_t p_gl_id) {554font_id = p_font_id;555gl_id = p_gl_id;556}557};558559struct GlyphMeshKeyHasher {560_FORCE_INLINE_ static uint32_t hash(const GlyphMeshKey &p_a) {561return hash_murmur3_buffer(&p_a, sizeof(GlyphMeshKey));562}563};564565struct GlyphMeshData {566Vector<Vector2> triangles;567Vector<Vector<ContourPoint>> contours;568Vector<ContourInfo> contours_info;569Vector2 min_p = Vector2(Math::INF, Math::INF);570Vector2 max_p = Vector2(-Math::INF, -Math::INF);571};572mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache;573574RID text_rid;575mutable Vector<RID> lines_rid;576577String text;578String xl_text;579580int font_size = 16;581Ref<Font> font_override;582583TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;584BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;585float width = 500.0;586float line_spacing = 0.f;587Point2 lbl_offset;588589HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;590VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;591bool uppercase = false;592String language;593TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;594TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;595Array st_args;596597real_t depth = 0.05;598real_t pixel_size = 0.01;599real_t curve_step = 0.5;600601mutable bool dirty_lines = true;602mutable bool dirty_text = true;603mutable bool dirty_font = true;604mutable bool dirty_cache = true;605606void _generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_glyph) const;607void _font_changed();608609protected:610static void _bind_methods();611void _notification(int p_what);612613virtual void _create_mesh_array(Array &p_arr) const override;614615public:616GDVIRTUAL2RC(TypedArray<Vector3i>, _structured_text_parser, Array, String)617618TextMesh();619~TextMesh();620621void set_horizontal_alignment(HorizontalAlignment p_alignment);622HorizontalAlignment get_horizontal_alignment() const;623624void set_vertical_alignment(VerticalAlignment p_alignment);625VerticalAlignment get_vertical_alignment() const;626627void set_text(const String &p_string);628String get_text() const;629630void set_font(const Ref<Font> &p_font);631Ref<Font> get_font() const;632Ref<Font> _get_font_or_default() const;633634void set_font_size(int p_size);635int get_font_size() const;636637void set_line_spacing(float p_size);638float get_line_spacing() const;639640void set_autowrap_mode(TextServer::AutowrapMode p_mode);641TextServer::AutowrapMode get_autowrap_mode() const;642643void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);644BitField<TextServer::JustificationFlag> get_justification_flags() const;645646void set_text_direction(TextServer::Direction p_text_direction);647TextServer::Direction get_text_direction() const;648649void set_language(const String &p_language);650String get_language() const;651652void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);653TextServer::StructuredTextParser get_structured_text_bidi_override() const;654655void set_structured_text_bidi_override_options(Array p_args);656Array get_structured_text_bidi_override_options() const;657658void set_uppercase(bool p_uppercase);659bool is_uppercase() const;660661void set_width(real_t p_width);662real_t get_width() const;663664void set_depth(real_t p_depth);665real_t get_depth() const;666667void set_curve_step(real_t p_step);668real_t get_curve_step() const;669670void set_pixel_size(real_t p_amount);671real_t get_pixel_size() const;672673void set_offset(const Point2 &p_offset);674Point2 get_offset() const;675};676677VARIANT_ENUM_CAST(RibbonTrailMesh::Shape)678679680