Add `TorusMesh`
This commit is contained in:
parent
bed2482ce2
commit
21b9b117be
|
@ -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>
|
|
@ -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>
|
After Width: | Height: | Size: 226 B |
|
@ -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);
|
||||
|
|
|
@ -1621,6 +1621,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
|
||||
*/
|
||||
|
|
|
@ -350,6 +350,38 @@ public:
|
|||
SphereMesh();
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue