private List <MyEntity> EntitiesInLargeAABB(BoundingBoxD start, BoundingBoxD end) { Vector3D[] pathPoints = new Vector3D[4]; pathPoints[0] = start.Min; pathPoints[1] = start.Max; pathPoints[2] = end.Min; pathPoints[3] = end.Max; BoundingBoxD PathAABB = BoundingBoxD.CreateFromPoints(pathPoints); //m_logger.debugLog("Path AABB = " + PathAABB, "EntitiesInLargeAABB()"); m_offenders.Clear(); MyGamePruningStructure.GetTopMostEntitiesInBox(ref PathAABB, m_offenders); m_offRemove.Clear(); for (int i = 0; i < m_offenders.Count; i++) { if (!collect_Entity(m_grid, m_offenders[i]) || (m_ignoreEntity != null && m_ignoreEntity == m_offenders[i])) { //m_logger.debugLog("discarding: " + m_offenders[i].getBestName(), "EntitiesInLargeAABB()"); m_offRemove.Add(m_offenders[i]); } } for (int i = 0; i < m_offRemove.Count; i++) { m_offenders.Remove(m_offRemove[i]); } return(m_offenders); }
private HashSet <IMyEntity> EntitiesInLargeAABB(BoundingBoxD start, BoundingBoxD end) { List <Vector3D> PathPoints = new List <Vector3D>(); PathPoints.Add(start.Min); PathPoints.Add(start.Max); PathPoints.Add(end.Min); PathPoints.Add(end.Max); BoundingBoxD PathAABB = BoundingBoxD.CreateFromPoints(PathPoints); myLogger.debugLog("Path AABB = " + PathAABB, "EntitiesInLargeAABB()"); HashSet <IMyEntity> results = new HashSet <IMyEntity>(); MyAPIGateway.Entities.GetEntitiesInAABB_Safe_NoBlock(PathAABB, results, collect_Entities); return(results); }
/// <summary> /// <para>Test for entities intersecting a line segment.</para> /// </summary> /// <param name="world">Line to test for entities</param> /// <param name="pointOfIntersection">the point of contact between Line and intersecting entity</param> /// <param name="collect">Ignore entity if function returns false. Not tested against IMyCubeBlock</param> /// <param name="collect_CubeBlock">If null, do not ignore any IMyCubeBlock. Ignore IMyCubeBlock if function returns false</param> /// <param name="sort">entities will be sorted according to results of this function</param> /// <returns>An entity intersecting the Line</returns> /// <remarks> /// <para>For IMyCubeGrid, if a cell the line passes through is occupied, the cell is considered to be the point of intersection</para> /// <para>For entities that are not IMyCubeGrid, Line will be tested against IMyEntity.WorldVolume</para> /// </remarks> public static IMyEntity EntityOnLine(LineD world, out Vector3D?pointOfIntersection, Func <IMyEntity, bool> collect, Func <IMyCubeBlock, bool> collect_CubeBlock = null, Func <IMyEntity, double> sort = null) { if (collect == null) { throw new ArgumentNullException("collect"); } // Get entities in AABB Vector3D[] points = { world.From, world.To }; BoundingBoxD AABB = BoundingBoxD.CreateFromPoints(points); ICollection <IMyEntity> entitiesInAABB = MyAPIGateway.Entities.GetEntitiesInAABB_Safe(ref AABB); RayD worldRay = new RayD(world.From, world.Direction); if (sort != null) { SortedDictionary <double, IMyEntity> sortedEntities = new SortedDictionary <double, IMyEntity>(); foreach (IMyEntity entity in entitiesInAABB) { // filter entities if (entity is IMyCubeBlock || !collect(entity)) { continue; } sortedEntities.Add(sort(entity), entity); } entitiesInAABB = sortedEntities.Values; } foreach (IMyEntity entity in entitiesInAABB) { if (sort == null) { // filter entities if (entity is IMyCubeBlock || !collect(entity)) { continue; } } // ray cast IMyCubeGrid entityAsGrid = entity as IMyCubeGrid; if (entityAsGrid != null) { // TODO: test GetLineIntersectionExact... List <Vector3I> rayCastCells = new List <Vector3I>(); entityAsGrid.RayCastCells(world.From, world.To, rayCastCells); // I do not know if rayCastCells will be sorted foreach (Vector3I cell in rayCastCells) { IMySlimBlock block = entityAsGrid.GetCubeBlock(cell); if (block == null) { continue; } IMyCubeBlock FatBlock = block.FatBlock; if (FatBlock == null) { pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell); return(entityAsGrid); } else if (collect_CubeBlock == null || collect_CubeBlock(FatBlock)) { pointOfIntersection = entityAsGrid.GridIntegerToWorld(cell); return(entityAsGrid); } } } else { double tMin, tMax; if (entity.WorldVolume.IntersectRaySphere(worldRay, out tMin, out tMax)) { pointOfIntersection = tMin * worldRay.Direction + worldRay.Position; return(entity); } } } pointOfIntersection = null; return(null); }
public unsafe void ScanItems(int targetLod) { int lodDiff = MinimumScannedLod - targetLod; if (lodDiff < 1) { return; } int startingLod = MinimumScannedLod - 1; int totalItems = m_itemCountTotal; int[] localLodOffsets = new int[lodDiff]; for (int lod = startingLod; lod >= targetLod; --lod) { int count = m_scanHelper.GetItemsForLod(lod); localLodOffsets[lod - targetLod] = totalItems; // Using for cumulative sum totalItems += count; } List <MySurfaceParams> surfaceParams = new List <MySurfaceParams>(totalItems); // Step 1: Generate Points List <Vector3> points = new List <Vector3>(totalItems); /*if (m_environment.ScanningMethod == MyProceduralScanningMethod.Grid) * { * // compute non-centric basis for the grid method. * Vector3 start = -BasisX - BasisY; * * // has to be per lod otherwise we will have gaps. * for (int lod = startingLod; lod >= targetLod; --lod) * { * int relativeLod = lod - targetLod; * int count = lod > targetLod ? localLodOffsets[relativeLod - 1] - localLodOffsets[relativeLod] : totalItems - localLodOffsets[relativeLod]; * float root = (float)Math.Sqrt(count); * * int width = (int)Math.Ceiling(root); * int height = (int)Math.Floor(root); * * float hrecip = .5f / height; * float wrecip = .5f / width; * * Vector3 newBasisX = 2 * BasisX + wrecip; * Vector3 newBasisY = 2 * BasisY + hrecip; * * for (int x = 0; x < width; ++x) * for (int y = 0; y < height; ++y) * { * Vector3 pos = start + newBasisX * ((float)x / width) + newBasisY * ((float)y / height); * pos += newBasisX * m_itemPositionRng.NextFloat(-wrecip, wrecip) + newBasisY * m_itemPositionRng.NextFloat(-hrecip, hrecip); * points.Add(pos); * } * } * } * else*/ { // Random is default for (int i = 0; i < m_itemCountTotal; ++i) { points.Add(ComputeRandomItemPosition()); } } BoundingBoxD box = BoundingBoxD.CreateFromPoints(Bounds); // Step 2: Query surface Provider.Owner.QuerySurfaceParameters(WorldPos, ref box, points, surfaceParams); // Step 3: Select items to spawn Items.Capacity = Items.Count + points.Count; int locationOffset = 0; int itemOffset = 0; fixed(ItemInfo *items = Items.GetInternalArray()) fixed(MySurfaceParams * parms = surfaceParams.GetInternalArray()) for (int lod = startingLod; lod >= targetLod; --lod) { int relativeLod = lod - targetLod; // Count of items in this lod int count = lod > targetLod ? localLodOffsets[relativeLod - 1] - localLodOffsets[relativeLod] : totalItems - localLodOffsets[relativeLod]; // Scan those items. for (int i = 0; i < count; ++i) { //Debug.Assert(itemOffset < points.Count); var definition = GetItemForPosition(ref parms[itemOffset], lod); if (definition != null) { Vector3 up = -parms[itemOffset].Gravity; items[m_totalSpawned].Position = parms[itemOffset].Position; items[m_totalSpawned].ModelIndex = -1; items[m_totalSpawned].Rotation = Quaternion.CreateFromForwardUp(GetRandomPerpendicularVector(ref up, parms[itemOffset].Position.GetHashCode()), up); parms[locationOffset++] = parms[itemOffset]; items[m_totalSpawned].DefinitionIndex = definition.Index; var moduled = GetModule(definition); if (moduled != null) { MyLodEnvironmentItemSet set; if (!moduled.ItemsPerDefinition.TryGetValue(definition.Index, out set)) { moduled.ItemsPerDefinition[definition.Index] = set = new MyLodEnvironmentItemSet() { Items = new List <int>() }; } set.Items.Add(m_totalSpawned); } m_totalSpawned++; Debug.Assert(m_totalSpawned <= m_itemCountTotal); } itemOffset++; } ItemCountForLod[lod] = m_totalSpawned; foreach (var module in m_modules.Values) { if (module == null) { continue; } //if (module.Module.MaximumLodIndex >= relativeLod) foreach (var def in module.ItemsPerDefinition.Keys.ToArray()) { //Debug.Assert(lod <= 15 && lod >= 0); var set = module.ItemsPerDefinition[def]; //set.LodOffsets[lod] = set.Items.Count; module.ItemsPerDefinition[def] = set; } } } Items.SetSize(m_totalSpawned); // Update modules m_scanning = true; foreach (var moduleData in m_modules.Values) { if (moduleData == null) { continue; } moduleData.Module.ProcessItems(moduleData.ItemsPerDefinition, surfaceParams, new[] { 0, 0, 0, 0 }, startingLod, targetLod); } m_scanning = false; MinimumScannedLod = targetLod; }