class_name M2StaticBatchMaterializer extends RefCounted ## Builds and attaches one static M2 MultiMesh batch from an ordered transform ## slice. All Resource and SceneTree mutation belongs on the main thread. ## Returns the attached MultiMeshInstance3D, or null for invalid/empty input. ## The supplied parent owns the returned node and its MultiMesh Resource. ## Transform bounds are a build-planner precondition and are not clamped. func materialize_batch( m2_parent_root: Node3D, relative_path: String, mesh: Mesh, transforms: Array, start_index: int, instance_count: int, batch_serial: int, visibility_range_end: float, visibility_range_margin: float, cast_shadows: bool ) -> MultiMeshInstance3D: if ( m2_parent_root == null or mesh == null or transforms.is_empty() or instance_count <= 0 ): return null var multimesh := MultiMesh.new() multimesh.transform_format = MultiMesh.TRANSFORM_3D multimesh.mesh = mesh multimesh.instance_count = instance_count for batch_offset in instance_count: multimesh.set_instance_transform( batch_offset, transforms[start_index + batch_offset] ) var multimesh_instance := MultiMeshInstance3D.new() multimesh_instance.name = "%s_%d" % [ relative_path.get_file().get_basename(), batch_serial, ] multimesh_instance.multimesh = multimesh multimesh_instance.cast_shadow = ( GeometryInstance3D.SHADOW_CASTING_SETTING_ON if cast_shadows else GeometryInstance3D.SHADOW_CASTING_SETTING_OFF ) if visibility_range_end > 0.0: multimesh_instance.visibility_range_end = visibility_range_end multimesh_instance.visibility_range_end_margin = visibility_range_margin m2_parent_root.add_child(multimesh_instance) return multimesh_instance