Add properties to disable top/bottom cap generation in TubeTrailMesh

This can be used to improve generation and rendering performance,
or for certain special effects such as particle trails.
This commit is contained in:
Hugo Locurcio 2022-05-21 02:03:34 +02:00
parent d34594179a
commit 6e330e8a75
No known key found for this signature in database
GPG key ID: 39E8F8BE30B0A49C
3 changed files with 132 additions and 87 deletions

View file

@ -7,6 +7,12 @@
<tutorials>
</tutorials>
<members>
<member name="cap_bottom" type="bool" setter="set_cap_bottom" getter="is_cap_bottom" default="true">
If [code]true[/code], generates a cap at the bottom of the tube. This can be set to [code]false[/code] to speed up generation and rendering when the cap is never seen by the camera.
</member>
<member name="cap_top" type="bool" setter="set_cap_top" getter="is_cap_top" default="true">
If [code]true[/code], generates a cap at the top of the tube. This can be set to [code]false[/code] to speed up generation and rendering when the cap is never seen by the camera.
</member>
<member name="curve" type="Curve" setter="set_curve" getter="get_curve">
</member>
<member name="radial_steps" type="int" setter="set_radial_steps" getter="get_radial_steps" default="8">

View file

@ -2171,6 +2171,24 @@ int TubeTrailMesh::get_section_rings() const {
return section_rings;
}
void TubeTrailMesh::set_cap_top(bool p_cap_top) {
cap_top = p_cap_top;
_request_update();
}
bool TubeTrailMesh::is_cap_top() const {
return cap_top;
}
void TubeTrailMesh::set_cap_bottom(bool p_cap_bottom) {
cap_bottom = p_cap_bottom;
_request_update();
}
bool TubeTrailMesh::is_cap_bottom() const {
return cap_bottom;
}
void TubeTrailMesh::set_curve(const Ref<Curve> &p_curve) {
if (curve == p_curve) {
return;
@ -2284,49 +2302,21 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
thisrow = point;
}
// add top
float scale_pos = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
scale_pos = curve->sample_baked(0);
}
if (cap_top) {
// add top
float scale_pos = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
scale_pos = curve->sample_baked(0);
}
if (scale_pos > CMP_EPSILON) {
float y = depth * 0.5;
if (scale_pos > CMP_EPSILON) {
float y = depth * 0.5;
thisrow = point;
points.push_back(Vector3(0.0, y, 0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.25, 0.75));
point++;
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_weights.push_back(1.0);
bone_weights.push_back(0);
bone_weights.push_back(0);
bone_weights.push_back(0);
float rm = radius * scale_pos;
for (int i = 0; i <= radial_steps; i++) {
float r = i;
r /= radial_steps;
float x = sin(r * Math_TAU);
float z = cos(r * Math_TAU);
float u = ((x + 1.0) * 0.25);
float v = 0.5 + ((z + 1.0) * 0.25);
Vector3 p = Vector3(x * rm, y, z * rm);
points.push_back(p);
thisrow = point;
points.push_back(Vector3(0.0, y, 0));
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
uvs.push_back(Vector2(0.25, 0.75));
point++;
bone_indices.push_back(0);
@ -2339,57 +2329,59 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
bone_weights.push_back(0);
bone_weights.push_back(0);
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 1);
indices.push_back(point - 2);
float rm = radius * scale_pos;
for (int i = 0; i <= radial_steps; i++) {
float r = i;
r /= radial_steps;
float x = sin(r * Math_TAU);
float z = cos(r * Math_TAU);
float u = ((x + 1.0) * 0.25);
float v = 0.5 + ((z + 1.0) * 0.25);
Vector3 p = Vector3(x * rm, y, z * rm);
points.push_back(p);
normals.push_back(Vector3(0.0, 1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
point++;
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_weights.push_back(1.0);
bone_weights.push_back(0);
bone_weights.push_back(0);
bone_weights.push_back(0);
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 1);
indices.push_back(point - 2);
}
}
}
}
float scale_neg = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
scale_neg = curve->sample_baked(1.0);
}
if (cap_bottom) {
float scale_neg = 1.0;
if (curve.is_valid() && curve->get_point_count() > 0) {
scale_neg = curve->sample_baked(1.0);
}
// add bottom
if (scale_neg > CMP_EPSILON) {
float y = depth * -0.5;
if (scale_neg > CMP_EPSILON) {
// add bottom
float y = depth * -0.5;
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(0.75, 0.75));
point++;
bone_indices.push_back(sections);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_weights.push_back(1.0);
bone_weights.push_back(0);
bone_weights.push_back(0);
bone_weights.push_back(0);
float rm = radius * scale_neg;
for (int i = 0; i <= radial_steps; i++) {
float r = i;
r /= radial_steps;
float x = sin(r * Math_TAU);
float z = cos(r * Math_TAU);
float u = 0.5 + ((x + 1.0) * 0.25);
float v = 1.0 - ((z + 1.0) * 0.25);
Vector3 p = Vector3(x * rm, y, z * rm);
points.push_back(p);
thisrow = point;
points.push_back(Vector3(0.0, y, 0.0));
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
uvs.push_back(Vector2(0.75, 0.75));
point++;
bone_indices.push_back(sections);
@ -2402,10 +2394,40 @@ void TubeTrailMesh::_create_mesh_array(Array &p_arr) const {
bone_weights.push_back(0);
bone_weights.push_back(0);
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 2);
indices.push_back(point - 1);
float rm = radius * scale_neg;
for (int i = 0; i <= radial_steps; i++) {
float r = i;
r /= radial_steps;
float x = sin(r * Math_TAU);
float z = cos(r * Math_TAU);
float u = 0.5 + ((x + 1.0) * 0.25);
float v = 1.0 - ((z + 1.0) * 0.25);
Vector3 p = Vector3(x * rm, y, z * rm);
points.push_back(p);
normals.push_back(Vector3(0.0, -1.0, 0.0));
ADD_TANGENT(1.0, 0.0, 0.0, 1.0)
uvs.push_back(Vector2(u, v));
point++;
bone_indices.push_back(sections);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_indices.push_back(0);
bone_weights.push_back(1.0);
bone_weights.push_back(0);
bone_weights.push_back(0);
bone_weights.push_back(0);
if (i > 0) {
indices.push_back(thisrow);
indices.push_back(point - 2);
indices.push_back(point - 1);
}
}
}
}
@ -2435,6 +2457,12 @@ void TubeTrailMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_section_rings", "section_rings"), &TubeTrailMesh::set_section_rings);
ClassDB::bind_method(D_METHOD("get_section_rings"), &TubeTrailMesh::get_section_rings);
ClassDB::bind_method(D_METHOD("set_cap_top", "cap_top"), &TubeTrailMesh::set_cap_top);
ClassDB::bind_method(D_METHOD("is_cap_top"), &TubeTrailMesh::is_cap_top);
ClassDB::bind_method(D_METHOD("set_cap_bottom", "cap_bottom"), &TubeTrailMesh::set_cap_bottom);
ClassDB::bind_method(D_METHOD("is_cap_bottom"), &TubeTrailMesh::is_cap_bottom);
ClassDB::bind_method(D_METHOD("set_curve", "curve"), &TubeTrailMesh::set_curve);
ClassDB::bind_method(D_METHOD("get_curve"), &TubeTrailMesh::get_curve);
@ -2447,13 +2475,16 @@ void TubeTrailMesh::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "section_rings", PROPERTY_HINT_RANGE, "1,128,1"), "set_section_rings", "get_section_rings");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_top"), "set_cap_top", "is_cap_top");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cap_bottom"), "set_cap_bottom", "is_cap_bottom");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve");
}
TubeTrailMesh::TubeTrailMesh() {
}
// TUBE TRAIL
// RIBBON TRAIL
void RibbonTrailMesh::set_shape(Shape p_shape) {
shape = p_shape;

View file

@ -431,6 +431,8 @@ private:
int sections = 5;
float section_length = 0.2;
int section_rings = 3;
bool cap_top = true;
bool cap_bottom = true;
Ref<Curve> curve;
@ -456,6 +458,12 @@ public:
void set_section_rings(const int p_section_rings);
int get_section_rings() const;
void set_cap_top(bool p_cap_top);
bool is_cap_top() const;
void set_cap_bottom(bool p_cap_bottom);
bool is_cap_bottom() const;
void set_curve(const Ref<Curve> &p_curve);
Ref<Curve> get_curve() const;