public class Plane : CuGeometry { // p satisfies normal.dot(p) + d = 0 public Plane() : base(GeometryType.Plane) { } public Plane(Vector3 _normal, float _d) : base(GeometryType.Plane) { normal = _normal; d = _d; } public float distance(Vector3 p) { return Vector3.Dot(p, normal) + d; } public bool contains(Vector3 p) { Debug.Log(" Mathf.Abs(distance(p))" + Mathf.Abs(distance(p))); return Mathf.Abs(distance(p)) < (1.0e-3f); } public Vector3 normal; // The normal to the plane public float d; // The distance from the origin }
public static bool Raycast(Ray ray, float distance, Plane plane, out RaycastHitInfo hitInfo) { hitInfo = new RaycastHitInfo(); float dn = Vector3.Dot(ray.direction, plane.normal); if(-1E-7 < dn && dn < 1E-7) return false; // parallel Debug.Log("dIST: " + plane.distance(ray.origin)); float dist = -plane.distance(ray.origin) / dn; if(dist< distance) { hitInfo.distance = dist; }else { return false; } hitInfo.point = ray.origin + hitInfo.distance * ray.direction; //Inverse to ray direction if (dist < 0F) { return false; } return true; }
很简单,直接向看向量点乘结果,然后根据距离判断一下。
测试代码
public class RayPlaneTester : MonoBehaviour { public GameObject plane; NPhysX.Plane _plane; Ray ray; float castDistance = 10f; // Use this for initialization void Start () { ray = new Ray(Vector3.zero, new Vector3(1, 1, 1)); _plane = new NPhysX.Plane(); } // Update is called once per frame void Update () { _plane.normal = plane.transform.rotation * Vector3.up; _plane.d = -Vector3.Dot(plane.transform.position, _plane.normal); Debug.DrawLine(plane.transform.position, plane.transform.position + 3f * _plane.normal); RaycastHitInfo hitinfo2 = new RaycastHitInfo(); if (NRaycastTests.Raycast(ray, castDistance, _plane, out hitinfo2)) { Debug.DrawLine(ray.origin, ray.origin + ray.direction * hitinfo2.distance, Color.red, 0, true); } else { Debug.DrawLine(ray.origin, ray.origin + ray.direction * castDistance, Color.blue, 0, true); } } }
结果
PhysX 3.3 source code