Ejemplo n.º 1
0
        /**
         * March through Octree checking collisions. Every node on the way (when traversing to leaf direction) is checked for hits.
         *
         * @param v point to search for
         * @param c collision details
         * @return smallest node containing v, or null if (and only if) v is not inside the tree
         */

        public Node MarchToCheckingCollisions(Vect3 v, CollisionDetails c, Shapes.Ray ray)
        {
            if (Encloses(v))
            {
                if (_child == null)
                {
                    return(this);
                }

                foreach (Node n in _child)
                {
                    if (n.Encloses(v))
                    {
                        c.CheckCollisionSet(n.Content, ray);
                        return(n.MarchToCheckingCollisions(v, c, ray));
                    }
                }

                return(this);
            }
            if (_parent != null)
            {
                return(_parent.MarchToCheckingCollisions(v, c, ray));
            }
            return(null);
        }
Ejemplo n.º 2
0
        public static CollisionDetails GetFirstCollision(Octree tree, Shapes.Ray r)
        {
            var c = new CollisionDetails {
                Distance = double.PositiveInfinity
            };

            double distanceTravelled = 0; //distance traveled since the ray's origin

            //Algorithm starts at the ray's origin and in the root node.

            Node n = tree.GetRoot();

            c.CheckCollisionSet(n.Content, r);

            var pos = r.Origin;

            if (!n.Encloses(pos))
            {
                throw new Exception("Ray's origin is not located in the octree!");
            }

            do
            {
                //March to the leaf containing "pos" and check collisions
                n = n.MarchToCheckingCollisions(pos, c, r);

                //No leaf is containing "pos" -> left tree -> stop searching
                if (n == null)
                {
                    break;
                }

                //march out of current node
                double d = RayCube.GetDistanceToBorderPlane(pos, r.Direction, n.Center, n.Width / 2) + Constants.EPS * 1e4;
                //distance traveled since the ray's origin
                pos = pos + r.Direction * d;
                distanceTravelled += d;

                //in case eps was not enough
                while (n.Encloses(pos))
                {
                    d   = Constants.EPS * 1e4;
                    pos = pos + r.Direction * d;
                    distanceTravelled += d;
                }

                /**
                 * When passing a box-border, all intersection tests between the ray's origin and the
                 * box-border-intersection-point must have taken place (and some beyond the box-border too).
                 * Therefore, if an intersection located between the ray's origin and the box-border has been found, this
                 * must be the nearest intersection and the search may stop.
                 */
            } while (c.Distance > distanceTravelled);

            return(c);
        }
Ejemplo n.º 3
0
        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);
        }