Path: blob/master/scene/resources/3d/primitive_meshes.h
21793 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/curve.h"33#include "scene/resources/font.h"34#include "scene/resources/mesh.h"35#include "servers/text/text_server.h"3637///@TODO probably should change a few integers to unsigned integers...3839/**40Base class for all the classes in this file, handles a number of code functions that are shared among all meshes.41This class is set apart that it assumes a single surface is always generated for our mesh.42*/4344class PrimitiveMesh : public Mesh {45GDCLASS(PrimitiveMesh, Mesh);4647private:48RID mesh;49mutable AABB aabb;50AABB custom_aabb;5152mutable int array_len = 0;53mutable int index_array_len = 0;5455Ref<Material> material;56bool flip_faces = false;5758bool add_uv2 = false;59float uv2_padding = 2.0;6061// make sure we do an update after we've finished constructing our object62mutable bool pending_request = true;63void _update() const;6465protected:66// assume primitive triangles as the type, correct for all but one and it will change this :)67Mesh::PrimitiveType primitive_type = Mesh::PRIMITIVE_TRIANGLES;6869// Copy of our texel_size project setting.70float texel_size = 0.2;7172static void _bind_methods();7374virtual void _create_mesh_array(Array &p_arr) const {}75GDVIRTUAL0RC(Array, _create_mesh_array)7677Vector2 get_uv2_scale(Vector2 p_margin_scale = Vector2(1.0, 1.0)) const;78float get_lightmap_texel_size() const;79virtual void _update_lightmap_size() {}8081void _on_settings_changed();8283public:84virtual int get_surface_count() const override;85virtual int surface_get_array_len(int p_idx) const override;86virtual int surface_get_array_index_len(int p_idx) const override;87virtual Array surface_get_arrays(int p_surface) const override;88virtual TypedArray<Array> surface_get_blend_shape_arrays(int p_surface) const override;89virtual Dictionary surface_get_lods(int p_surface) const override;90virtual BitField<ArrayFormat> surface_get_format(int p_idx) const override;91virtual Mesh::PrimitiveType surface_get_primitive_type(int p_idx) const override;92virtual void surface_set_material(int p_idx, const Ref<Material> &p_material) override;93virtual Ref<Material> surface_get_material(int p_idx) const override;94virtual int get_blend_shape_count() const override;95virtual StringName get_blend_shape_name(int p_index) const override;96virtual void set_blend_shape_name(int p_index, const StringName &p_name) override;97virtual AABB get_aabb() const override;98virtual RID get_rid() const override;99100void set_material(const Ref<Material> &p_material);101Ref<Material> get_material() const;102103Array get_mesh_arrays() const;104105void set_custom_aabb(const AABB &p_custom);106AABB get_custom_aabb() const;107108void set_flip_faces(bool p_enable);109bool get_flip_faces() const;110111void set_add_uv2(bool p_enable);112bool get_add_uv2() const { return add_uv2; }113114void set_uv2_padding(float p_padding);115float get_uv2_padding() const { return uv2_padding; }116117void request_update();118119PrimitiveMesh();120~PrimitiveMesh();121};122123/**124Mesh for a simple capsule125*/126class CapsuleMesh : public PrimitiveMesh {127GDCLASS(CapsuleMesh, PrimitiveMesh);128129private:130float radius = 0.5;131float height = 2.0;132int radial_segments = 64;133int rings = 8;134135protected:136static void _bind_methods();137virtual void _create_mesh_array(Array &p_arr) const override;138139virtual void _update_lightmap_size() override;140141public:142static 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);143144void set_radius(const float p_radius);145float get_radius() const;146147void set_height(const float p_height);148float get_height() const;149150void set_radial_segments(const int p_segments);151int get_radial_segments() const;152153void set_rings(const int p_rings);154int get_rings() const;155};156157/**158A box159*/160class BoxMesh : public PrimitiveMesh {161GDCLASS(BoxMesh, PrimitiveMesh);162163private:164Vector3 size = Vector3(1, 1, 1);165int subdivide_w = 0;166int subdivide_h = 0;167int subdivide_d = 0;168169protected:170static void _bind_methods();171virtual void _create_mesh_array(Array &p_arr) const override;172173virtual void _update_lightmap_size() override;174175public:176static 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);177178void set_size(const Vector3 &p_size);179Vector3 get_size() const;180181void set_subdivide_width(const int p_divisions);182int get_subdivide_width() const;183184void set_subdivide_height(const int p_divisions);185int get_subdivide_height() const;186187void set_subdivide_depth(const int p_divisions);188int get_subdivide_depth() const;189};190191/**192A cylinder193*/194195class CylinderMesh : public PrimitiveMesh {196GDCLASS(CylinderMesh, PrimitiveMesh);197198private:199float top_radius = 0.5;200float bottom_radius = 0.5;201float height = 2.0;202int radial_segments = 64;203int rings = 4;204bool cap_top = true;205bool cap_bottom = true;206207protected:208static void _bind_methods();209virtual void _create_mesh_array(Array &p_arr) const override;210211virtual void _update_lightmap_size() override;212213public:214static 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);215216void set_top_radius(const float p_radius);217float get_top_radius() const;218219void set_bottom_radius(const float p_radius);220float get_bottom_radius() const;221222void set_height(const float p_height);223float get_height() const;224225void set_radial_segments(const int p_segments);226int get_radial_segments() const;227228void set_rings(const int p_rings);229int get_rings() const;230231void set_cap_top(bool p_cap_top);232bool is_cap_top() const;233234void set_cap_bottom(bool p_cap_bottom);235bool is_cap_bottom() const;236};237238/*239A flat rectangle, can be used as quad or heightmap.240*/241class PlaneMesh : public PrimitiveMesh {242GDCLASS(PlaneMesh, PrimitiveMesh);243244public:245enum Orientation {246FACE_X,247FACE_Y,248FACE_Z,249};250251private:252Size2 size = Size2(2.0, 2.0);253int subdivide_w = 0;254int subdivide_d = 0;255Vector3 center_offset;256Orientation orientation = FACE_Y;257258protected:259static void _bind_methods();260virtual void _create_mesh_array(Array &p_arr) const override;261262virtual void _update_lightmap_size() override;263264public:265void set_size(const Size2 &p_size);266Size2 get_size() const;267268void set_subdivide_width(const int p_divisions);269int get_subdivide_width() const;270271void set_subdivide_depth(const int p_divisions);272int get_subdivide_depth() const;273274void set_center_offset(const Vector3 p_offset);275Vector3 get_center_offset() const;276277void set_orientation(const Orientation p_orientation);278Orientation get_orientation() const;279};280281VARIANT_ENUM_CAST(PlaneMesh::Orientation)282283/*284A flat rectangle, inherits from PlaneMesh but defaults to facing the Z-plane.285*/286class QuadMesh : public PlaneMesh {287GDCLASS(QuadMesh, PlaneMesh);288289public:290QuadMesh() {291set_orientation(FACE_Z);292set_size(Size2(1, 1));293}294};295296/**297A prism shapen, handy for ramps, triangles, etc.298*/299class PrismMesh : public PrimitiveMesh {300GDCLASS(PrismMesh, PrimitiveMesh);301302private:303float left_to_right = 0.5;304Vector3 size = Vector3(1.0, 1.0, 1.0);305int subdivide_w = 0;306int subdivide_h = 0;307int subdivide_d = 0;308309protected:310static void _bind_methods();311virtual void _create_mesh_array(Array &p_arr) const override;312313virtual void _update_lightmap_size() override;314315public:316void set_left_to_right(const float p_left_to_right);317float get_left_to_right() const;318319void set_size(const Vector3 &p_size);320Vector3 get_size() const;321322void set_subdivide_width(const int p_divisions);323int get_subdivide_width() const;324325void set_subdivide_height(const int p_divisions);326int get_subdivide_height() const;327328void set_subdivide_depth(const int p_divisions);329int get_subdivide_depth() const;330};331332/**333A sphere..334*/335class SphereMesh : public PrimitiveMesh {336GDCLASS(SphereMesh, PrimitiveMesh);337338private:339float radius = 0.5;340float height = 1.0;341int radial_segments = 64;342int rings = 32;343bool is_hemisphere = false;344345protected:346static void _bind_methods();347virtual void _create_mesh_array(Array &p_arr) const override;348349virtual void _update_lightmap_size() override;350351public:352static 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);353354void set_radius(const float p_radius);355float get_radius() const;356357void set_height(const float p_height);358float get_height() const;359360void set_radial_segments(const int p_radial_segments);361int get_radial_segments() const;362363void set_rings(const int p_rings);364int get_rings() const;365366void set_is_hemisphere(const bool p_is_hemisphere);367bool get_is_hemisphere() const;368};369370/**371Big donut372*/373class TorusMesh : public PrimitiveMesh {374GDCLASS(TorusMesh, PrimitiveMesh);375376private:377float inner_radius = 0.5;378float outer_radius = 1.0;379int rings = 64;380int ring_segments = 32;381382protected:383static void _bind_methods();384virtual void _create_mesh_array(Array &p_arr) const override;385386virtual void _update_lightmap_size() override;387388public:389void set_inner_radius(const float p_inner_radius);390float get_inner_radius() const;391392void set_outer_radius(const float p_outer_radius);393float get_outer_radius() const;394395void set_rings(const int p_rings);396int get_rings() const;397398void set_ring_segments(const int p_ring_segments);399int get_ring_segments() const;400};401402/**403A single point for use in particle systems404*/405406class PointMesh : public PrimitiveMesh {407GDCLASS(PointMesh, PrimitiveMesh)408409protected:410virtual void _create_mesh_array(Array &p_arr) const override;411412public:413PointMesh();414};415416class TubeTrailMesh : public PrimitiveMesh {417GDCLASS(TubeTrailMesh, PrimitiveMesh);418419private:420float radius = 0.5;421int radial_steps = 8;422int sections = 5;423float section_length = 0.2;424int section_rings = 3;425bool cap_top = true;426bool cap_bottom = true;427428Ref<Curve> curve;429430void _curve_changed();431432protected:433static void _bind_methods();434virtual void _create_mesh_array(Array &p_arr) const override;435436public:437void set_radius(const float p_radius);438float get_radius() const;439440void set_radial_steps(const int p_radial_steps);441int get_radial_steps() const;442443void set_sections(const int p_sections);444int get_sections() const;445446void set_section_length(float p_sectionlength);447float get_section_length() const;448449void set_section_rings(const int p_section_rings);450int get_section_rings() const;451452void set_cap_top(bool p_cap_top);453bool is_cap_top() const;454455void set_cap_bottom(bool p_cap_bottom);456bool is_cap_bottom() const;457458void set_curve(const Ref<Curve> &p_curve);459Ref<Curve> get_curve() const;460461virtual int get_builtin_bind_pose_count() const override;462virtual Transform3D get_builtin_bind_pose(int p_index) const override;463464TubeTrailMesh();465};466467class RibbonTrailMesh : public PrimitiveMesh {468GDCLASS(RibbonTrailMesh, PrimitiveMesh);469470public:471enum Shape {472SHAPE_FLAT,473SHAPE_CROSS474};475476private:477float size = 1.0;478int sections = 5;479float section_length = 0.2;480int section_segments = 3;481482Shape shape = SHAPE_CROSS;483484Ref<Curve> curve;485486void _curve_changed();487488protected:489static void _bind_methods();490virtual void _create_mesh_array(Array &p_arr) const override;491492public:493void set_shape(Shape p_shape);494Shape get_shape() const;495496void set_size(const float p_size);497float get_size() const;498499void set_sections(const int p_sections);500int get_sections() const;501502void set_section_length(float p_sectionlength);503float get_section_length() const;504505void set_section_segments(const int p_section_segments);506int get_section_segments() const;507508void set_curve(const Ref<Curve> &p_curve);509Ref<Curve> get_curve() const;510511virtual int get_builtin_bind_pose_count() const override;512virtual Transform3D get_builtin_bind_pose(int p_index) const override;513514RibbonTrailMesh();515};516517/**518Text...519*/520521class TextMesh : public PrimitiveMesh {522GDCLASS(TextMesh, PrimitiveMesh);523524private:525struct ContourPoint {526Vector2 point;527bool sharp = false;528529ContourPoint() {}530ContourPoint(const Vector2 &p_pt, bool p_sharp) {531point = p_pt;532sharp = p_sharp;533}534};535536struct ContourInfo {537real_t length = 0.0;538bool ccw = true;539ContourInfo() {}540ContourInfo(real_t p_len, bool p_ccw) {541length = p_len;542ccw = p_ccw;543}544};545546struct GlyphMeshKey {547uint64_t font_id;548uint32_t gl_id;549550bool operator==(const GlyphMeshKey &p_b) const {551return (font_id == p_b.font_id) && (gl_id == p_b.gl_id);552}553554GlyphMeshKey(uint64_t p_font_id, uint32_t p_gl_id) {555font_id = p_font_id;556gl_id = p_gl_id;557}558};559560struct GlyphMeshKeyHasher {561_FORCE_INLINE_ static uint32_t hash(const GlyphMeshKey &p_a) {562return hash_murmur3_buffer(&p_a, sizeof(GlyphMeshKey));563}564};565566struct GlyphMeshData {567Vector<Vector2> triangles;568Vector<Vector<ContourPoint>> contours;569Vector<ContourInfo> contours_info;570Vector2 min_p = Vector2(Math::INF, Math::INF);571Vector2 max_p = Vector2(-Math::INF, -Math::INF);572};573mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache;574575RID text_rid;576mutable Vector<RID> lines_rid;577578String text;579String xl_text;580581int font_size = 16;582Ref<Font> font_override;583584TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF;585BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_SKIP_LAST_LINE | TextServer::JUSTIFICATION_DO_NOT_SKIP_SINGLE_LINE;586float width = 500.0;587float line_spacing = 0.f;588Point2 lbl_offset;589590HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER;591VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER;592bool uppercase = false;593String language;594TextServer::Direction text_direction = TextServer::DIRECTION_AUTO;595TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT;596Array st_args;597598real_t depth = 0.05;599real_t pixel_size = 0.01;600real_t curve_step = 0.5;601602mutable bool dirty_lines = true;603mutable bool dirty_text = true;604mutable bool dirty_font = true;605mutable bool dirty_cache = true;606607void _generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph &p_glyph) const;608void _font_changed();609610protected:611static void _bind_methods();612void _notification(int p_what);613614virtual void _create_mesh_array(Array &p_arr) const override;615616public:617GDVIRTUAL2RC(TypedArray<Vector3i>, _structured_text_parser, Array, String)618619TextMesh();620~TextMesh();621622void set_horizontal_alignment(HorizontalAlignment p_alignment);623HorizontalAlignment get_horizontal_alignment() const;624625void set_vertical_alignment(VerticalAlignment p_alignment);626VerticalAlignment get_vertical_alignment() const;627628void set_text(const String &p_string);629String get_text() const;630631void set_font(const Ref<Font> &p_font);632Ref<Font> get_font() const;633Ref<Font> _get_font_or_default() const;634635void set_font_size(int p_size);636int get_font_size() const;637638void set_line_spacing(float p_size);639float get_line_spacing() const;640641void set_autowrap_mode(TextServer::AutowrapMode p_mode);642TextServer::AutowrapMode get_autowrap_mode() const;643644void set_justification_flags(BitField<TextServer::JustificationFlag> p_flags);645BitField<TextServer::JustificationFlag> get_justification_flags() const;646647void set_text_direction(TextServer::Direction p_text_direction);648TextServer::Direction get_text_direction() const;649650void set_language(const String &p_language);651String get_language() const;652653void set_structured_text_bidi_override(TextServer::StructuredTextParser p_parser);654TextServer::StructuredTextParser get_structured_text_bidi_override() const;655656void set_structured_text_bidi_override_options(const Array &p_args);657Array get_structured_text_bidi_override_options() const;658659void set_uppercase(bool p_uppercase);660bool is_uppercase() const;661662void set_width(real_t p_width);663real_t get_width() const;664665void set_depth(real_t p_depth);666real_t get_depth() const;667668void set_curve_step(real_t p_step);669real_t get_curve_step() const;670671void set_pixel_size(real_t p_amount);672real_t get_pixel_size() const;673674void set_offset(const Point2 &p_offset);675Point2 get_offset() const;676};677678VARIANT_ENUM_CAST(RibbonTrailMesh::Shape)679680681