- Home /
Finding if point is contained within irregular mesh
Is there something like bounds.Contain() that instead of returning true if a point is contained within a bounding box, returns true if the point is within the volume defined by the mesh collider? (So it would work if the mesh was a doughnut shape)
Check out this answer to a similar question: http://answers.unity3d.com/questions/611947/am-i-inside-a-volume-without-colliders.html#answer-832969
Answer by Eric5h5 · Feb 18, 2011 at 10:27 AM
There's nothing built-in, but you can make whatever functions you want. See here for a function that checks if a point is inside an arbitrary 2D shape.
edit (copy from wiki)
// Poly.cs
using UnityEngine;
public static class Poly
{
public static bool ContainsPoint(Vector2[] polyPoints, Vector2 p)
{
var j = polyPoints.Length - 1;
var inside = false;
for (int i = 0; i < polyPoints.Length; j = i++)
{
var pi = polyPoints[i];
var pj = polyPoints[j];
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) &&
(p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
inside = !inside;
}
return inside;
}
}
Eric, how in the world did you come up with that function? Totally sweet!
The Unity wiki does no longer exist. However we have the wayback machine (archive.org). So I fixed the link, again ^^.
Answer by IsGreen · Feb 05, 2014 at 08:20 PM
Script Action Video: http://www.youtube.com/watch?v=O2xcTvWBRiU#t=0
using UnityEngine;
using System.Collections;
public class csObject : MonoBehaviour {
public MeshCollider meshCollider;
public bool In;
public bool concaveHull;
public float distance=100f;
Ray right,left,up,down,forward,back,tempRay;
bool r,l,u,d,f,b;
RaycastHit rightHit = new RaycastHit();
RaycastHit leftHit = new RaycastHit();
RaycastHit upHit = new RaycastHit();
RaycastHit downHit = new RaycastHit();
RaycastHit forwardHit = new RaycastHit();
RaycastHit backHit = new RaycastHit();
RaycastHit tempHit = new RaycastHit();
void Start(){
right = new Ray(Vector3.zero , -Vector3.right);
left = new Ray(Vector3.zero , -Vector3.left);
up = new Ray(Vector3.zero , -Vector3.up);
down = new Ray(Vector3.zero , -Vector3.down);
forward = new Ray(Vector3.zero , -Vector3.forward);
back = new Ray(Vector3.zero , -Vector3.back);
tempRay = new Ray();
}
bool ConcaveHull(Ray ray, RaycastHit hit){
tempRay.origin = transform.position;
tempRay.direction = -ray.direction;
float customDistance = distance-hit.distance;
int lastPoint = hit.triangleIndex;
while(meshCollider.Raycast(tempRay, out tempHit, customDistance)){
if(tempHit.triangleIndex == lastPoint) break;
lastPoint = tempHit.triangleIndex;
customDistance = tempHit.distance;
ray.origin = -ray.direction * customDistance + transform.position;
if(!meshCollider.Raycast(ray, out tempHit, customDistance)) {
concaveHull = true;
return true;
}
if(tempHit.triangleIndex == lastPoint) break;
lastPoint = tempHit.triangleIndex;
customDistance -= tempHit.distance;
}
return false;
}
// Update is called once per frame
void FixedUpdate () {
right.origin = -right.direction * distance + transform.position;
left.origin = -left.direction * distance + transform.position;
up.origin = -up.direction * distance + transform.position;
down.origin = -down.direction * distance + transform.position;
forward.origin = -forward.direction * distance + transform.position;
back.origin = -back.direction * distance + transform.position;
r = meshCollider.Raycast(right , out rightHit , distance);
l = meshCollider.Raycast(left , out leftHit , distance);
u = meshCollider.Raycast(up , out upHit , distance);
d = meshCollider.Raycast(down , out downHit , distance);
f = meshCollider.Raycast(forward , out forwardHit , distance);
b = meshCollider.Raycast(back , out backHit , distance);
if(r&&l&&u&&d&&f&&b) {
if(ConcaveHull(right,rightHit)) In = false;
else if(ConcaveHull(left,leftHit)) In = false;
else if(ConcaveHull(up,upHit)) In = false;
else if(ConcaveHull(down,downHit)) In = false;
else if(ConcaveHull(forward,forwardHit)) In = false;
else if(ConcaveHull(back,backHit)) In = false;
else { In = true; concaveHull = false; }
} else In=false;
}
}
It works very well for non-convex mesh colliders - contrary to Physics.CheckSphere. Just what I was looking for!
Answer by tyjkenn · Jul 03, 2013 at 10:43 PM
Physics.CheckSphere is what you need. Just use a small test sphere like so:
if(Physics.CheckSphere(testPosition,.0001)){
//It is in a collider
} else{
//It is not in a collider
}
This does only work if the sphere intersects the surface of a mesh and not if it is fully inside.