protected override Intersections IntersectsInt(Ray r)
        {
            var dir_cross_e2 = Tuple.Cross(r.Direction, E2);
            var det          = Tuple.Dot(E1, dir_cross_e2);

            if (Math.Abs(det) < EPSILON)
            {
                return(Intersections.EMPTY);
            }

            var f            = 1.0 / det;
            var p1_to_origin = r.Origin - P1;
            var u            = f * Tuple.Dot(p1_to_origin, dir_cross_e2);

            if (u < 0 || u > 1)
            {
                return(Intersections.EMPTY);
            }

            var origin_cross_e1 = Tuple.Cross(p1_to_origin, E1);
            var v = f * Tuple.Dot(r.Direction, origin_cross_e1);

            if (v < 0 || (u + v) > 1)
            {
                return(Intersections.EMPTY);
            }

            var t = f * Tuple.Dot(E2, origin_cross_e1);

            return(new Intersections(
                       new Intersection(t, this, u, v)));
        }
        public Triangle(Point p1, Point p2, Point p3)
        {
            P1 = p1;
            P2 = p2;
            P3 = p3;

            E1 = (p2 - p1).ToVector();
            E2 = (p3 - p1).ToVector();

            Normal = Tuple.Cross(E2, E1).Normalize().ToVector();
        }
        public static Matrix View(Point from, Point to, Vector up)
        {
            var forward     = (to - from).Normalize();
            var left        = Tuple.Cross(forward, up.Normalize());
            var trueUp      = Tuple.Cross(left, forward);
            var orientation = new Matrix(new List <double> {
                left.x, left.y, left.z, 0,
                trueUp.x, trueUp.y, trueUp.z, 0,
                -forward.x, -forward.y, -forward.z, 0,
                0, 0, 0, 1
            });

            return(orientation * Transform.Translation(-from.x, -from.y, -from.z));
        }