@tool class_name KelpLeaf extends PrimitiveMesh @export var faceted : bool = false : set(value) : faceted = value; request_update() @export_subgroup("Tip", "tip") @export var tip_set : bool = false : set(value) : tip_set = value; request_update() @export_range(0.01, 0.99, 0.01) var tip_ratio : float = 0.2 : set(value) : tip_ratio = value; request_update() @export_subgroup("Segment", "segment") @export_range(1, 8, 1) var segment_count : int = 2 : set(value) : segment_count = value; request_update() @export_range(0., PI/2., 0.01) var segment_angle : float = PI/6. : set(value) : segment_angle = value; request_update() const TIP_VERTICES_SMOOTH : Array[Vector3] = [ Vector3( 0., 1., 0.), Vector3(-1., 0., 0.), Vector3( 0., 0., 0.), Vector3( 1., 0., 0.) ] const LEAF_VERTICES_SMOOTH : Array[Vector3] = [ Vector3(-1., 0., 0.), Vector3( 0., 0., 0.), Vector3( 1., 0., 0.) ] const TIP_INDICES_SMOOTH : Array[int] = [ 0, 2, 1, 0, 3, 2 ] const LEAF_INDICES_SMOOTH : Array[int] = [ 0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4 ] const TIP_VERTICES_FACETED : Array[Vector3] = [ Vector3( 0., 0., 0.), Vector3( 0., -1., 0.), Vector3(-1., -1., 0.), Vector3( 0., 0., 0.), Vector3( 1., -1., 0.), Vector3( 0., -1., 0.) ] const LEAF_VERTICES_FACETED : Array[Vector3] = [ Vector3(-1., 0., 0.), Vector3( 0., -1., 0.), Vector3(-1., -1., 0.), Vector3(-1., 0., 0.), Vector3( 0., 0., 0.), Vector3( 0., -1., 0.), Vector3( 0., 0., 0.), Vector3( 1., 0., 0.), Vector3( 0., -1., 0.), Vector3( 1., 0., 0.), Vector3( 1., -1., 0.), Vector3( 0., -1., 0.) ] func _create_faceted() -> Array: var body_height : float = 1. - tip_ratio if tip_set else 1. var segment_height : float = body_height / float(segment_count) var vertices : PackedVector3Array = PackedVector3Array() var normals : PackedVector3Array = PackedVector3Array() var vertices_count : int = (TIP_VERTICES_FACETED.size() if tip_set else 0) + segment_count * LEAF_VERTICES_FACETED.size() vertices.resize(vertices_count) normals.resize(vertices_count) # Structure pass var index : int = 0 var cs : float = cos(segment_angle) var sn : float = -sin(segment_angle) if tip_set: for v in TIP_VERTICES_FACETED: vertices[index] = Vector3(v.x * cs, 1. + (v.y * tip_ratio), abs(v.x) * sn) index += 1 vertices[0].z = sn / 2.; vertices[3].z = sn / 2. var current_height : float = body_height for i in range(segment_count): for v in LEAF_VERTICES_FACETED: vertices[index] = Vector3(v.x * cs, current_height + (v.y * segment_height), abs(v.x) * sn) index += 1 current_height -= segment_height # Normal pass @warning_ignore("integer_division") var face_count : int = vertices_count / 3 for i in range(face_count): var j : int = i * 3 var n : Vector3 = -(vertices[j + 1] - vertices[j]).cross(vertices[j + 2] - vertices[j]).normalized() normals[j] = n; normals[j + 1] = n; normals[j + 2] = n # Return mesh var mesh : Array = [] mesh.resize(Mesh.ARRAY_MAX) mesh[Mesh.ARRAY_VERTEX] = vertices mesh[Mesh.ARRAY_NORMAL] = normals return mesh func _create_smooth() -> Array: var body_height : float = 1. - tip_ratio if tip_set else 1. var segment_height : float = body_height / float(segment_count) var current_height : float = body_height var vertices : Array[Vector3] = [] var indices : Array[int] = [] # Structure pass if tip_set: vertices.append_array(TIP_VERTICES_SMOOTH) indices.append_array(TIP_INDICES_SMOOTH) vertices[1].y = current_height ; vertices[2].y = current_height ; vertices[3].y = current_height else: vertices.append_array(LEAF_VERTICES_SMOOTH) vertices[0].y = current_height ; vertices[1].y = current_height ; vertices[2].y = current_height for i in range(segment_count): current_height -= segment_height var c : int = vertices.size() vertices.append_array(LEAF_VERTICES_SMOOTH) for j in range(3): vertices[c + j].y = current_height for j in LEAF_INDICES_SMOOTH: indices.append(j + c - 3) # Value adjustment pass var vertices_count : int = vertices.size() var normals : PackedVector3Array = PackedVector3Array() normals.resize(vertices_count) normals.fill(Vector3(0., 0., 1.)) var cs : float = cos(segment_angle) var sn : float = -sin(segment_angle) if tip_set: vertices[0].z = sn / 2. normals[0].y = -sn / 2. ; normals[0].z = tip_ratio; normals[0] = normals[0].normalized() for i in range(1 if tip_set else 0, vertices_count): normals[i] = Vector3(-vertices[i].x * sn, 0., cs) vertices[i] = Vector3(vertices[i].x * cs, vertices[i].y, abs(vertices[i].x) * sn) # Return mesh var mesh : Array = [] mesh.resize(Mesh.ARRAY_MAX) mesh[Mesh.ARRAY_VERTEX] = PackedVector3Array(vertices) mesh[Mesh.ARRAY_INDEX] = PackedInt32Array(indices) mesh[Mesh.ARRAY_NORMAL] = normals return mesh # Primitive Mesh entry point func _create_mesh_array() -> Array: return _create_faceted() if faceted else _create_smooth()
or share this direct link: