private void FindForestInitialCandidate() { BoundingBoxD groundBox = m_ground.PositionComp.WorldAABB; Vector3D boxSize = groundBox.Size; boxSize *= 0.1f; groundBox.Inflate(-boxSize); MyBBSetSampler sampler = new MyBBSetSampler(groundBox.Min, groundBox.Max); bool posIsValid = true; Vector3D worldPos = default(Vector3D); int counter = 0; do { // find random position for starting worldPos = sampler.Sample(); var worldPosProjected = worldPos; worldPosProjected.Y = 0.5f; posIsValid = true; counter++; Vector3D areaCheck = new Vector3D(20, 20, 20); foreach (var enqueued in m_initialForestLocations) { // only interested in XZ plane BoundingBoxD tmp = new BoundingBoxD(enqueued - areaCheck, enqueued + areaCheck); tmp.Min.Y = 0; tmp.Max.Y = 1; if (tmp.Contains(worldPosProjected) == ContainmentType.Contains) { posIsValid = false; break; } } } while (!posIsValid && counter != 10); if (!posIsValid) { // could not find any position return; } var lineStart = new Vector3D(worldPos.X, groundBox.Max.Y, worldPos.Z); var lineEnd = new Vector3D(worldPos.X, groundBox.Min.Y, worldPos.Z); LineD line = new LineD(lineStart, lineEnd); VRage.Game.Models.MyIntersectionResultLineTriangleEx? result = null; var correctGroundDefinition = MyDefinitionManager.Static.GetVoxelMaterialDefinition("Grass"); var materialId = correctGroundDefinition.Index; if (m_ground.GetIntersectionWithLine(ref line, out result, VRage.Game.Components.IntersectionFlags.DIRECT_TRIANGLES)) { Vector3D intersectionPoint = result.Value.IntersectionPointInWorldSpace; Vector3I voxelCoord, minRead, maxRead; MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_ground.PositionLeftBottomCorner, ref intersectionPoint, out voxelCoord); minRead = voxelCoord - Vector3I.One; maxRead = voxelCoord + Vector3I.One; m_ground.Storage.ReadRange(m_voxelCache, MyStorageDataTypeFlags.Material, 0, ref minRead, ref maxRead); var minLocal = Vector3I.Zero; var maxLocal = Vector3I.One * 2; var it = new Vector3I_RangeIterator(ref minLocal, ref maxLocal); while (it.IsValid()) { var vec = it.Current; var material = m_voxelCache.Material(ref vec); if (material == materialId) { // found a location var desired = voxelCoord - Vector3I.One + vec; Vector3D desiredWorldPosition = default(Vector3D); MyVoxelCoordSystems.VoxelCoordToWorldPosition(m_ground.PositionLeftBottomCorner, ref desired, out desiredWorldPosition); m_initialForestLocations.Enqueue(desiredWorldPosition); break; } it.MoveNext(); } } }
private bool TryFindLocationOutsideForestInternal(Vector3D? desiredLocationSize, out Vector3D location, Predicate<AreaData> predicate = null) { Vector3D desiredHalfSize = desiredLocationSize.HasValue ? desiredLocationSize.Value * 0.5f : Vector3D.Zero; desiredHalfSize.Y = 0; if (m_highLevelBoxes.Count == 0) { // no forest on the map, generate starting point bool valid = false; while (m_initialForestLocations.Count > 0 && !valid) { var potentialTreePosition = m_initialForestLocations.Dequeue(); valid = true; BoundingBoxD itemBox = new BoundingBoxD(potentialTreePosition, potentialTreePosition); itemBox.Inflate(desiredHalfSize); var entities = MyEntities.GetEntitiesInAABB(ref itemBox); foreach (var entity in entities) { if (entity is MyEnvironmentItems) continue; if (entity is MyVoxelBase) continue; var entityBox = entity.PositionComp.WorldAABB; var containment = entityBox.Intersects(itemBox); if (containment) { valid = false; break; } } entities.Clear(); if (valid) { Vector3D end = potentialTreePosition; end.Y -= 20; if (RaycastForExactPosition(potentialTreePosition, end, out location)) { d_foundEnlargingPoints.Add(location); return true; } else { valid = false; } } } location = Vector3D.Zero; return false; } else { if (!TryGetRandomAreas(m_tmpAreas)) { location = Vector3D.Zero; return false; } int areaIdx = 0; int randomStartIdx = MyUtils.GetRandomInt(m_tmpAreas.Count); while (areaIdx < m_tmpAreas.Count) { var spawnArea = m_tmpAreas[randomStartIdx]; randomStartIdx = (randomStartIdx + 1) % m_tmpAreas.Count; areaIdx++; if (!spawnArea.IsValid || spawnArea.IsFull) continue; if (predicate != null && !predicate(spawnArea.GetAreaData())) { spawnArea.IsFull = true; continue; } var spawnBox = spawnArea.ForestBox; var forestBox = spawnArea.ForestBox; spawnBox = forestBox.Inflate(desiredHalfSize); spawnBox.Inflate(new Vector3D(0.2, 0, 0.2)); // inflate for some minimum size MyBBSetSampler setSampler = new MyBBSetSampler(spawnBox.Min, spawnBox.Max); setSampler.SubtractBB(ref forestBox); RefineSampler(spawnArea, ref spawnBox, ref desiredHalfSize, setSampler); if (!setSampler.Valid) continue; Vector3D exactLocation; Vector3D samplePosition = setSampler.Sample(); if (TryGetExactLocation(spawnArea, samplePosition, 40, out exactLocation)) { location = exactLocation; d_foundEnlargingPoints.Add(exactLocation); m_tmpAreas.Clear(); return true; } else { location = Vector3D.Zero; m_tmpAreas.Clear(); return false; } } } location = Vector3D.Zero; m_tmpAreas.Clear(); return false; }
private void RefineSampler(Area spawnArea, ref BoundingBoxD spawnBox, ref Vector3D desiredHalfSize, MyBBSetSampler setSampler) { var entities = MyEntities.GetEntitiesInAABB(ref spawnBox); foreach (var entity in entities) { if (entity is MyEnvironmentItems) continue; if (entity is MyVoxelBase) continue; var entityBox = entity.PositionComp.WorldAABB; entityBox.Inflate(desiredHalfSize); entityBox.Min.Y = DEBUG_BOX_Y_MIN_POS; entityBox.Max.Y = DEBUG_BOX_Y_MAX_POS; setSampler.SubtractBB(ref entityBox); } entities.Clear(); m_aabbTree.OverlapAllBoundingBox(ref spawnBox, m_tmpAreas2); foreach (var area in m_tmpAreas2) { if (area != spawnArea) { var box = area.ForestBox; box.Inflate(desiredHalfSize); setSampler.SubtractBB(ref box); } } m_tmpAreas2.Clear(); }
private bool TryFindLocationInsideForestInternal(Vector3D? desiredLocationSize, out Vector3D location, Predicate<AreaData> predicate = null) { if (!TryGetRandomAreas(m_tmpAreas)) { location = Vector3D.Zero; return false; } Vector3D desiredHalfSize = desiredLocationSize.HasValue ? desiredLocationSize.Value * 0.5f : Vector3D.Zero; desiredHalfSize.Y = 0; int areaIdx = 0; int randomStartIdx = MyUtils.GetRandomInt(m_tmpAreas.Count); while (areaIdx < m_tmpAreas.Count) { var spawnArea = m_tmpAreas[randomStartIdx]; randomStartIdx = (randomStartIdx + 1) % m_tmpAreas.Count; areaIdx++; if (!spawnArea.IsValid || spawnArea.IsFull) continue; if (predicate != null && !predicate(spawnArea.GetAreaData())) { spawnArea.IsFull = true; continue; } var spawnBox = spawnArea.ForestBox; MyBBSetSampler setSampler = new MyBBSetSampler(spawnBox.Min, spawnBox.Max); RefineSampler(spawnArea, ref spawnBox, ref desiredHalfSize, setSampler); if (!setSampler.Valid) continue; Vector3D exactLocation; if (TryGetExactLocation(spawnArea, setSampler.Sample(), 10, out exactLocation)) { location = exactLocation; d_foundEnrichingPoints.Add(exactLocation); m_tmpAreas.Clear(); if (SelectedArea != null) SelectedArea(spawnArea.ProxyId); return true; } } location = Vector3D.Zero; m_tmpAreas.Clear(); return false; }