| 1137 | self.readback_water_interval.insert(*node, interval); |
| 1138 | let accum = self.readback_water_accum.entry(*node).or_insert(0.0); |
| 1139 | if !all_paused { |
| 1140 | *accum += ctx.delta_seconds.max(0.0); |
| 1141 | } |
| 1142 | let scheduled = interval > 0.0 && *accum + 1.0e-6 >= interval; |
| 1143 | if water.sim[1] > 0 && scheduled { |
| 1144 | self.readback_nodes.push(*node); |
| 1145 | self.readback_offsets.push(water_center_cell_offset(water)); |
| 1146 | self.readback_scheduled_nodes.push(*node); |
| 1147 | } |
| 1148 | } |
| 1149 | for ((node, state), water) in waters_3d |
| 1150 | .iter() |
| 1151 | .zip(self.staged_waters.iter().skip(waters_2d.len())) |
| 1152 | { |
| 1153 | let interval = water_adaptive_readback_interval( |
| 1154 | state.sample_readback_rate, |
| 1155 | water.wave[3], |
| 1156 | !state.queries.is_empty(), |
| 1157 | !state.impacts.is_empty(), |
| 1158 | ); |
| 1159 | self.readback_water_interval.insert(*node, interval); |
| 1160 | let accum = self.readback_water_accum.entry(*node).or_insert(0.0); |
| 1161 | if !all_paused { |
| 1162 | *accum += ctx.delta_seconds.max(0.0); |
| 1163 | } |
| 1164 | let scheduled = interval > 0.0 && *accum + 1.0e-6 >= interval; |
| 1165 | if water.sim[1] > 0 && scheduled { |
| 1166 | self.readback_nodes.push(*node); |
| 1167 | self.readback_offsets.push(water_center_cell_offset(water)); |
| 1168 | self.readback_scheduled_nodes.push(*node); |
| 1169 | } |
| 1170 | } |
| 1171 | self.readback_water_sample_count = self.readback_nodes.len(); |
| 1172 | // Sort once so the membership checks below are O(log n) binary searches |
| 1173 | // rather than O(n) scans per water. |
| 1174 | self.readback_scheduled_nodes |
| 1175 | .sort_unstable_by_key(|node| node.as_u64()); |
| 1176 | for ((node, state), water) in waters_2d.iter().zip(self.staged_waters.iter()) { |
| 1177 | if self |
| 1178 | .readback_scheduled_nodes |
| 1179 | .binary_search_by_key(&node.as_u64(), |n| n.as_u64()) |
| 1180 | .is_err() |
| 1181 | { |
| 1182 | continue; |
| 1183 | } |
| 1184 | for query in state.queries.iter() { |
| 1185 | let sample = water_query_sample_offsets(water, query.local); |
| 1186 | self.readback_queries.push(WaterReadbackQuery { |
| 1187 | query: *query, |
| 1188 | frac: sample.frac, |
| 1189 | }); |
| 1190 | self.readback_offsets.extend(sample.offsets); |
| 1191 | debug_assert_eq!(query.water, *node); |
| 1192 | } |
| 1193 | } |
| 1194 | for ((node, state), water) in waters_3d |
| 1195 | .iter() |
| 1196 | .zip(self.staged_waters.iter().skip(waters_2d.len())) |