Raycast up slope to find the peak in the terrain.


I’m trying to programmatically find the peak of a terrain slope by incrementally raycasting up the slope until I don’t hit the terrain any more, and I’m having trouble remembering the trig function to figure out how to find a spot to raycast from.

I’m raycasting downward evenly across the terrain, and storing the locations where the hit.normal angle is greater that 30 degrees, then looping through those points to find the approximate peak of the slope. So the blue line is the ray down, the green line is the normal, and I’m trying to determine the Vector3 of the orange arrow and the direction for the Red raycast back to the terrain.


To find the peaks in the terrain like here:

So basically I’m trying to remember how to find a spot on the green line that corresponds to creating a right angle on the blue line.

I have:

    private void CreateTerrainLedges(List<Vector3> points)
        foreach (var point points)
            bool isPeak = true;
            var hits = new List<RaycastHit>();
            var rayOrigin = point + Vector3.up; // + whatever offset for the normal
            var dir = new Vector3(point.x, point.y + Vector3.up, point.z);
            var rayDirection = (dir - rayOrigin).normalized;
            var ray = new Ray(rayOrigin, rayDirection);
            var top = RayToTop(ray, hits); // recursively raycast to find approx top
            // do stuff with the top point

    private RaycastHit RayToTop(Ray ray, List<RaycastHit> hits)
        if (Physics.Raycast(ray, out RaycastHit hit, 2.5f, gridLayerMask))
            var rayOrigin = new Vector3(hit.point.x, hit.point.y + .2f, hit.point.z);
            Ray newRay = new Ray(rayOrigin, ray.direction);
            return RayToTop(newRay, hits);
        return hits.Last();

Here is an explanation using that methodology (i.e. the first part of the experiment)



That said: Given that that you have more data than that available I probably wouldn’t use that but instead use an actual hillclimbing algorithm or if its static just cache the local maximas and then derive them from closest distance.

Or you know? Raycast downwards from vertical instead and use the position of the first ray hit?