Ejemplo n.º 1
0
        // http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms
        // release 0.050010 us
        // debug   0.069480 us
        public static RayDHitInfo CastRay(this RayD ray, Bounds bounds)
        {
            // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
            // r.org is origin of ray
            double tt1 = (bounds.Min.X - ray.origin.X) / ray.direction.X;
            double t2  = (bounds.Max.X - ray.origin.X) / ray.direction.X;
            double t3  = (bounds.Min.Y - ray.origin.Y) / ray.direction.Y;
            double t4  = (bounds.Max.Y - ray.origin.Y) / ray.direction.Y;
            double t5  = (bounds.Min.Z - ray.origin.Z) / ray.direction.Z;
            double t6  = (bounds.Max.Z - ray.origin.Z) / ray.direction.Z;

            double tmin = Math.Max(Math.Max(Math.Min(tt1, t2), Math.Min(t3, t4)), Math.Min(t5, t6));
            double tmax = Math.Min(Math.Min(Math.Max(tt1, t2), Math.Max(t3, t4)), Math.Max(t5, t6));

            // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
            if (tmax < 0)
            {
                //t0 = tmax;
                return(RayDHitInfo.NoHit);
            }

            //if (tmin > t1) return false;

            // if tmin > tmax, ray doesn't intersect AABB
            if (tmin > tmax)
            {
                //t0 = tmax;
                return(RayDHitInfo.NoHit);
            }

            return(RayDHitInfo.HitAtRayDistance(tmin));
            //t1 = tmin;
        }
Ejemplo n.º 2
0
        public static RayDHitInfo CastRay(this RayD ray, SphereD sphere)
        {
            var u = ray.direction;
            var A = ray.origin;
            var S = sphere.center;
            var r = sphere.radius;

            double _a = 1;
            // if u is not normalized then:
            //_a = u.x * u.x + u.y * u.y + u.z * u.z;

            double _b =
                (
                    (A.X * u.X) - (u.X * S.X) +
                    (A.Y * u.Y) - (u.Y * S.Y) +
                    (A.Z * u.Z) - (u.Z * S.Z)
                ) * 2;

            double _c =
                ((A.X - S.X) * (A.X - S.X)) +
                ((A.Y - S.Y) * (A.Y - S.Y)) +
                ((A.Z - S.Z) * (A.Z - S.Z)) +
                -(r * r);

            // a*t*t + b*t + c

            double determinant = _b * _b - 4 * _a * _c;

            if (determinant < 0)
            {
                return(RayDHitInfo.NoHit);                             // no hit
            }
            double _2a = 2 * _a;

            if (determinant > 0)             // two hits
            {
                double dSqrt = (double)Math.Sqrt(determinant);
                double t1    = (-_b + dSqrt) / _2a;
                double t2    = (-_b - dSqrt) / _2a;

                if (t1 < t2)
                {
                    return(RayDHitInfo.HitAtRayDistance(t1));
                }
                else
                {
                    return(RayDHitInfo.HitAtRayDistance(t2));
                }
            }

            if (determinant == 0)             // one hit
            {
                double t1 = -_b / _2a;
                return(RayDHitInfo.HitAtRayDistance(t1));
            }

            return(RayDHitInfo.NoHit);
        }
Ejemplo n.º 3
0
        // Thomas Moller ray triangle intersection
        // or http://www.lighthouse3d.com/tutorials/maths/ray-triangle-intersection/
        // release 0.054317 us
        // debug   0.602176 us
        public static RayDHitInfo CastRay(this RayD ray, TriangleD triangle)
        {
            // TODO

            /*
             * Zde doplòte kód pro testování existence prùseèíku parsku s trojúhelníkem.
             * Vypoètený parametr t spoleènì s trojúhelníkem triangle vložte ma konci této metody
             * do metody ray.closest_hit, napø. takto
             *
             * return ray.closest_hit( t, triangle );
             *
             * Tato metoda vrátí true v pøípadì, že zadaný parametr t je menší než pøedchozí a zapíše
             * do paprsku i ukazatel na zasažený trojúhelník, pøes který (metoda target) je možno následnì zjistit
             * normálu (target.normal()) nebo materiál v bodì zásahu.
             */

            const double ____EPSILON = 0.000001f;

            Vector3d V1 = triangle.a;
            Vector3d V2 = triangle.b;
            Vector3d V3 = triangle.c;
            Vector3d O  = ray.origin;             //RayD origin
            Vector3d D  = ray.direction;          //RayD direction


            Vector3d e1, e2;              //Edge1, Edge2
            Vector3d P, Q, T;
            double   det, inv_det, u, v;
            double   t;

            //Find vectors for two edges sharing V1
            e1 = V2 - V1;
            e2 = V3 - V1;
            //Begin calculating determinant - also used to calculate u parameter
            P = D.Cross(e2);
            //if determinant is near zero, ray lies in plane of triangle
            det = e1.Dot(P);
            //NOT CULLING
            if (det > -____EPSILON && det < ____EPSILON)
            {
                return(RayDHitInfo.NoHit);
            }
            inv_det = 1.0f / det;

            //calculate distance from V1 to ray origin
            T = O - V1;

            //Calculate u parameter and test bound
            u = T.Dot(P) * inv_det;
            //The intersection lies outside of the triangle
            if (u < 0.0f || u > 1.0f)
            {
                return(RayDHitInfo.NoHit);
            }

            //Prepare to test v parameter
            Q = T.Cross(e1);

            //Calculate V parameter and test bound
            v = D.Dot(Q) * inv_det;
            //The intersection lies outside of the triangle
            if (v < 0.0f || u + v > 1.0f)
            {
                return(RayDHitInfo.NoHit);
            }

            t = e2.Dot(Q) * inv_det;

            if (t > ____EPSILON)
            {             //ray intersection
                return(RayDHitInfo.HitAtRayDistance(t));
            }


            return(RayDHitInfo.NoHit);            // trojúhelník nenalezen
        }