public static bool Contains2DPoint(Vector2 point, Vector2 p0, Vector2 p1, Vector2 p2, TriangleEpsilon epsilon = new TriangleEpsilon()) { return(Contains3DPoint(point, false, p0, p1, p2, epsilon)); }
public static bool Contains3DPoint(Vector3 point, bool checkOnPlane, Vector3 p0, Vector3 p1, Vector3 p2, TriangleEpsilon epsilon = new TriangleEpsilon()) { Vector3 edge0 = p1 - p0; Vector3 edge1 = p2 - p1; Vector3 edge2 = p0 - p2; Vector3 normal = Vector3.Cross(edge0, -edge2).normalized; if (checkOnPlane) { float distanceToPt = Vector3.Dot(point - p0, normal); if (Mathf.Abs(distanceToPt) > epsilon.ExtrudeEps) { return(false); } } Vector3 edgeNormal = Vector3.Cross(edge0, normal).normalized; if (Vector3.Dot(point - p0, edgeNormal) > epsilon.AreaEps) { return(false); } edgeNormal = Vector3.Cross(edge1, normal).normalized; if (Vector3.Dot(point - p1, edgeNormal) > epsilon.AreaEps) { return(false); } edgeNormal = Vector3.Cross(edge2, normal).normalized; if (Vector3.Dot(point - p2, edgeNormal) > epsilon.AreaEps) { return(false); } return(true); }
public static bool Raycast(Ray ray, out float t, Vector3 p0, Vector3 p1, Vector3 p2, TriangleEpsilon epsilon = new TriangleEpsilon()) { t = 0.0f; float rayEnter; Plane trianglePlane = new Plane(p0, p1, p2); if (trianglePlane.Raycast(ray, out rayEnter) && Contains3DPoint(ray.GetPoint(rayEnter), false, p0, p1, p2, epsilon)) { t = rayEnter; return(true); } if (epsilon.ExtrudeEps != 0.0f) { float dot = Vector3Ex.AbsDot(ray.direction, trianglePlane.normal); if (dot < ExtrudeEpsThreshold.Get) { OOBB oobb = Calc3DTriangleOOBB(p0, p1, p2, trianglePlane.normal, epsilon); return(BoxMath.Raycast(ray, oobb.Center, oobb.Size, oobb.Rotation)); } } return(false); }
public static bool RaycastWire(Ray ray, out float t, Vector3 p0, Vector3 p1, Vector3 p2, TriangleEpsilon epsilon = new TriangleEpsilon()) { t = 0.0f; float rayEnter; Plane trianglePlane = new Plane(p0, p1, p2); if (trianglePlane.Raycast(ray, out rayEnter)) { Vector3 intersectPt = ray.GetPoint(rayEnter); float distToSegment = intersectPt.GetDistanceToSegment(p0, p1); if (distToSegment <= epsilon.WireEps) { t = rayEnter; return(true); } distToSegment = intersectPt.GetDistanceToSegment(p1, p2); if (distToSegment <= epsilon.WireEps) { t = rayEnter; return(true); } distToSegment = intersectPt.GetDistanceToSegment(p2, p0); if (distToSegment <= epsilon.WireEps) { t = rayEnter; return(true); } } if (epsilon.ExtrudeEps != 0.0f) { float dot = Vector3Ex.AbsDot(ray.direction, trianglePlane.normal); if (dot < ExtrudeEpsThreshold.Get) { OOBB oobb = Calc3DTriangleOOBB(p0, p1, p2, trianglePlane.normal, epsilon); return(BoxMath.Raycast(ray, oobb.Center, oobb.Size, oobb.Rotation)); } } return(false); }
public static OOBB Calc3DTriangleOOBB(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 normal, TriangleEpsilon epsilon = new TriangleEpsilon()) { const float eps = 1e-5f; Vector3 lgEdgeStart = p0; Vector3 lgEdgeEnd = p1; Vector3 oppositePt = p2; float sqrEdgeLength = (p0 - p1).sqrMagnitude + eps; // Add small epsilon to avoid problems with equilateral triangles float nextSqrLength = (p1 - p2).sqrMagnitude; if (nextSqrLength > sqrEdgeLength) { lgEdgeStart = p1; lgEdgeEnd = p2; oppositePt = p0; sqrEdgeLength = nextSqrLength; } nextSqrLength = (p2 - p0).sqrMagnitude; if (nextSqrLength > sqrEdgeLength) { lgEdgeStart = p2; lgEdgeEnd = p0; oppositePt = p1; sqrEdgeLength = nextSqrLength; } Quaternion oobbRotation = Quaternion.LookRotation((lgEdgeEnd - lgEdgeStart).normalized, normal); OOBB oobb = new OOBB(oobbRotation); float sizeAdd = 2.0f * epsilon.AreaEps; float oobbDepth = Mathf.Sqrt(sqrEdgeLength) + sizeAdd; float dotRight = Vector3.Dot(oobb.Right, (oppositePt - lgEdgeStart)); float oobbWidth = Mathf.Abs(dotRight) + sizeAdd; float oobbHeight = epsilon.ExtrudeEps * 2.0f; oobb.Size = new Vector3(oobbWidth, oobbHeight, oobbDepth); Vector3 right = oobb.Right * Mathf.Sign(dotRight); oobb.Center = right * oobbWidth * 0.5f - right * epsilon.AreaEps + lgEdgeStart - oobb.Look * epsilon.AreaEps + oobb.Look * oobbDepth * 0.5f; return(oobb); }