示例#1
0
        /// <summary>
        /// Gets the point of the terrain that the mouse cursor is currently casting a ray to.
        /// Returns null if the ray range is surpassed.
        /// </summary>
        /// <param name="projectionMatrix">
        /// The projection matrix.
        /// </param>
        /// <param name="viewMatrix">
        /// The view matrix.
        /// </param>
        /// <param name="terrain">
        /// The terrain.
        /// </param>
        /// <returns>
        /// The <see cref="Vector3?"/>
        /// </returns>
        public static Vector3 GetTerrainPoint(
            GraphicsDevice device,
            Matrix projectionMatrix,
            Matrix viewMatrix,
            ITerrain terrain)
        {
            Ray ray = CastRay(device, projectionMatrix, viewMatrix);

            Vector3 currentTerrainPoint = BinarySplitSearch(0, Range, ray, terrain, BinarySplits);

            if (!IsIntersectionInRange(0, Range, ray, terrain))
            {
                currentTerrainPoint.Y = terrain.GetWorldHeight(currentTerrainPoint.X, currentTerrainPoint.Z);
            }

            return(currentTerrainPoint);
        }
示例#2
0
        /// <summary>
        /// Affects entities with gravity
        /// </summary>
        /// <param name="gameTime">
        /// The game time.
        /// </param>
        /// <param name="terrain">
        /// The terrain.
        /// </param>
        public void GravityAffect(GameTime gameTime, ITerrain terrain)
        {
            float height = terrain.GetWorldHeight(this.Position.X, this.Position.Z);

            if (this.Position.Y < height)
            {
                this.Position = new Vector3(this.Position.X, height, this.Position.Z);
            }
            else if (this.Position.Y > height || this.Weight < 0)
            {
                float y =
                    this.Position.Y -
                    (this.Weight *
                     (float)gameTime.ElapsedGameTime.TotalSeconds);

                y = y < height ? height : y;

                this.Position = new Vector3(this.Position.X, y, this.Position.Z);
            }
        }
示例#3
0
        /// <summary>
        /// Custom split binary search implementation.
        /// Returns the closest point projected from the mouse cursor
        /// to the terrain surface.
        /// </summary>
        /// <param name="start">
        /// The start.
        /// </param>
        /// <param name="finish">
        /// The finish.
        /// </param>
        /// <param name="ray">
        /// The ray.
        /// </param>
        /// <param name="terrain">
        /// The terrain.
        /// </param>
        /// <param name="binarySplits">
        /// The number of splits for the binary search.
        /// </param>
        /// <returns>
        /// The <see cref="Vector3"/>.
        /// </returns>
        private static Vector3 BinarySplitSearch(
            float start,
            float finish,
            Ray ray,
            ITerrain terrain,
            uint binarySplits = 1)
        {
            binarySplits = binarySplits == 0 ? 1 : binarySplits;

            Vector3[] endpoints = new Vector3[binarySplits];

            // The section size of each split
            float sectionSize = binarySplits > 0 ? (finish - start) / binarySplits : finish - start;

            bool found      = false;
            int  iterations = 0;

            for (uint i = 0; i < binarySplits; i++)
            {
                iterations++;
                float s = i * sectionSize;
                float f = (i + 1) * sectionSize;

                bool    intersectionFound = false;
                Vector3 endpoint          = BinarySearch(s, f, ray, terrain, out intersectionFound);

                if (intersectionFound)
                {
                    found = true;

                    float   height   = terrain.GetWorldHeight(endpoint.X, endpoint.Z);
                    Vector3 vertice  = new Vector3(endpoint.X, height, endpoint.Z);
                    float   distance = Vector3.Distance(endpoint, vertice);

                    // If the point found is in the seamless range
                    // skip the rest of the search and return it
                    if (distance <= SeamlessDistance)
                    {
                        return(endpoint);
                    }
                }

                endpoints[i] = endpoint;
            }

            // If no point was in intersection range with terrain during search
            // returns furthest point in range
            if (!found)
            {
                Vector3 furthestEndpoint = BinarySearch(start, finish, ray, terrain, out found);

                return(furthestEndpoint);
            }

            // Calculates the best result from all splits
            // Only reachable if no seamless result is found during split search
            Vector3 winner = endpoints[0];

            foreach (var endpoint in endpoints)
            {
                float   winnerHeight   = terrain.GetWorldHeight(winner.X, winner.Z);
                Vector3 winnerVertice  = new Vector3(winner.X, winnerHeight, winner.Z);
                float   winnerDistance = Vector3.Distance(winner, winnerVertice);

                float   height          = terrain.GetWorldHeight(endpoint.X, endpoint.Z);
                Vector3 currentVertice  = new Vector3(endpoint.X, height, endpoint.Z);
                float   currentDistance = Vector3.Distance(endpoint, currentVertice);

                if (currentDistance < winnerDistance)
                {
                    winner = endpoint;
                }
            }

            return(winner);
        }
示例#4
0
        /// <summary>
        /// Checks if the specified point is under the terrain
        /// </summary>
        /// <param name="testPoint">
        /// The test point.
        /// </param>
        /// <param name="terrain">
        /// The terrain.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private static bool IsUnderGround(Vector3 testPoint, ITerrain terrain)
        {
            float height = terrain.GetWorldHeight(testPoint.X, testPoint.Z);

            return(testPoint.Y < height);
        }
示例#5
0
        /// <summary>
        /// Snaps the entity Y position to the terrain Y at the specified point
        /// </summary>
        /// <param name="terrain">
        /// The terrain.
        /// </param>
        public void SnapToTerrainHeight(ITerrain terrain)
        {
            float height = terrain.GetWorldHeight(this.Position.X, this.Position.Z);

            this.Position = new Vector3(this.Position.X, height, this.Position.Z);
        }