public void MarkBoxForAddition(BoundingBoxD box) { ProfilerShort.Begin("VoxelNavMesh.MarkBoxForAddition"); Vector3I pos, end; MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxelMap.PositionLeftBottomCorner, ref box.Min, out pos); MyVoxelCoordSystems.WorldPositionToVoxelCoord(m_voxelMap.PositionLeftBottomCorner, ref box.Max, out end); m_voxelMap.Storage.ClampVoxelCoord(ref pos); m_voxelMap.Storage.ClampVoxelCoord(ref end); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref pos, out pos); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref end, out end); Vector3 center = pos + end; center = center * 0.5f; pos /= 1 << NAVMESH_LOD; end /= 1 << NAVMESH_LOD; for (var it = new Vector3I.RangeIterator(ref pos, ref end); it.IsValid(); it.GetNext(out pos)) { if (!m_processedCells.Contains(ref pos) && !m_markedForAddition.Contains(ref pos)) { float weight = 1.0f / (0.01f + Vector3.RectangularDistance(pos, center)); if (!m_toAdd.Full) { m_toAdd.Insert(pos, weight); m_markedForAddition.Add(ref pos); } else { float min = m_toAdd.MinKey(); if (weight > min) { Vector3I posRemoved = m_toAdd.RemoveMin(); m_markedForAddition.Remove(ref posRemoved); m_toAdd.Insert(pos, weight); m_markedForAddition.Add(ref pos); } } } } ProfilerShort.End(); }
public void RemoveTooFarCells(List <Vector3D> importantPositions, float maxDistance, MyVector3ISet processedCells) { // remove too far high level info (if it isn't in processed cells) m_removedHLpackedCoord.Clear(); foreach (var cell in m_exploredCells) { Vector3D worldCellCenterPos; Vector3I cellPos = cell; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(m_mesh.VoxelMapReferencePosition, ref cellPos, out worldCellCenterPos); // finding of distance from the nearest important object float dist = float.PositiveInfinity; foreach (Vector3D vec in importantPositions) { float d = Vector3.RectangularDistance(vec, worldCellCenterPos); if (d < dist) { dist = d; } } if (dist > maxDistance && !processedCells.Contains(cellPos)) { MyCellCoord coord = new MyCellCoord(MyVoxelNavigationMesh.NAVMESH_LOD, cellPos); m_removedHLpackedCoord.Add(coord.PackId64()); } } foreach (ulong coord in m_removedHLpackedCoord) { TryClearCell(coord); } }
public void RemoveTooFarCells(List <Vector3D> importantPositions, float maxDistance, MyVector3ISet processedCells) { m_removedHLpackedCoord.Clear(); foreach (Vector3I vectori in this.m_exploredCells) { Vector3D vectord; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(this.m_mesh.VoxelMapReferencePosition, ref vectori, out vectord); float positiveInfinity = float.PositiveInfinity; using (List <Vector3D> .Enumerator enumerator2 = importantPositions.GetEnumerator()) { while (enumerator2.MoveNext()) { float num2 = Vector3.RectangularDistance(enumerator2.Current, (Vector3)vectord); if (num2 < positiveInfinity) { positiveInfinity = num2; } } } if ((positiveInfinity > maxDistance) && !processedCells.Contains(vectori)) { m_removedHLpackedCoord.Add(new MyCellCoord(0, vectori).PackId64()); } } foreach (ulong num3 in m_removedHLpackedCoord) { this.TryClearCell(num3); } }
public void InvalidateRange(Vector3I minVoxelChanged, Vector3I maxVoxelChanged) { minVoxelChanged -= MyPrecalcComponent.InvalidatedRangeInflate; maxVoxelChanged += MyPrecalcComponent.InvalidatedRangeInflate; m_voxelMap.Storage.ClampVoxelCoord(ref minVoxelChanged); m_voxelMap.Storage.ClampVoxelCoord(ref maxVoxelChanged); Vector3I minCell, maxCell; MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref minVoxelChanged, out minCell); MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref maxVoxelChanged, out maxCell); Vector3I currentCell = minCell; for (var it = new Vector3I.RangeIterator(ref minCell, ref maxCell); it.IsValid(); it.GetNext(out currentCell)) { if (m_processedCells.Contains(ref currentCell)) { RemoveCell(currentCell); } MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, currentCell); m_higherLevelHelper.TryClearCell(coord.PackId64()); } }
public IMyHighLevelComponent GetComponent(MyHighLevelPrimitive primitive) { ulong cellIndex; if (m_navmeshComponents.GetComponentCell(primitive.Index, out cellIndex)) { Base6Directions.DirectionFlags exploredDirections; if (m_navmeshComponents.GetComponentInfo(primitive.Index, cellIndex, out exploredDirections)) { MyCellCoord coord = new MyCellCoord(); coord.SetUnpack(cellIndex); // Look at present unexplored cells around this cell. // Their direction can be marked as explored, because there was no geometry when they were being explored foreach (var direction in Base6Directions.EnumDirections) { var directionFlag = Base6Directions.GetDirectionFlag(direction); if (exploredDirections.HasFlag(directionFlag)) { continue; } Vector3I neighbor = coord.CoordInLod + Base6Directions.GetIntVector(direction); if (m_exploredCells.Contains(ref neighbor)) { exploredDirections |= directionFlag; } } return(new Component(primitive.Index, exploredDirections)); } else { return(null); } } else { return(null); } }
private void MergeFromAnotherMesh(MyGridNavigationMesh otherMesh, ref MatrixI transform) { ProfilerShort.Begin("MergeFromAnotherMesh"); m_mergeHelper.Clear(); // Save the cubes from the other mesh that are touching cubes of this mesh into a helper set. // Also put the touched cubes from this mesh into the set. foreach (var position in otherMesh.m_smallTriangleRegistry.Keys) { bool add = false; foreach (var direction in Base6Directions.IntDirections) { // CH: TODO: We query the grid so far, but in the future, we should make sure that the access is thread-safe Vector3I pos = Vector3I.Transform(position + direction, transform); if (m_cubeSet.Contains(ref pos)) // Test the transformed position... { m_mergeHelper.Add(position + direction); // ... but add the original one add = true; } } if (add) { m_mergeHelper.Add(position); } } foreach (var entry in otherMesh.m_smallTriangleRegistry) { Vector3I originalCube = entry.Key; Vector3I tformedCube; Vector3I.Transform(ref originalCube, ref transform, out tformedCube); // If the cube is one of the touching cubes, we have to intersect the touching triangles if (m_mergeHelper.Contains(originalCube)) { // Take the touching pairs one by one and calculate triangulation of the disjoint union of the opposing faces // Remove the opposing faces from the old block // Add the triangulation to the mesh // Add the rest of the navmesh from this block to the mesh m_tmpTriangleList.Clear(); // CH: TODO. Just remove the triangles now foreach (var direction in Base6Directions.EnumDirections) { Vector3I directionVec = Base6Directions.GetIntVector((int)direction); Base6Directions.Direction tformedDirection = transform.GetDirection(direction); Vector3I tformedFlippedVec = Base6Directions.GetIntVector((int)Base6Directions.GetFlippedDirection(tformedDirection)); // Remove face triangles from this mesh if (m_mergeHelper.Contains(originalCube + directionVec)) { List <int> triList = null; if (m_smallTriangleRegistry.TryGetValue(tformedCube - tformedFlippedVec, out triList)) { foreach (var index in triList) { var triangle = GetTriangle(index); // CH: TODO: This will probably be expensive. Could we precalculate it? if (IsFaceTriangle(triangle, tformedCube - tformedFlippedVec, tformedFlippedVec)) { m_tmpTriangleList.Add(new KeyValuePair <MyNavigationTriangle, Vector3I>(triangle, tformedCube - tformedFlippedVec)); } } } } } foreach (var triangle in m_tmpTriangleList) { RemoveTriangle(triangle.Key, triangle.Value); } m_tmpTriangleList.Clear(); int debugCounter = 0; // CH: TODO: optimize this (actually whole this method) foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); Vector3I pos = entry.Key; bool addTriangle = true; foreach (var direction in Base6Directions.EnumDirections) { Vector3I dirvec = Base6Directions.GetIntVector((int)direction); if (m_mergeHelper.Contains(pos + dirvec) && IsFaceTriangle(triangle, pos, dirvec)) { addTriangle = false; break; } } if (addTriangle) { if (debugCounter == 5) { } CopyTriangle(triangle, pos, ref transform); debugCounter++; } } } // Otherwise, we just transform the triangles from the other mesh and add them to this mesh else { foreach (var triangleIndex in entry.Value) { var triangle = otherMesh.GetTriangle(triangleIndex); CopyTriangle(triangle, entry.Key, ref transform); //if (triangleIndex > 1) break; } } } m_mergeHelper.Clear(); ProfilerShort.End(); }
public void RemoveTooFarCells(List<Vector3D> importantPositions, float maxDistance, MyVector3ISet processedCells) { // remove too far high level info (if it isn't in processed cells) m_removedHLpackedCoord.Clear(); foreach (var cell in m_exploredCells) { Vector3D worldCellCenterPos; Vector3I cellPos = cell; MyVoxelCoordSystems.GeometryCellCenterCoordToWorldPos(m_mesh.VoxelMapReferencePosition, ref cellPos, out worldCellCenterPos); // finding of distance from the nearest important object float dist = float.PositiveInfinity; foreach (Vector3D vec in importantPositions) { float d = Vector3.RectangularDistance(vec, worldCellCenterPos); if (d < dist) dist = d; } if (dist > maxDistance && !processedCells.Contains(cellPos)) { MyCellCoord coord = new MyCellCoord(MyVoxelNavigationMesh.NAVMESH_LOD, cellPos); m_removedHLpackedCoord.Add(coord.PackId64()); } } foreach(ulong coord in m_removedHLpackedCoord) { TryClearCell(coord); } }