# Question How to get all terrain points within a sphere?

Discussion in 'Scripting' started by FinTerra, Nov 30, 2023.

1. ### FinTerra

Joined:
May 1, 2015
Posts:
13
Hey all,

when using the unity terrain and determining a point on the terrain via raycast, I want to get a collection of terrain points that are within a sphere with the raycast point as the center.

Now, to get all the points within a vertical cylinder is easy: Just return all the points that are within a circle in the flat 2d heightmap.

However, this is not the same as comparing a sphere, see the attached image (black is the terrain, e.g., one steep peak, red is the sphere, blue is the cylinder, the striped areas are the parts of the terrain that are marked by the geometric shape). In this example, the cylinder would mark a lot more points than the sphere.

I realise that I can initially grab all the points within the cylinder and then sample the heights and compare their distance to the center of the sphere and exclude them if the distance is greater than the radius.

But I would like to know if I am missing a more efficient method here, like some inbuilt function I overlooked or use a vertex shader.

ps: I think you cannot access the vertex information of a terrain directly: here or here

File size:
24.3 KB
Views:
20
2. ### Thinted

Joined:
Nov 21, 2023
Posts:
2
1. Get points within a cylinder using the terrain's heightmap.
2. Sample heights to obtain 3D positions.
3. Exclude points whose distance from the sphere's center is greater than the sphere's radius.
4. Consider using optimizations like spatial partitioning and custom shaders for efficiency.
Vector3 raycastPoint = // Obtain raycast point

List<Vector3> pointsWithinSphere = new List<Vector3>();

foreach (Vector3 point in pointsInCylinder) {
Vector3 terrainPoint = GetTerrainPointFromHeightmap(point);
float distance = Vector3.Distance(terrainPoint, raycastPoint);

}
}
// pointsWithinSphere contains points within the sphere

Optimize using spatial data structures and custom shaders for better performance. Adjust parameters as needed for specific project requirements.

3. ### halley

Joined:
Aug 26, 2013
Posts:
2,297
They already said that they understood they COULD use the technique you described. You also should use the code tags to properly format your code so it's readable.

@FinTerra , if you have to iterate through all the points, you can at least check if it's inside the AABB of the sphere before calculating the distance. For a SphereCollider, this can be done with a collider's .bounds which is already calculated for you. Otherwise, check if the
``Mathf.Abs(xTerrainPoint - xSphereCenter) > sphereRadius``
then also check Y, then also check Z, and only calculate the distance if you're within all of those box dimensions.

4. ### zulo3d

Joined:
Feb 18, 2023
Posts:
775
I apologize if I'm wrong but Thinted's post is probably a ChatGPT suggestion. There shouldn't be any need for spatial partitioning as the GetHeights function will take the points of interest directly from the specified region of the height map. There's no searching required.

halley likes this.
5. ### halley

Joined:
Aug 26, 2013
Posts:
2,297
You're right that it can help but you're still going to want to do some calculations. GetHeights() is integer sample based, not world coordinate based. You should figure out what span of integer samples are within the world span of X and Z of interest. You can then still check the Y heights against the Y axis bounds of the sphere in question before you check if a hill or valley happens to poke into the sphere or not.

6. ### FinTerra

Joined:
May 1, 2015
Posts:
13
@halley, thanks yes the AABB will filter even more irrelevant points easily.

So, this sounds like I am not overlooking some built-in terrain method for this