extends MultiMeshInstance3D var mm: MultiMesh var parent_node: GrassController static var grass_mesh: Mesh = null func _ready() -> void: parent_node = get_parent() as GrassController if parent_node == null: Log.pr("Error: Parent node is not a GrassController!") # Load mesh once and reuse if grass_mesh == null: grass_mesh = load("res://Entities/Grass/assets/grass2_mesh.res") func setup_multimesh() -> void: if parent_node == null: return if grass_mesh == null: Log.pr("Error: Could not load grass mesh") return # Reuse existing MultiMesh if possible, or create new one if mm == null: mm = MultiMesh.new() mm.transform_format = MultiMesh.TRANSFORM_3D mm.mesh = grass_mesh update_shader_parameter('top_color', ColorData.grass_materials[Season.current]['top']) update_shader_parameter('bottom_color', ColorData.grass_materials[Season.current]['base']) # Configure instance count mm.instance_count = parent_node.grass_instance_range # Get shared RNG from GroundTile var rng = parent_node.parent_node.get_rng() # Generate positions using shared RNG for i in range(mm.instance_count): var random_pos = Vector3( rng.randf_range(-1.0, 1.0), 0.0, rng.randf_range(-1.0, 1.0) ) var random_rotation = rng.randf_range(0.0, TAU) var basis = Basis(Vector3.UP, random_rotation) var random_scale = rng.randf_range(0.05, 0.3) basis = basis.scaled(Vector3(random_scale, random_scale, random_scale)) var tx = Transform3D(basis, random_pos) mm.set_instance_transform(i, tx) multimesh = mm cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_OFF func update_shader_parameter(param_name: String, value) -> void: if material_override == null: Log.pr("Error: No material override found") return # Check if it's a ShaderMaterial if material_override is ShaderMaterial: var shader_material = material_override as ShaderMaterial shader_material.set_shader_parameter(param_name, value) else: Log.pr("Error: Material override is not a ShaderMaterial") return