diff options
-rw-r--r-- | doc/classes/TorusMesh.xml | 25 | ||||
-rw-r--r-- | editor/icons/TorusMesh.svg | 1 | ||||
-rw-r--r-- | scene/register_scene_types.cpp | 1 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.cpp | 128 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.h | 32 |
5 files changed, 187 insertions, 0 deletions
diff --git a/doc/classes/TorusMesh.xml b/doc/classes/TorusMesh.xml new file mode 100644 index 0000000000..6b83152793 --- /dev/null +++ b/doc/classes/TorusMesh.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="TorusMesh" inherits="PrimitiveMesh" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + Class representing a torus [PrimitiveMesh]. + </brief_description> + <description> + Class representing a torus [PrimitiveMesh]. + </description> + <tutorials> + </tutorials> + <members> + <member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="0.5"> + The inner radius of the torus. + </member> + <member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="1.0"> + The outer radius of the torus. + </member> + <member name="ring_segments" type="int" setter="set_ring_segments" getter="get_ring_segments" default="32"> + The number of edges each ring of the torus is constructed of. + </member> + <member name="rings" type="int" setter="set_rings" getter="get_rings" default="64"> + The number of slices the torus is constructed of. + </member> + </members> +</class> diff --git a/editor/icons/TorusMesh.svg b/editor/icons/TorusMesh.svg new file mode 100644 index 0000000000..2ed973d3cf --- /dev/null +++ b/editor/icons/TorusMesh.svg @@ -0,0 +1 @@ +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="8" cy="7.5" fill="none" rx="6" ry="3.5" stroke="#ffca5f" stroke-linecap="square" stroke-linejoin="round" stroke-width="2"/></svg> diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index d7fcd500b2..a5842106fb 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -785,6 +785,7 @@ void register_scene_types() { GDREGISTER_CLASS(QuadMesh); GDREGISTER_CLASS(SphereMesh); GDREGISTER_CLASS(TextMesh); + GDREGISTER_CLASS(TorusMesh); GDREGISTER_CLASS(TubeTrailMesh); GDREGISTER_CLASS(RibbonTrailMesh); GDREGISTER_CLASS(PointMesh); diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 68441afb1c..f038a79b8f 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -1622,6 +1622,134 @@ bool SphereMesh::get_is_hemisphere() const { SphereMesh::SphereMesh() {} /** + TorusMesh +*/ + +void TorusMesh::_create_mesh_array(Array &p_arr) const { + // set our bounding box + + Vector<Vector3> points; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int> indices; + +#define ADD_TANGENT(m_x, m_y, m_z, m_d) \ + tangents.push_back(m_x); \ + tangents.push_back(m_y); \ + tangents.push_back(m_z); \ + tangents.push_back(m_d); + + ERR_FAIL_COND_MSG(inner_radius == outer_radius, "Inner radius and outer radius cannot be the same."); + + float min_radius = inner_radius; + float max_radius = outer_radius; + + if (min_radius > max_radius) { + SWAP(min_radius, max_radius); + } + + float radius = (max_radius - min_radius) * 0.5; + + for (int i = 0; i <= rings; i++) { + int prevrow = (i - 1) * (ring_segments + 1); + int thisrow = i * (ring_segments + 1); + float inci = float(i) / rings; + float angi = inci * Math_TAU; + + Vector2 normali = Vector2(-Math::sin(angi), -Math::cos(angi)); + + for (int j = 0; j <= ring_segments; j++) { + float incj = float(j) / ring_segments; + float angj = incj * Math_TAU; + + Vector2 normalj = Vector2(-Math::cos(angj), Math::sin(angj)); + Vector2 normalk = normalj * radius + Vector2(min_radius + radius, 0); + + points.push_back(Vector3(normali.x * normalk.x, normalk.y, normali.y * normalk.x)); + normals.push_back(Vector3(normali.x * normalj.x, normalj.y, normali.y * normalj.x)); + ADD_TANGENT(-Math::cos(angi), 0.0, Math::sin(angi), 1.0); + uvs.push_back(Vector2(inci, incj)); + + if (i > 0 && j > 0) { + indices.push_back(thisrow + j - 1); + indices.push_back(prevrow + j); + indices.push_back(prevrow + j - 1); + + indices.push_back(thisrow + j - 1); + indices.push_back(thisrow + j); + indices.push_back(prevrow + j); + } + } + } + + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; +} + +void TorusMesh::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_inner_radius", "radius"), &TorusMesh::set_inner_radius); + ClassDB::bind_method(D_METHOD("get_inner_radius"), &TorusMesh::get_inner_radius); + + ClassDB::bind_method(D_METHOD("set_outer_radius", "radius"), &TorusMesh::set_outer_radius); + ClassDB::bind_method(D_METHOD("get_outer_radius"), &TorusMesh::get_outer_radius); + + ClassDB::bind_method(D_METHOD("set_rings", "rings"), &TorusMesh::set_rings); + ClassDB::bind_method(D_METHOD("get_rings"), &TorusMesh::get_rings); + + ClassDB::bind_method(D_METHOD("set_ring_segments", "rings"), &TorusMesh::set_ring_segments); + ClassDB::bind_method(D_METHOD("get_ring_segments"), &TorusMesh::get_ring_segments); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inner_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_inner_radius", "get_inner_radius"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "outer_radius", PROPERTY_HINT_RANGE, "0.001,1000.0,0.001,or_greater,exp"), "set_outer_radius", "get_outer_radius"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "rings", PROPERTY_HINT_RANGE, "3,128,1"), "set_rings", "get_rings"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "ring_segments", PROPERTY_HINT_RANGE, "3,64,1"), "set_ring_segments", "get_ring_segments"); +} + +void TorusMesh::set_inner_radius(const float p_inner_radius) { + inner_radius = p_inner_radius; + _request_update(); +} + +float TorusMesh::get_inner_radius() const { + return inner_radius; +} + +void TorusMesh::set_outer_radius(const float p_outer_radius) { + outer_radius = p_outer_radius; + _request_update(); +} + +float TorusMesh::get_outer_radius() const { + return outer_radius; +} + +void TorusMesh::set_rings(const int p_rings) { + ERR_FAIL_COND(p_rings < 3); + rings = p_rings; + _request_update(); +} + +int TorusMesh::get_rings() const { + return rings; +} + +void TorusMesh::set_ring_segments(const int p_ring_segments) { + ERR_FAIL_COND(p_ring_segments < 3); + ring_segments = p_ring_segments; + _request_update(); +} + +int TorusMesh::get_ring_segments() const { + return ring_segments; +} + +TorusMesh::TorusMesh() {} + +/** PointMesh */ diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index ec124e379f..64eefd2c07 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -351,6 +351,38 @@ public: }; /** + Big donut +*/ +class TorusMesh : public PrimitiveMesh { + GDCLASS(TorusMesh, PrimitiveMesh); + +private: + float inner_radius = 0.5; + float outer_radius = 1.0; + int rings = 64; + int ring_segments = 32; + +protected: + static void _bind_methods(); + virtual void _create_mesh_array(Array &p_arr) const override; + +public: + void set_inner_radius(const float p_inner_radius); + float get_inner_radius() const; + + void set_outer_radius(const float p_outer_radius); + float get_outer_radius() const; + + void set_rings(const int p_rings); + int get_rings() const; + + void set_ring_segments(const int p_ring_segments); + int get_ring_segments() const; + + TorusMesh(); +}; + +/** A single point for use in particle systems */ |