| | | 1 | | using FixedMathSharp; |
| | | 2 | | using GridForge.Spatial; |
| | | 3 | | using GridForge.Utility; |
| | | 4 | | using SwiftCollections; |
| | | 5 | | using SwiftCollections.Pool; |
| | | 6 | | using System; |
| | | 7 | | using System.Collections.Generic; |
| | | 8 | | using System.Linq; |
| | | 9 | | |
| | | 10 | | namespace GridForge.Grids; |
| | | 11 | | |
| | | 12 | | /// <summary> |
| | | 13 | | /// Provides efficient querying methods for retrieving occupants within a grid. |
| | | 14 | | /// Handles spatial lookups for voxels, filtering by occupant type, and fetching occupants using unique tickets. |
| | | 15 | | /// </summary> |
| | | 16 | | public static class GridScanManager |
| | | 17 | | { |
| | | 18 | | #region Scan Methods |
| | | 19 | | |
| | | 20 | | /// <summary> |
| | | 21 | | /// Scans for occupants within a given radius from a specified position in the supplied world. |
| | | 22 | | /// </summary> |
| | | 23 | | public static IEnumerable<IVoxelOccupant> ScanRadius( |
| | | 24 | | GridWorld world, |
| | | 25 | | Vector3d position, |
| | | 26 | | Fixed64 radius, |
| | | 27 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 28 | | Func<byte, bool>? groupCondition = null) |
| | | 29 | | { |
| | 6 | 30 | | if (world == null || !world.IsActive) |
| | 0 | 31 | | return Enumerable.Empty<IVoxelOccupant>(); |
| | | 32 | | |
| | 6 | 33 | | return ScanRadiusIterator(world, position, radius, occupantCondition, groupCondition); |
| | | 34 | | } |
| | | 35 | | |
| | | 36 | | /// <summary> |
| | | 37 | | /// Scans for occupants of a specific type within a given radius in the supplied world. |
| | | 38 | | /// </summary> |
| | | 39 | | public static IEnumerable<T> ScanRadius<T>( |
| | | 40 | | GridWorld world, |
| | | 41 | | Vector3d position, |
| | | 42 | | Fixed64 radius, |
| | | 43 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 44 | | Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant |
| | | 45 | | { |
| | 1 | 46 | | return ScanRadius(world, position, radius, occupantCondition, groupCondition).OfType<T>(); |
| | | 47 | | } |
| | | 48 | | |
| | | 49 | | /// <summary> |
| | | 50 | | /// Clears and fills caller-owned storage with occupants within the supplied radius. |
| | | 51 | | /// </summary> |
| | | 52 | | public static void ScanRadiusInto( |
| | | 53 | | GridWorld world, |
| | | 54 | | Vector3d position, |
| | | 55 | | Fixed64 radius, |
| | | 56 | | SwiftList<IVoxelOccupant> results, |
| | | 57 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 58 | | Func<byte, bool>? groupCondition = null) |
| | | 59 | | { |
| | 7 | 60 | | if (results == null) |
| | 0 | 61 | | throw new ArgumentNullException(nameof(results)); |
| | | 62 | | |
| | 7 | 63 | | results.Clear(); |
| | 7 | 64 | | if (world == null || !world.IsActive) |
| | 0 | 65 | | return; |
| | | 66 | | |
| | 7 | 67 | | AddRadiusOccupantsTo(world, position, radius, results, occupantCondition, groupCondition); |
| | 7 | 68 | | } |
| | | 69 | | |
| | | 70 | | /// <summary> |
| | | 71 | | /// Clears and fills caller-owned storage using caller-owned scratch collections. |
| | | 72 | | /// </summary> |
| | | 73 | | public static void ScanRadiusInto( |
| | | 74 | | GridWorld world, |
| | | 75 | | Vector3d position, |
| | | 76 | | Fixed64 radius, |
| | | 77 | | SwiftList<IVoxelOccupant> results, |
| | | 78 | | GridScanScratch scratch, |
| | | 79 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 80 | | Func<byte, bool>? groupCondition = null) |
| | | 81 | | { |
| | 257 | 82 | | if (results == null) |
| | 0 | 83 | | throw new ArgumentNullException(nameof(results)); |
| | | 84 | | |
| | 257 | 85 | | if (scratch == null) |
| | 0 | 86 | | throw new ArgumentNullException(nameof(scratch)); |
| | | 87 | | |
| | 257 | 88 | | results.Clear(); |
| | 257 | 89 | | if (world == null || !world.IsActive) |
| | 0 | 90 | | return; |
| | | 91 | | |
| | 257 | 92 | | AddRadiusOccupantsTo(world, position, radius, results, scratch, occupantCondition, groupCondition); |
| | 257 | 93 | | } |
| | | 94 | | |
| | | 95 | | /// <summary> |
| | | 96 | | /// Clears and fills caller-owned storage with typed occupants within the supplied radius. |
| | | 97 | | /// </summary> |
| | | 98 | | public static void ScanRadiusInto<T>( |
| | | 99 | | GridWorld world, |
| | | 100 | | Vector3d position, |
| | | 101 | | Fixed64 radius, |
| | | 102 | | SwiftList<T> results, |
| | | 103 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 104 | | Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant |
| | | 105 | | { |
| | 0 | 106 | | if (results == null) |
| | 0 | 107 | | throw new ArgumentNullException(nameof(results)); |
| | | 108 | | |
| | 0 | 109 | | results.Clear(); |
| | 0 | 110 | | if (world == null || !world.IsActive) |
| | 0 | 111 | | return; |
| | | 112 | | |
| | 0 | 113 | | AddRadiusOccupantsTo(world, position, radius, results, occupantCondition, groupCondition); |
| | 0 | 114 | | } |
| | | 115 | | |
| | | 116 | | /// <summary> |
| | | 117 | | /// Clears and fills caller-owned typed storage using caller-owned scratch collections. |
| | | 118 | | /// </summary> |
| | | 119 | | public static void ScanRadiusInto<T>( |
| | | 120 | | GridWorld world, |
| | | 121 | | Vector3d position, |
| | | 122 | | Fixed64 radius, |
| | | 123 | | SwiftList<T> results, |
| | | 124 | | GridScanScratch scratch, |
| | | 125 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 126 | | Func<byte, bool>? groupCondition = null) where T : IVoxelOccupant |
| | | 127 | | { |
| | 1 | 128 | | if (results == null) |
| | 0 | 129 | | throw new ArgumentNullException(nameof(results)); |
| | | 130 | | |
| | 1 | 131 | | if (scratch == null) |
| | 0 | 132 | | throw new ArgumentNullException(nameof(scratch)); |
| | | 133 | | |
| | 1 | 134 | | results.Clear(); |
| | 1 | 135 | | if (world == null || !world.IsActive) |
| | 0 | 136 | | return; |
| | | 137 | | |
| | 1 | 138 | | AddRadiusOccupantsTo(world, position, radius, results, scratch, occupantCondition, groupCondition); |
| | 1 | 139 | | } |
| | | 140 | | |
| | | 141 | | #endregion |
| | | 142 | | |
| | | 143 | | #region Occupant Registration & Retrieval |
| | | 144 | | |
| | | 145 | | /// <summary> |
| | | 146 | | /// Retrieves all occupants of a specific type at a given world-scoped voxel identity in the supplied world. |
| | | 147 | | /// </summary> |
| | | 148 | | public static IEnumerable<T> GetVoxelOccupantsByType<T>(GridWorld world, WorldVoxelIndex index) where T : IVoxelOccu |
| | | 149 | | { |
| | 2 | 150 | | return world != null && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel) |
| | 2 | 151 | | ? grid!.GetVoxelOccupantsByType<T>(voxel!) |
| | 2 | 152 | | : Enumerable.Empty<T>(); |
| | | 153 | | } |
| | | 154 | | |
| | | 155 | | /// <summary> |
| | | 156 | | /// Retrieves all occupants of a specific type at a given world position. |
| | | 157 | | /// </summary> |
| | | 158 | | public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, Vector3d position) where T : IVoxelOccu |
| | | 159 | | { |
| | 2 | 160 | | return grid.TryGetVoxel(position, out Voxel? voxel) |
| | 2 | 161 | | ? grid.GetVoxelOccupantsByType<T>(voxel!) |
| | 2 | 162 | | : Enumerable.Empty<T>(); |
| | | 163 | | } |
| | | 164 | | |
| | | 165 | | /// <summary> |
| | | 166 | | /// Retrieves all occupants of a specific type at a given voxel coordinate. |
| | | 167 | | /// </summary> |
| | | 168 | | public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, VoxelIndex index) where T : IVoxelOccup |
| | | 169 | | { |
| | 2 | 170 | | return grid.TryGetVoxel(index, out Voxel? voxel) |
| | 2 | 171 | | ? grid.GetVoxelOccupantsByType<T>(voxel!) |
| | 2 | 172 | | : Enumerable.Empty<T>(); |
| | | 173 | | } |
| | | 174 | | |
| | | 175 | | /// <summary> |
| | | 176 | | /// Retrieves all occupants of a specific type at a given voxel. |
| | | 177 | | /// </summary> |
| | | 178 | | public static IEnumerable<T> GetVoxelOccupantsByType<T>(this VoxelGrid grid, Voxel voxel) where T : IVoxelOccupant |
| | | 179 | | { |
| | 4 | 180 | | return voxel == null |
| | 4 | 181 | | ? Enumerable.Empty<T>() |
| | 4 | 182 | | : grid.GetOccupants(voxel).OfType<T>(); |
| | | 183 | | } |
| | | 184 | | |
| | | 185 | | /// <summary> |
| | | 186 | | /// Retrieves a specific occupant at a given world-scoped voxel identity using an occupant ticket in the supplied wo |
| | | 187 | | /// </summary> |
| | | 188 | | public static bool TryGetVoxelOccupant( |
| | | 189 | | GridWorld world, |
| | | 190 | | WorldVoxelIndex index, |
| | | 191 | | int ticket, |
| | | 192 | | out IVoxelOccupant? occupant) |
| | | 193 | | { |
| | 4 | 194 | | occupant = null; |
| | 4 | 195 | | return world != null |
| | 4 | 196 | | && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel) |
| | 4 | 197 | | && grid!.TryGetVoxelOccupant(voxel!, ticket, out occupant); |
| | | 198 | | } |
| | | 199 | | |
| | | 200 | | /// <summary> |
| | | 201 | | /// Retrieves a specific occupant at a given world position using an occupant ticket. |
| | | 202 | | /// </summary> |
| | | 203 | | public static bool TryGetVoxelOccupant( |
| | | 204 | | this VoxelGrid grid, |
| | | 205 | | Vector3d position, |
| | | 206 | | int ticket, |
| | | 207 | | out IVoxelOccupant? occupant) |
| | | 208 | | { |
| | 3 | 209 | | occupant = null; |
| | 3 | 210 | | return grid.TryGetVoxel(position, out Voxel? voxel) |
| | 3 | 211 | | && grid.TryGetVoxelOccupant(voxel!, ticket, out occupant); |
| | | 212 | | } |
| | | 213 | | |
| | | 214 | | /// <summary> |
| | | 215 | | /// Retrieves a specific occupant at a given voxel coordinate using an occupant ticket. |
| | | 216 | | /// </summary> |
| | | 217 | | public static bool TryGetVoxelOccupant( |
| | | 218 | | this VoxelGrid grid, |
| | | 219 | | VoxelIndex index, |
| | | 220 | | int ticket, |
| | | 221 | | out IVoxelOccupant? occupant) |
| | | 222 | | { |
| | 2 | 223 | | occupant = null; |
| | 2 | 224 | | return grid.TryGetVoxel(index, out Voxel? voxel) |
| | 2 | 225 | | && grid.TryGetVoxelOccupant(voxel!, ticket, out occupant); |
| | | 226 | | } |
| | | 227 | | |
| | | 228 | | /// <summary> |
| | | 229 | | /// Retrieves a specific occupant from a given voxel using an occupant ticket. |
| | | 230 | | /// </summary> |
| | | 231 | | public static bool TryGetVoxelOccupant( |
| | | 232 | | this VoxelGrid grid, |
| | | 233 | | Voxel voxel, |
| | | 234 | | int ticket, |
| | | 235 | | out IVoxelOccupant? occupant) |
| | | 236 | | { |
| | 12 | 237 | | occupant = null; |
| | 12 | 238 | | return voxel.IsOccupied |
| | 12 | 239 | | && grid.TryGetScanCell(voxel.ScanCellKey, out ScanCell? scanCell) |
| | 12 | 240 | | && scanCell!.IsOccupied |
| | 12 | 241 | | && scanCell.TryGetOccupantAt(voxel.WorldIndex, ticket, out occupant); |
| | | 242 | | } |
| | | 243 | | |
| | | 244 | | /// <summary> |
| | | 245 | | /// Retrieves all occupants at a given world-scoped voxel identity in the supplied world. |
| | | 246 | | /// </summary> |
| | | 247 | | public static IEnumerable<IVoxelOccupant> GetOccupants(GridWorld world, WorldVoxelIndex index) |
| | | 248 | | { |
| | 2 | 249 | | return world != null && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel) |
| | 2 | 250 | | ? grid!.GetOccupants(voxel!) |
| | 2 | 251 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 252 | | } |
| | | 253 | | |
| | | 254 | | /// <summary> |
| | | 255 | | /// Retrieves all occupants at a given world position within the grid. |
| | | 256 | | /// </summary> |
| | | 257 | | public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, Vector3d position) |
| | | 258 | | { |
| | 5 | 259 | | return grid.TryGetVoxel(position, out Voxel? targetVoxel) |
| | 5 | 260 | | ? grid.GetOccupants(targetVoxel!) |
| | 5 | 261 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 262 | | } |
| | | 263 | | |
| | | 264 | | /// <summary> |
| | | 265 | | /// Retrieves all occupants at a given voxel coordinate within the grid. |
| | | 266 | | /// </summary> |
| | | 267 | | public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, VoxelIndex index) |
| | | 268 | | { |
| | 2 | 269 | | return grid.TryGetVoxel(index, out Voxel? targetVoxel) |
| | 2 | 270 | | ? grid.GetOccupants(targetVoxel!) |
| | 2 | 271 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 272 | | } |
| | | 273 | | |
| | | 274 | | /// <summary> |
| | | 275 | | /// Retrieves all occupants at a given voxel. |
| | | 276 | | /// </summary> |
| | | 277 | | public static IEnumerable<IVoxelOccupant> GetOccupants(this VoxelGrid grid, Voxel voxel) |
| | | 278 | | { |
| | 9 | 279 | | return voxel.IsOccupied |
| | 9 | 280 | | && grid.TryGetScanCell(voxel.ScanCellKey, out ScanCell? scanCell) |
| | 9 | 281 | | && scanCell!.IsOccupied |
| | 9 | 282 | | ? scanCell.GetOccupants() |
| | 9 | 283 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 284 | | } |
| | | 285 | | |
| | | 286 | | /// <summary> |
| | | 287 | | /// Retrieves occupants whose group Ids match a given condition at a world-scoped voxel identity in the supplied wor |
| | | 288 | | /// </summary> |
| | | 289 | | public static IEnumerable<IVoxelOccupant> GetConditionalOccupants( |
| | | 290 | | GridWorld world, |
| | | 291 | | WorldVoxelIndex index, |
| | | 292 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 293 | | Func<byte, bool>? groupCondition = null) |
| | | 294 | | { |
| | 3 | 295 | | return world != null && world.TryGetGridAndVoxel(index, out VoxelGrid? grid, out Voxel? voxel) |
| | 3 | 296 | | ? grid!.GetConditionalOccupants(voxel!, occupantCondition, groupCondition) |
| | 3 | 297 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 298 | | } |
| | | 299 | | |
| | | 300 | | /// <summary> |
| | | 301 | | /// Retrieves occupants whose group Ids match a given condition. |
| | | 302 | | /// </summary> |
| | | 303 | | public static IEnumerable<IVoxelOccupant> GetConditionalOccupants( |
| | | 304 | | this VoxelGrid grid, |
| | | 305 | | Vector3d position, |
| | | 306 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 307 | | Func<byte, bool>? groupCondition = null) |
| | | 308 | | { |
| | 3 | 309 | | return grid.TryGetVoxel(position, out Voxel? voxel) |
| | 3 | 310 | | ? grid.GetConditionalOccupants(voxel!, occupantCondition, groupCondition) |
| | 3 | 311 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 312 | | } |
| | | 313 | | |
| | | 314 | | /// <summary> |
| | | 315 | | /// Retrieves occupants whose group Ids match a given condition. |
| | | 316 | | /// </summary> |
| | | 317 | | public static IEnumerable<IVoxelOccupant> GetConditionalOccupants( |
| | | 318 | | this VoxelGrid grid, |
| | | 319 | | VoxelIndex index, |
| | | 320 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 321 | | Func<byte, bool>? groupCondition = null) |
| | | 322 | | { |
| | 4 | 323 | | return grid.TryGetVoxel(index, out Voxel? voxel) |
| | 4 | 324 | | ? grid.GetConditionalOccupants(voxel!, occupantCondition, groupCondition) |
| | 4 | 325 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 326 | | } |
| | | 327 | | |
| | | 328 | | /// <summary> |
| | | 329 | | /// Retrieves occupants at a given voxel that match a specified group condition. |
| | | 330 | | /// </summary> |
| | | 331 | | public static IEnumerable<IVoxelOccupant> GetConditionalOccupants( |
| | | 332 | | this VoxelGrid grid, |
| | | 333 | | Voxel targetVoxel, |
| | | 334 | | Func<IVoxelOccupant, bool>? occupantCondition = null, |
| | | 335 | | Func<byte, bool>? groupCondition = null) |
| | | 336 | | { |
| | 9 | 337 | | return targetVoxel != null |
| | 9 | 338 | | && targetVoxel.IsOccupied |
| | 9 | 339 | | && grid.TryGetScanCell(targetVoxel.ScanCellKey, out ScanCell? scanCell) |
| | 9 | 340 | | && scanCell!.IsOccupied |
| | 9 | 341 | | ? scanCell.GetConditionalOccupants(occupantCondition, groupCondition) |
| | 9 | 342 | | : Enumerable.Empty<IVoxelOccupant>(); |
| | | 343 | | } |
| | | 344 | | |
| | | 345 | | #endregion |
| | | 346 | | |
| | | 347 | | #region Private Methods |
| | | 348 | | |
| | | 349 | | private static IEnumerable<IVoxelOccupant> ScanRadiusIterator( |
| | | 350 | | GridWorld world, |
| | | 351 | | Vector3d position, |
| | | 352 | | Fixed64 radius, |
| | | 353 | | Func<IVoxelOccupant, bool>? occupantCondition, |
| | | 354 | | Func<byte, bool>? groupCondition) |
| | | 355 | | { |
| | 6 | 356 | | SwiftList<IVoxelOccupant> results = SwiftListPool<IVoxelOccupant>.Shared.Rent(); |
| | | 357 | | |
| | | 358 | | try |
| | | 359 | | { |
| | 6 | 360 | | ScanRadiusInto(world, position, radius, results, occupantCondition, groupCondition); |
| | | 361 | | |
| | 26 | 362 | | foreach (IVoxelOccupant result in results) |
| | | 363 | | { |
| | 7 | 364 | | yield return result; |
| | | 365 | | } |
| | 6 | 366 | | } |
| | | 367 | | finally |
| | | 368 | | { |
| | 6 | 369 | | SwiftListPool<IVoxelOccupant>.Shared.Release(results); |
| | 6 | 370 | | } |
| | 6 | 371 | | } |
| | | 372 | | |
| | | 373 | | private static void AddRadiusOccupantsTo( |
| | | 374 | | GridWorld world, |
| | | 375 | | Vector3d position, |
| | | 376 | | Fixed64 radius, |
| | | 377 | | SwiftList<IVoxelOccupant> results, |
| | | 378 | | Func<IVoxelOccupant, bool>? occupantCondition, |
| | | 379 | | Func<byte, bool>? groupCondition) |
| | | 380 | | { |
| | 7 | 381 | | Fixed64 squaredRadius = radius * radius; |
| | 7 | 382 | | Vector3d boundsMin = position - radius; |
| | 7 | 383 | | Vector3d boundsMax = position + radius; |
| | 7 | 384 | | SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent(); |
| | | 385 | | |
| | | 386 | | try |
| | | 387 | | { |
| | 7 | 388 | | GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells); |
| | | 389 | | |
| | 80 | 390 | | for (int i = 0; i < scanCells.Count; i++) |
| | | 391 | | { |
| | 33 | 392 | | ScanCell scanCell = scanCells[i]; |
| | 33 | 393 | | if (scanCell.IsOccupied) |
| | 9 | 394 | | scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondit |
| | | 395 | | } |
| | 7 | 396 | | } |
| | | 397 | | finally |
| | | 398 | | { |
| | 7 | 399 | | SwiftListPool<ScanCell>.Shared.Release(scanCells); |
| | 7 | 400 | | } |
| | 7 | 401 | | } |
| | | 402 | | |
| | | 403 | | private static void AddRadiusOccupantsTo( |
| | | 404 | | GridWorld world, |
| | | 405 | | Vector3d position, |
| | | 406 | | Fixed64 radius, |
| | | 407 | | SwiftList<IVoxelOccupant> results, |
| | | 408 | | GridScanScratch scratch, |
| | | 409 | | Func<IVoxelOccupant, bool>? occupantCondition, |
| | | 410 | | Func<byte, bool>? groupCondition) |
| | | 411 | | { |
| | 257 | 412 | | Fixed64 squaredRadius = radius * radius; |
| | 257 | 413 | | Vector3d boundsMin = position - radius; |
| | 257 | 414 | | Vector3d boundsMax = position + radius; |
| | | 415 | | |
| | 257 | 416 | | GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch); |
| | | 417 | | |
| | 2570 | 418 | | for (int i = 0; i < scratch.ScanCells.Count; i++) |
| | | 419 | | { |
| | 1028 | 420 | | ScanCell scanCell = scratch.ScanCells[i]; |
| | 1028 | 421 | | if (scanCell.IsOccupied) |
| | 257 | 422 | | scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondition) |
| | | 423 | | } |
| | 257 | 424 | | } |
| | | 425 | | |
| | | 426 | | private static void AddRadiusOccupantsTo<T>( |
| | | 427 | | GridWorld world, |
| | | 428 | | Vector3d position, |
| | | 429 | | Fixed64 radius, |
| | | 430 | | SwiftList<T> results, |
| | | 431 | | Func<IVoxelOccupant, bool>? occupantCondition, |
| | | 432 | | Func<byte, bool>? groupCondition) where T : IVoxelOccupant |
| | | 433 | | { |
| | 0 | 434 | | Fixed64 squaredRadius = radius * radius; |
| | 0 | 435 | | Vector3d boundsMin = position - radius; |
| | 0 | 436 | | Vector3d boundsMax = position + radius; |
| | 0 | 437 | | SwiftList<ScanCell> scanCells = SwiftListPool<ScanCell>.Shared.Rent(); |
| | | 438 | | |
| | | 439 | | try |
| | | 440 | | { |
| | 0 | 441 | | GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scanCells); |
| | | 442 | | |
| | 0 | 443 | | for (int i = 0; i < scanCells.Count; i++) |
| | | 444 | | { |
| | 0 | 445 | | ScanCell scanCell = scanCells[i]; |
| | 0 | 446 | | if (scanCell.IsOccupied) |
| | 0 | 447 | | scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondit |
| | | 448 | | } |
| | 0 | 449 | | } |
| | | 450 | | finally |
| | | 451 | | { |
| | 0 | 452 | | SwiftListPool<ScanCell>.Shared.Release(scanCells); |
| | 0 | 453 | | } |
| | 0 | 454 | | } |
| | | 455 | | |
| | | 456 | | private static void AddRadiusOccupantsTo<T>( |
| | | 457 | | GridWorld world, |
| | | 458 | | Vector3d position, |
| | | 459 | | Fixed64 radius, |
| | | 460 | | SwiftList<T> results, |
| | | 461 | | GridScanScratch scratch, |
| | | 462 | | Func<IVoxelOccupant, bool>? occupantCondition, |
| | | 463 | | Func<byte, bool>? groupCondition) where T : IVoxelOccupant |
| | | 464 | | { |
| | 1 | 465 | | Fixed64 squaredRadius = radius * radius; |
| | 1 | 466 | | Vector3d boundsMin = position - radius; |
| | 1 | 467 | | Vector3d boundsMax = position + radius; |
| | | 468 | | |
| | 1 | 469 | | GridTracer.AddCoveredScanCellsTo(world, boundsMin, boundsMax, scratch.ScanCells, scratch); |
| | | 470 | | |
| | 10 | 471 | | for (int i = 0; i < scratch.ScanCells.Count; i++) |
| | | 472 | | { |
| | 4 | 473 | | ScanCell scanCell = scratch.ScanCells[i]; |
| | 4 | 474 | | if (scanCell.IsOccupied) |
| | 1 | 475 | | scanCell.AddOccupantsWithinRadiusTo(results, position, squaredRadius, occupantCondition, groupCondition) |
| | | 476 | | } |
| | 1 | 477 | | } |
| | | 478 | | |
| | | 479 | | #endregion |
| | | 480 | | } |