Example #1
0
        public StepVectors(Vector3I up)
        {
            if (up.RectangularLength() != 1)
            {
                throw new ArgumentException("Up must be a unit vector.");
            }

            Steps[UpIdx]   = up;
            Steps[DownIdx] = -up;

            // We don't care which side is actually forward, we just don't want to travel up or down.
            // Maybe there is some clever math how to do this transformation.
            if (up.Z == 0)
            {
                Steps[FwdIdx] = Vector3I.Forward;

                Steps[RightIdx] = (up.X == 0) ? Vector3I.Right : Vector3I.Up;
            }
            else // Z != 0  -> the other two dimensions should be "free" to use for side directions
            {
                if (up.X != 0 || up.Y != 0)
                {
                    throw new ArgumentException("X and Y of the Up vector expected to be 0.");
                }

                Steps[FwdIdx]   = Vector3I.Up;
                Steps[RightIdx] = Vector3I.Right;
            }

            Steps[LeftIdx] = -Right;
            Steps[BackIdx] = -Forward;
        }
        private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
        {
            // The triangle parent can be wrong when we have multiple navmeshes connected via external edges
            if (triangle.Parent != m_mesh)
            {
                return(false);
            }

            // Previously unvisited triangle will be assigned the current relative component index
            if (triangle.ComponentIndex == -1)
            {
                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                m_tmpComponentTriangles.Add(triangle);
                triangle.ComponentIndex = m_currentComponentMarker;
                return(true);
            }
            else if (triangle.ComponentIndex == m_currentComponentMarker)
            {
                // We can safely ignore this triangle (it has already been processed);
                return(true);
            }
            else
            {
                ulong cellIndex;
                if (m_navmeshComponents.GetComponentCell(triangle.ComponentIndex, out cellIndex))
                {
                    MyCellCoord cellCoord = new MyCellCoord();
                    cellCoord.SetUnpack(cellIndex);
                    Vector3I diff = cellCoord.CoordInLod - m_currentCell;
                    if (diff.RectangularLength() != 1)
                    {
                        // CH: TODO: Connection of components over cell edges or vertices. I currently silently ignore that...
                        return(false);
                    }

                    ConnectionInfo connection = new ConnectionInfo();
                    connection.Direction      = Base6Directions.GetDirection(diff);
                    connection.ComponentIndex = triangle.ComponentIndex;

                    // Save connections to other components. There won't be so many, so we can keep them in a list instead of a HashSet
                    if (!m_currentCellConnections[m_currentComponentRel].Contains(connection))
                    {
                        m_currentCellConnections[m_currentComponentRel].Add(connection);
                    }
                }
            }
            return(false);
        }
Example #3
0
            public Vector3ILineIterator(Vector3I start, Vector3I end)
            {
                if (start == end)
                {
                    throw new ArgumentException("Start and end cannot be equal");
                }

                _start     = start;
                _end       = end;
                Current    = start;
                _direction = Vector3I.Clamp(end - start, -Vector3I.One, Vector3I.One);

                if (_direction.RectangularLength() > 1)
                {
                    throw new ArgumentException("Start and end are not in a straight line");
                }
            }
Example #4
0
 private bool ProcessTriangleForHierarchy(MyNavigationTriangle triangle)
 {
     if (ReferenceEquals(triangle.Parent, this.m_mesh))
     {
         ulong num;
         if (triangle.ComponentIndex == -1)
         {
             this.m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
             this.m_tmpComponentTriangles.Add(triangle);
             triangle.ComponentIndex = this.m_currentComponentMarker;
             return(true);
         }
         if (triangle.ComponentIndex == this.m_currentComponentMarker)
         {
             return(true);
         }
         if (this.m_navmeshComponents.GetComponentCell(triangle.ComponentIndex, out num))
         {
             MyCellCoord coord = new MyCellCoord();
             coord.SetUnpack(num);
             Vector3I vec = coord.CoordInLod - this.m_currentCell;
             if (vec.RectangularLength() != 1)
             {
                 return(false);
             }
             ConnectionInfo item = new ConnectionInfo {
                 Direction      = Base6Directions.GetDirection(vec),
                 ComponentIndex = triangle.ComponentIndex
             };
             if (!this.m_currentCellConnections[this.m_currentComponentRel].Contains(item))
             {
                 this.m_currentCellConnections[this.m_currentComponentRel].Add(item);
             }
         }
     }
     return(false);
 }
        public void InitOrientation(ref Vector3I forward, ref Vector3I up)
        {
            Debug.Assert(forward.RectangularLength() == 1 && up.RectangularLength() == 1);
            Debug.Assert(Vector3I.Dot(ref forward, ref up) == 0);

            InitOrientation(Base6Directions.GetDirection(forward), Base6Directions.GetDirection(up));
        }
Example #6
0
        /// <summary>
        /// Yields the first occupied cells encountered when raycasting a grid in a given base direction.
        /// </summary>
        /// <param name="grid">The grid to get blocks from.</param>
        /// <param name="baseDirection">The direction of ray.</param>
        public static IEnumerable <Vector3I> FirstBlocks(this IMyCubeGrid grid, Vector3I baseDirection)
        {
            Logger.DebugLog("baseDirection(" + baseDirection + ") has a magnitude", Logger.severity.FATAL, condition: baseDirection.RectangularLength() != 1);

            BoundingBox localAABB = grid.LocalAABB;

            Vector3I min = grid.Min, max = grid.Max;

            // ???
            //Vector3 minF; Vector3.Divide(ref localAABB.Min, grid.GridSize, out minF);
            //Vector3 maxF; Vector3.Divide(ref localAABB.Max, grid.GridSize, out maxF);
            //Vector3I min, max;

            //Func<float, int> round = f => (int)Math.Round(f);
            //minF.ApplyOperation(round, out min);
            //maxF.ApplyOperation(round, out max);

            Vector3I perp0, perp1;

            perp0 = Base6Directions.GetIntVector(Base6Directions.GetPerpendicular(Base6Directions.GetDirection(baseDirection)));
            Vector3I.Cross(ref baseDirection, ref perp0, out perp1);

            int baseStart; Vector3I.Dot(ref baseDirection, ref min, out baseStart);
            int baseEnd; Vector3I.Dot(ref baseDirection, ref max, out baseEnd);

            if (baseStart > baseEnd)
            {
                int temp = baseStart;
                baseStart = baseEnd;
                baseEnd   = temp;
            }
            bool incrementBase = baseStart <= baseEnd;

            int perp0Min; Vector3I.Dot(ref perp0, ref min, out perp0Min);
            int perp0Max; Vector3I.Dot(ref perp0, ref max, out perp0Max);

            if (perp0Max < perp0Min)
            {
                int temp = perp0Max;
                perp0Max = perp0Min;
                perp0Min = temp;
            }

            int perp1Min; Vector3I.Dot(ref perp1, ref min, out perp1Min);
            int perp1Max; Vector3I.Dot(ref perp1, ref max, out perp1Max);

            if (perp1Max < perp1Min)
            {
                int temp = perp1Max;
                perp1Max = perp1Min;
                perp1Min = temp;
            }

            Logger.TraceLog("min: " + min + ", max: " + max, Logger.severity.DEBUG);
            Logger.TraceLog("base: " + baseDirection + ", perp0: " + perp0 + ", perp1: " + perp1, Logger.severity.DEBUG);
            Logger.TraceLog("base range: " + baseStart + ":" + baseEnd, Logger.severity.DEBUG);
            Logger.TraceLog("perp0 range: " + perp0Min + ":" + perp0Max, Logger.severity.DEBUG);
            Logger.TraceLog("perp1 range: " + perp1Min + ":" + perp1Max, Logger.severity.DEBUG);

            for (int perp0Value = perp0Min; perp0Value <= perp0Max; perp0Value++)
            {
                for (int perp1Value = perp1Min; perp1Value <= perp1Max; perp1Value++)
                {
                    int baseValue = baseStart;
                    while (true)
                    {
                        Vector3I cell = baseValue * baseDirection + perp0Value * perp0 + perp1Value * perp1;

                        if (grid.CubeExists(cell))
                        {
                            yield return(cell);

                            break;
                        }

                        if (baseValue == baseEnd)
                        {
                            break;
                        }
                        if (incrementBase)
                        {
                            baseValue++;
                        }
                        else
                        {
                            baseValue--;
                        }
                    }
                }
            }

            yield break;
        }