- Home /
How do I find slope on a spherical terrain
I have a generated spherical mesh terrain with collider and I need to find if the slope of a triangle at a given point is too steep. I want to only find points with slope close to flat terrain. Basically I need to compare the normal of the triangle to something, however comparing it to Vector3.up doesn't quite do the trick. And it also returns angles greater than 90, I would expect angles to be only on the range [0, 90]. Don't need solutions involving raycasting. There must be a way to do it with just vectors.
Way to unspecific question. What exactly do you understand by "sphere with terrain"? How is that terrain generated? How is it represented? Is it a mesh or a collection of meshes? Do the mesh objects have a mesh collider?
Answer by Bunny83 · Aug 27, 2017 at 10:23 PM
So if I understand your question correctly you basically have a large sphere mesh with uneven surface which probably resembles a planet like object. What you want to know is the angle between the surface normal of your terrain compared to the normal of the reference sphere at the same point.
The normal of the reference sphere can simply be gathered by taking the worldspace position on the surface of your object and subtract the center of your sphere and normalize the result.
Now you just need to use Vector3.Angle between that reference normal and your surface normal. You can get the surface normal by using a raycast against the MeshCollider of your sphere mesh.
Here's an image that shows what i mean:
I think you got the idea, but not sure if I understand what you mean. So you are saying having the normal of the point on terrain I find:
v1 = normal - centre
then i compare Vector3.Angle(v1.normalized, normal.normalized)? Tried it and doesn't quite work.
No, you should do:
refNormal = (p - center).normalized;
and then just do
Vector3.Angle(refNormal, surfaceNormal)
p is the point on the terrain in worldspace coordinates from which you want to know the normal of. and surfaceNormal is the normal vector you usually get from a raycasting onto a $$anonymous$$eshCollider. (hit.normal).
Thanks a lot, it finally worked. I was just not normalizing the whole (p - centre) and in my case I had to do it with Quaternions. And I was stupidly not realizing that flat terrain means angle of 0 between the vectors.
Answer by unidad2pete · Aug 27, 2017 at 09:57 PM
If you need get a Vector3 on mesh , I dont have idea how do it without raycasting.
But with only one Linecast you can do it.
public LayerMask yourLayer;
public float distanceToYourFoot; // the distance of your player to you foot (if your player scale is Vector3(x, 2, z) your position is (x, 1, z) distance = 2 (high) - 1 (position)
RaycastHit hit;
float angle;
private void Update()
{
if(Physics.Linecast(transform.position + transform.forward + Vector3.up * 100, transform.position + transform.forward - Vector3.up * 10, out hit, yourLayer))
{
Debug.DrawLine(transform.position + transform.forward + Vector3.up * 100, transform.position + transform.forward - Vector3.up * 10, Color.red); //Print the line of the LineCast
Debug.DrawLine(transform.position + Vector3.down * distanceToYourFoot, hit.point, Color.green); // Print a Line starting on your position, to direction you are loocking arround the terrain.
angle = Vector3.Angle(hit.point - transform.position + Vector3.down * distanceToYourFoot, transform.forward);
// Value 45 represent just a straight line , the floor is plane, value 90 is a wall
// You can get your value based on 0 with
// angle -= 45; Now 0 is plane, 45 is a wall
print(angle);
}
}
You only need adjust values to your preferences of distances to check and directions.