private CollisionDetails GetFirstCollisionInternal(Shapes.Ray ray, bool isRayInside, bool useBiggerX, bool useBiggerY, bool useBiggerZ) { var result = new CollisionDetails { Distance = double.PositiveInfinity }; if (isRayInside) // recheck because ray was inside parent { isRayInside = PointCube.Encloses(_center, _halfWidth, ray.Origin); } // not inside and no hit -> return if (!isRayInside && double.IsInfinity(RayIntersectionDistance(ray, useBiggerX, useBiggerY, useBiggerZ))) { return(result); } if (_children != null && _children.Length > 0) { foreach (var child in _children) { var collision = child.GetFirstCollisionInternal(ray, isRayInside, useBiggerX, useBiggerY, useBiggerZ); if (!double.IsInfinity(collision.Distance)) { result = collision; break; } } } foreach (var o3D in _objects) { double distance = o3D.GetHitPointDistance(ray); if (distance > 0 && distance < result.Distance) { result.Obj = o3D; result.Distance = distance; } } return(result); }
/// <summary> /// Get the nearest intersection with the cube /// </summary> /// <param name="ray"></param> /// <param name="useBiggerX"></param> /// <param name="useBiggerY"></param> /// <param name="useBiggerZ"></param> /// <returns></returns> private double RayIntersectionDistance(Shapes.Ray ray, bool useBiggerX, bool useBiggerY, bool useBiggerZ) { if (PointCube.Encloses(_center, _halfWidth, ray.Origin)) { return(0); } var normal = new Vect3 { X = useBiggerX ? _halfWidth : -_halfWidth }; var planeCenter = _center + normal; double distance = SideRayIntersectionDistance(ray, normal, planeCenter); // we can return instantly as we only evaluate the hear side -> only one side should be hit at any time if (!double.IsInfinity(distance)) { return(distance); } normal = new Vect3 { Y = useBiggerY ? _halfWidth : -_halfWidth }; planeCenter = _center + normal; distance = SideRayIntersectionDistance(ray, normal, planeCenter); if (!double.IsInfinity(distance)) { return(distance); } normal = new Vect3 { Z = useBiggerZ ? _halfWidth : -_halfWidth }; planeCenter = _center + normal; distance = SideRayIntersectionDistance(ray, normal, planeCenter); if (!double.IsInfinity(distance)) { return(distance); } return(double.PositiveInfinity); }
/** * @param v a <code>Vect3</code> representing a point * @return true if, and only if, <code>v</code> is enclosed by this subtree. */ public bool Encloses(Vect3 v) { return(PointCube.Encloses(Center, Width / 2 + Constants.EPS, v)); }