public Sphere()
 {
     fromOrigin = true;
     Center     = new Tuple4(0.0, 0.0, 0.0, TupleFlavour.Point);
     Radius     = 1.0;
     radius2    = 1.0;
 }
        private double[] GetIntersectionsFromBook(Tuple4 origin, Tuple4 dir)
        {
            if (!Constants.EpsilonCompare(1.0, dir.Length()))
            {
                throw new ArgumentException("Direction should be normalized", nameof(dir));
            }

            var sphereToRay  = Tuple4.Subtract(origin, Tuple4.ZeroPoint);
            var a            = Tuple4.DotProduct(dir, dir);
            var b            = 2 * Tuple4.DotProduct(dir, sphereToRay);
            var c            = Tuple4.DotProduct(sphereToRay, sphereToRay) - 1.0;
            var discriminant = b * b - 4 * a * c;

            if (discriminant < 0.0)
            {
                return(null);
            }
            var discriminantSqrt = Math.Sqrt(discriminant);
            var t0 = (-b - discriminantSqrt) / (2 * a);
            var t1 = (-b + discriminantSqrt) / (2 * a);

            // Ray originates inside sphere
            // When t > 0 that is intersection in the direction of the ray
            // other intersection is in the opposite direction
            return(new double[] { t0, t1 });
        }
Exemple #3
0
            // https://en.wikipedia.org/wiki/Euler_angles
            // The basic theory of this camera model is that we want to build a camera matrix that first rotates pitch angle about the X axis,
            // then rotates yaw angle about the Y axis, then translates to some position in the world.
            // Since we want the view matrix, we need to compute the inverse of the resulting matrix.
            //              V=(T(RyRx))^-1
            public static IMatrix EulerAnglesTransform(Tuple4 from, double pitch, double yaw)
            {
                var orientation = MatrixOperations.Geometry3D.RotateZXY(pitch, yaw, 0);
                var translation = Translation(from.X, from.Y, from.Z);

                return(Invert(Multiply(translation, orientation)));
            }
 public Sphere(Tuple4 center, double radius)
 {
     fromOrigin = false;
     Center     = center;
     Radius     = radius;
     radius2    = radius * radius;
 }
Exemple #5
0
 protected internal virtual double DistanceFrom(Tuple4 point)
 {
     if (point.IsVector())
     {
         throw new ArgumentException("Argument is not a point");
     }
     throw new NotImplementedException();
 }
Exemple #6
0
 public static IMatrix FromTuple(Tuple4 tuple)
 {
     return(new Matrix(new double[, ]
     {
         { tuple.X },
         { tuple.Y },
         { tuple.Z },
         { tuple.W }
     }, false));
 }
Exemple #7
0
        public virtual Tuple4 GetNormal(Tuple4 objectPoint)
        {
            var estimateNormal = new Tuple4(
                DistanceFrom(new Tuple4(objectPoint.X + epsilon, objectPoint.Y, objectPoint.Z, TupleFlavour.Point)) - DistanceFrom(new Tuple4(objectPoint.X - epsilon, objectPoint.Y, objectPoint.Z, TupleFlavour.Point)),
                DistanceFrom(new Tuple4(objectPoint.X, objectPoint.Y + epsilon, objectPoint.Z, TupleFlavour.Point)) - DistanceFrom(new Tuple4(objectPoint.X, objectPoint.Y - epsilon, objectPoint.Z, TupleFlavour.Point)),
                DistanceFrom(new Tuple4(objectPoint.X, objectPoint.Y, objectPoint.Z + epsilon, TupleFlavour.Point)) - DistanceFrom(new Tuple4(objectPoint.X, objectPoint.Y, objectPoint.Z - epsilon, TupleFlavour.Point)),
                TupleFlavour.Vector
                );

            return(estimateNormal);
        }
 public static Tuple4 MovePoint(Tuple4 origin, Tuple4 dir, double t)
 {
     if (!dir.IsVector())
     {
         throw new ArgumentException("Not a vector");
     }
     return(new Tuple4(
                origin.X + t * dir.X,
                origin.Y + t * dir.Y,
                origin.Z + t * dir.Z,
                TupleFlavour.Point
                ));
 }
 public Ray(Tuple4 origin, Tuple4 dir)
 {
     if (!origin.IsPoint())
     {
         throw new ArgumentException("Not a point", nameof(origin));
     }
     if (!dir.IsVector())
     {
         throw new ArgumentException("Not a vector", nameof(dir));
     }
     this.origin = origin;
     this.dir    = dir;
 }
Exemple #10
0
 public static Tuple4 Transform(IMatrix matrix, Tuple4 tuple)
 {
     if (Object.ReferenceEquals(Matrix4x4.Identity, matrix))
     {
         return(tuple);
     }
     return(new Tuple4(
                matrix[0, 0] * tuple.X + matrix[0, 1] * tuple.Y + matrix[0, 2] * tuple.Z + matrix[0, 3] * tuple.W,
                matrix[1, 0] * tuple.X + matrix[1, 1] * tuple.Y + matrix[1, 2] * tuple.Z + matrix[1, 3] * tuple.W,
                matrix[2, 0] * tuple.X + matrix[2, 1] * tuple.Y + matrix[2, 2] * tuple.Z + matrix[2, 3] * tuple.W,
                matrix[3, 0] * tuple.X + matrix[3, 1] * tuple.Y + matrix[3, 2] * tuple.Z + matrix[3, 3] * tuple.W
                ));
 }
Exemple #11
0
            public static IMatrix LookAtTransform(Tuple4 from, Tuple4 to, Tuple4 up)
            {
                var forward      = Tuple4.Normalize(Tuple4.Subtract(to, from));
                var upNormalized = Tuple4.Normalize(up);
                var left         = Tuple4.CrossProduct(forward, upNormalized);
                var trueUp       = Tuple4.CrossProduct(left, forward);

                var viewMatrix = new Matrix(new double[, ]
                {
                    { left.X, left.Y, left.Z, -Tuple4.DotProduct(left, from) },
                    { trueUp.X, trueUp.Y, trueUp.Z, -Tuple4.DotProduct(trueUp, from) },
                    { -forward.X, -forward.Y, -forward.Z, Tuple4.DotProduct(forward, from) },
                    { 0.0, 0.0, 0.0, 1.0 }
                });

                return(viewMatrix);

                /*
                 *  // Create a 4x4 orientation matrix from the left, up, and forward vectors
                 *  // This is transposed which is equivalent to performing an inverse
                 *  // if the matrix is orthonormalized (in this case, it is).
                 *  var orientation = new Matrix(new double[,]
                 *  {
                 *      {      left.X,     left.Y,     left.Z, 0.0 },
                 *      {    trueUp.X,   trueUp.Y,   trueUp.Z, 0.0 },
                 *      {  -forward.X, -forward.Y, -forward.Z, 0.0 },
                 *      {         0.0,        0.0,        0.0, 1.0 }
                 *  }, false);
                 *
                 *  // Create a 4x4 translation matrix.
                 *  // The eye position is negated which is equivalent
                 *  // to the inverse of the translation matrix.
                 *  var translation = Translation(-from.X, -from.Y, -from.Z);
                 *
                 *  // Combine the orientation and translation to compute
                 *  // the final view matrix. Note that the order of
                 *  // multiplication is reversed because the matrices
                 *  // are already inverted.
                 *  return Multiply(orientation, translation);
                 */
            }
Exemple #12
0
            public static IMatrix EulerAnglesTransformDirectConstruction(Tuple4 from, double pitch, double yaw)
            {
                double cosPitch = Math.Cos(pitch);
                double sinPitch = Math.Sin(pitch);
                double cosYaw   = Math.Cos(yaw);
                double sinYaw   = Math.Sin(yaw);

                Tuple4 xaxis = new Tuple4(cosYaw, 0, -sinYaw, TupleFlavour.Vector);
                Tuple4 yaxis = new Tuple4(sinYaw * sinPitch, cosPitch, cosYaw * sinPitch, TupleFlavour.Vector);
                Tuple4 zaxis = new Tuple4(sinYaw * cosPitch, -sinPitch, cosPitch * cosYaw, TupleFlavour.Vector);

                var viewMatrix = new Matrix(new double[, ]
                {
                    { xaxis.X, xaxis.Y, xaxis.Z, -Tuple4.DotProduct(xaxis, from) },
                    { yaxis.X, yaxis.Y, yaxis.Z, -Tuple4.DotProduct(yaxis, from) },
                    { zaxis.X, zaxis.Y, zaxis.Z, -Tuple4.DotProduct(zaxis, from) },
                    { 0, 0, 0, 1 }
                });

                return(viewMatrix);
            }
Exemple #13
0
        private double[] GetIntersections(Tuple4 origin, Tuple4 dir)
        {
            if (!Constants.EpsilonCompare(1.0, dir.Length()))
            {
                throw new ArgumentException("Direction should be normalized", nameof(dir));
            }

            var t = 0.0;

            while (t < maxDistance)
            {
                var p = Tuple4.Geometry3D.MovePoint(origin, dir, t);
                var d = DistanceFrom(p);
                if (Math.Abs(d) < epsilon)
                {
                    return(new double[] { t });
                }
                t += d;
            }

            return(null);
        }
        private double[] GetIntersections(Tuple4 origin, Tuple4 dir)
        {
            if (!Constants.EpsilonCompare(1.0, dir.Length()))
            {
                throw new ArgumentException("Direction should be normalized", nameof(dir));
            }

            var l   = Tuple4.Subtract(Center, origin);
            var tca = Tuple4.DotProduct(l, dir);
            var d2  = Tuple4.DotProduct(l, l) - tca * tca;

            if (d2 > radius2)
            {
                return(null);
            }
            var thc = Math.Sqrt(radius2 - d2);
            var t0  = tca - thc;
            var t1  = tca + thc;

            // Ray originates inside sphere
            // When t > 0 that is intersection in the direction of the ray
            // other intersection is in the opposite direction
            return(new double[] { t0, t1 });
        }
 public Tuple4 GetNormal(Tuple4 objectPoint)
 {
     // hit - Center
     return(Tuple4.Subtract(objectPoint, Center));
 }
 public Tuple4 PositionAt(double t)
 {
     return(Tuple4.Add(origin, Tuple4.Scale(dir, Tuple4.Point(t, t, t))));
 }