Ejemplo n.º 1
0
        public void TransformToPlane(Plane newPlane)
        {
            double eps = 1e-7;

            if (!PipeDataUtil.Equals(Vec.Dot(newPlane.Z, Plane.Z), 1, eps))
            {
                throw new InvalidOperationException("Cannot transform arc to a new plane");
            }
            if (Vec.Difference(newPlane.Origin, Plane.Origin).Length > eps)
            {
                throw new InvalidOperationException("The origins of the planes do not match");
            }

            double angle = Vec.AngleBetween(Plane.X, newPlane.X);

            if (angle < eps)
            {
                return;
            }
            if (Vec.Dot(Vec.Cross(Plane.X, newPlane.X), Plane.Z) < 0)
            {
                angle *= -1;
            }

            Plane = new Plane(Plane.Origin, Plane.X.RotateAbout(Plane.Z, angle),
                              Plane.Y.RotateAbout(Plane.Z, angle));
            StartAngle -= angle;
            EndAngle   -= angle;
        }
Ejemplo n.º 2
0
        public static Vec[] RenderEntry()
        {
            int w     = 256;
            int h     = 256;
            int samps = 25;             // # samples

            var tmp1 = new Vec(50, 52, 295.6);
            var tmp2 = new Vec(0, -0.042612, -1).Norm();
            Ray cam  = new Ray(ref tmp1, ref tmp2);            // cam pos, dir
            Vec cx   = new Vec(w * .5135 / h, 0, 0);
            Vec cy   = (cx.Cross(ref cam.d)).Norm().Mul(.5135);

            Vec[] c = new Vec[w * h];

            //#pragma omp parallel for schedule(dynamic, 1)       // OpenMP
            // Loop over image rows
            for (int y = 0; y < h; y++)
            {
                //fprintf(stderr,"\rRendering (%d spp) %5.2f%%",samps*4,100.*y/(h-1));
                RandomLCG rand = new RandomLCG((uint)y);

                // Loop cols
                for (ushort x = 0; x < w; x++)
                {
                    // 2x2 subpixel rows
                    for (int sy = 0; sy < 2; sy++)
                    {
                        int i = (h - y - 1) * w + x;

                        // 2x2 subpixel cols
                        for (int sx = 0; sx < 2; sx++)
                        {
                            Vec r = Vec_Zero;
                            for (int s = 0; s < samps; s++)
                            {
                                double r1 = 2 * rand.NextNumber();
                                double r2 = 2 * rand.NextNumber();
                                double dx = r1 < 1 ? MathSqrt(r1) - 1 : 1 - MathSqrt(2 - r1);
                                double dy = r2 < 1 ? MathSqrt(r2) - 1 : 1 - MathSqrt(2 - r2);

                                var tmp3 = cy.Mul(((sy + .5 + dy) / 2 + y) / h - .5);
                                Vec d    = cx.Mul(((sx + .5 + dx) / 2 + x) / w - .5).Add(
                                    ref tmp3).Add(ref cam.d);

                                var tmp4 = d.Mul(140);
                                var tmp5 = cam.o.Add(ref tmp4);
                                var tmp6 = d.Norm();
                                var tmp7 = new Ray(ref tmp5, ref tmp6);
                                var tmp8 = radiance(ref tmp7, 0, ref rand).Mul(1.0 / samps);
                                r = r.Add(ref tmp8);
                            }
                            var tmp9 = new Vec(clamp(r.x), clamp(r.y), clamp(r.z)).Mul(.25);
                            c[i] = c[i].Add(ref tmp9);
                        }
                    }
                }
            }
            return(c);
        }
Ejemplo n.º 3
0
        public static double ComputeUnscaledFormFactor(
            this Polygon3d polygon,
            V3d p, V3d n,
            double eps = 1e-6)
        {
            var vc = polygon.PointCount;

            V3d[] cpa = new V3d[vc + 1];

            var cc = 0;
            var pb = polygon[0] - p;
            var hb = Vec.Dot(pb, n); bool hbp = hb > eps, hbn = hb < -eps;

            if (hb >= -eps)
            {
                cpa[cc++] = pb;
            }
            var p0 = pb; var h0 = hb; var h0p = hbp; var h0n = hbn;

            for (int vi = 1; vi < vc; vi++)
            {
                var  p1 = polygon[vi] - p; var h1 = Vec.Dot(p1, n);
                bool h1p = h1 > eps, h1n = h1 < -eps;
                if (h0p && h1n || h0n && h1p)
                {
                    cpa[cc++] = p0 + (p1 - p0) * (h0 / (h0 - h1));
                }
                if (h1 >= -eps)
                {
                    cpa[cc++] = p1;
                }
                p0 = p1; h0 = h1; h0p = h1p; h0n = h1n;
            }
            if (h0p && hbn || h0n && hbp)
            {
                cpa[cc++] = p0 + (pb - p0) * (h0 / (h0 - hb));
            }

            var cpr = cpa.Map(cc, v => v.Length);

            var    cv = Vec.Cross(cpa[0], cpa[cc - 1]);
            double ff = Vec.Dot(n, cv)
                        * Fun.AcosClamped(Vec.Dot(cpa[0], cpa[cc - 1])
                                          / (cpr[0] * cpr[cc - 1]))
                        / cv.Length;

            for (int ci = 0; ci < cc - 1; ci++)
            {
                cv  = Vec.Cross(cpa[ci + 1], cpa[ci]);
                ff += Vec.Dot(n, cv)
                      * Fun.AcosClamped(Vec.Dot(cpa[ci + 1], cpa[ci])
                                        / (cpr[ci + 1] * cpr[ci]))
                      / cv.Length;
            }
            return(ff);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Computes from a <see cref="V3f"/> point (origin) and
        /// a <see cref="V3f"/> normal the transformation matrix
        /// and its inverse.
        /// </summary>
        /// <param name="origin">The point which will become the new origin.</param>
        /// <param name="normal">The normal vector of the new ground plane.</param>
        /// <param name="local2global">A <see cref="M44f"/>The trafo from local to global system.</param>
        /// <param name="global2local">A <see cref="M44f"/>The trafofrom global to local system.</param>
        public static void NormalFrame(V3f origin, V3f normal,
                                       out M44f local2global, out M44f global2local
                                       )
        {
            V3f   min;
            float x = Fun.Abs(normal.X);
            float y = Fun.Abs(normal.Y);
            float z = Fun.Abs(normal.Z);

            if (x < y)
            {
                if (x < z)
                {
                    min = V3f.XAxis;
                }
                else
                {
                    min = V3f.ZAxis;
                }
            }
            else
            {
                if (y < z)
                {
                    min = V3f.YAxis;
                }
                else
                {
                    min = V3f.ZAxis;
                }
            }

            V3f xVec = Vec.Cross(normal, min);

            xVec.Normalize(); // this is now guaranteed to be normal to the input normal
            V3f yVec = Vec.Cross(normal, xVec);

            yVec.Normalize();
            V3f zVec = normal;

            zVec.Normalize();

            local2global = new M44f(xVec.X, yVec.X, zVec.X, origin.X,
                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,
                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,
                                    0, 0, 0, 1);

            M44f mat = new M44f(xVec.X, xVec.Y, xVec.Z, 0,
                                yVec.X, yVec.Y, yVec.Z, 0,
                                zVec.X, zVec.Y, zVec.Z, 0,
                                0, 0, 0, 1);

            var shift = M44f.Translation(-origin);

            global2local = mat * shift;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Computes from a <see cref="V3d"/> point (origin) and
        /// a <see cref="V3d"/> normal the transformation matrix
        /// and its inverse.
        /// </summary>
        /// <param name="origin">The point which will become the new origin.</param>
        /// <param name="normal">The normal vector of the new ground plane.</param>
        /// <param name="local2global">A <see cref="M44d"/>The trafo from local to global system.</param>
        /// <param name="global2local">A <see cref="M44d"/>The trafofrom global to local system.</param>
        public static void NormalFrame(V3d origin, V3d normal,
                                       out M44d local2global, out M44d global2local
                                       )
        {
            V3d    min;
            double x = Fun.Abs(normal.X);
            double y = Fun.Abs(normal.Y);
            double z = Fun.Abs(normal.Z);

            if (x < y)
            {
                if (x < z)
                {
                    min = V3d.XAxis;
                }
                else
                {
                    min = V3d.ZAxis;
                }
            }
            else
            {
                if (y < z)
                {
                    min = V3d.YAxis;
                }
                else
                {
                    min = V3d.ZAxis;
                }
            }

            V3d xVec = Vec.Cross(normal, min);

            xVec.Normalize(); // this is now guaranteed to be normal to the input normal
            V3d yVec = Vec.Cross(normal, xVec);

            yVec.Normalize();
            V3d zVec = normal;

            zVec.Normalize();

            local2global = new M44d(xVec.X, yVec.X, zVec.X, origin.X,
                                    xVec.Y, yVec.Y, zVec.Y, origin.Y,
                                    xVec.Z, yVec.Z, zVec.Z, origin.Z,
                                    0, 0, 0, 1);

            M44d mat = new M44d(xVec.X, xVec.Y, xVec.Z, 0,
                                yVec.X, yVec.Y, yVec.Z, 0,
                                zVec.X, zVec.Y, zVec.Z, 0,
                                0, 0, 0, 1);

            var shift = M44d.Translation(-origin);

            global2local = mat * shift;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Computes from a <see cref="V__x3t__"/> point (origin) and
        /// a <see cref="V__x3t__"/> normal the transformation matrix
        /// and its inverse.
        /// </summary>
        /// <param name="origin">The point which will become the new origin.</param>
        /// <param name="normal">The normal vector of the new ground plane.</param>
        /// <param name="local2global">A <see cref="M4__x4t__"/>The trafo from local to global system.</param>
        /// <param name="global2local">A <see cref="M4__x4t__"/>The trafofrom global to local system.</param>
        public static void NormalFrame(V__x3t__ origin, V__x3t__ normal,
                                       out M4__x4t__ local2global, out M4__x4t__ global2local
                                       )
        {
            V__x3t__ min;
            __ft__   x = Fun.Abs(normal.X);
            __ft__   y = Fun.Abs(normal.Y);
            __ft__   z = Fun.Abs(normal.Z);

            if (x < y)
            {
                if (x < z)
                {
                    min = V__x3t__.XAxis;
                }
                else
                {
                    min = V__x3t__.ZAxis;
                }
            }
            else
            {
                if (y < z)
                {
                    min = V__x3t__.YAxis;
                }
                else
                {
                    min = V__x3t__.ZAxis;
                }
            }

            V__x3t__ xVec = Vec.Cross(normal, min);

            xVec.Normalize(); // this is now guaranteed to be normal to the input normal
            V__x3t__ yVec = Vec.Cross(normal, xVec);

            yVec.Normalize();
            V__x3t__ zVec = normal;

            zVec.Normalize();

            local2global = new M4__x4t__(xVec.X, yVec.X, zVec.X, origin.X,
                                         xVec.Y, yVec.Y, zVec.Y, origin.Y,
                                         xVec.Z, yVec.Z, zVec.Z, origin.Z,
                                         0, 0, 0, 1);

            M4__x4t__ mat = new M4__x4t__(xVec.X, xVec.Y, xVec.Z, 0,
                                          yVec.X, yVec.Y, yVec.Z, 0,
                                          zVec.X, zVec.Y, zVec.Z, 0,
                                          0, 0, 0, 1);

            var shift = M4__x4t__.Translation(-origin);

            global2local = mat * shift;
        }
Ejemplo n.º 7
0
        public void Cross()
        {
            var p1 = new Vec(1, 2, 3);

            Assert.AreEqual(Math.Sqrt(96), p1.CrossMagnitude(new Vec(3, 2, 1)));
            Assert.AreEqual(96, p1.CrossSquareMagnitude(new Vec(3, 2, 1)));
            Assert.AreEqual(new Vec(-4, 8, -4), p1.Crossed(new Vec(3, 2, 1)));
            p1.Cross(new Vec(3, 2, 1));
            Assert.AreEqual(new Vec(-4, 8, -4), p1);
        }
Ejemplo n.º 8
0
 // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
 public static Rot3f HalfWayVec(V3f from, V3f into)
 {
     if (from.Dot(into).ApproximateEquals(-1))
     {
         return(new Rot3f(0, from.AxisAlignedNormal()));
     }
     else
     {
         V3f         half = Vec.Normalized(from + into);
         QuaternionF q    = new QuaternionF(Vec.Dot(from, half), Vec.Cross(from, half));
         return(new Rot3f(q.Normalized));
     }
 }
 // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
 public static __rot3t__ HalfWayVec(__v3t__ from, __v3t__ into)
 {
     if (from.Dot(into).ApproximateEquals(-1))
     {
         return(new __rot3t__(0, from.AxisAlignedNormal()));
     }
     else
     {
         __v3t__   half = Vec.Normalized(from + into);
         __quatt__ q    = new __quatt__(Vec.Dot(from, half), Vec.Cross(from, half));
         return(new __rot3t__(q.Normalized));
     }
 }
Ejemplo n.º 10
0
            public static __rot3t__ HalfWayQuat(__v3t__ from, __v3t__ into)
            {
                var d = Vec.Dot(from, into);

                if (d.ApproximateEquals(-1))
                {
                    return(new __rot3t__(0, from.AxisAlignedNormal()));
                }
                else
                {
                    __quatt__ q = new __quatt__(d + 1, Vec.Cross(from, into));
                    return(new __rot3t__(q.Normalized));
                }
            }
Ejemplo n.º 11
0
            public static Rot3f HalfWayQuat(V3f from, V3f into)
            {
                var d = Vec.Dot(from, into);

                if (d.ApproximateEquals(-1))
                {
                    return(new Rot3f(0, from.AxisAlignedNormal()));
                }
                else
                {
                    QuaternionF q = new QuaternionF(d + 1, Vec.Cross(from, into));
                    return(new Rot3f(q.Normalized));
                }
            }
Ejemplo n.º 12
0
            public static Rot3f Original(V3f from, V3f into)
            {
                var angle = from.AngleBetween(into);

                if (angle < 1e-6f)
                {
                    return(Rot3f.Identity);
                }
                else if (Constant.PiF - angle < 1e-6f)
                {
                    return(new Rot3f(0, from.AxisAlignedNormal()));
                }
                else
                {
                    V3f axis = Vec.Cross(from, into).Normalized;
                    return(Rot3f.Rotation(axis, angle));
                }
            }
Ejemplo n.º 13
0
        /// <summary>
        /// Computes from a <see cref="V__x3t__"/> normal the transformation matrix
        /// from the local coordinate system where the normal is the z-axis to
        /// the global coordinate system.
        /// </summary>
        /// <param name="normal">The normal vector of the new ground plane.</param>
        public static M3__x3t__ NormalFrameLocal2Global(V__x3t__ normal)
        {
            V__x3t__ min;
            double   x = Fun.Abs(normal.X);
            double   y = Fun.Abs(normal.Y);
            double   z = Fun.Abs(normal.Z);

            if (x < y)
            {
                if (x < z)
                {
                    min = V__x3t__.XAxis;
                }
                else
                {
                    min = V__x3t__.ZAxis;
                }
            }
            else
            {
                if (y < z)
                {
                    min = V__x3t__.YAxis;
                }
                else
                {
                    min = V__x3t__.ZAxis;
                }
            }

            var xVec = Vec.Cross(normal, min);

            xVec.Normalize(); // this is now guaranteed to be normal to the input normal
            var yVec = Vec.Cross(normal, xVec);

            yVec.Normalize();
            var zVec = normal;

            zVec.Normalize();

            return(new M3__x3t__(xVec.X, yVec.X, zVec.X,
                                 xVec.Y, yVec.Y, zVec.Y,
                                 xVec.Z, yVec.Z, zVec.Z));
        }
Ejemplo n.º 14
0
            public static __rot3t__ Original(__v3t__ from, __v3t__ into)
            {
                var angle = from.AngleBetween(into);

                //# var rotIntoEps = isDouble ? "1e-15" : "1e-6f";
                if (angle < __rotIntoEps__)
                {
                    return(__rot3t__.Identity);
                }
                else if (__pi__ - angle < __rotIntoEps__)
                {
                    return(new __rot3t__(0, from.AxisAlignedNormal()));
                }
                else
                {
                    __v3t__ axis = Vec.Cross(from, into).Normalized;
                    return(__rot3t__.Rotation(axis, angle));
                }
            }
Ejemplo n.º 15
0
        public Arc(Vec startPt, Vec endPt, Vec ptOnArc)
        {
            Vec midPt1 = Vec.Multiply(Vec.Sum(endPt, ptOnArc), 0.5);
            Vec midPt2 = Vec.Multiply(Vec.Sum(startPt, ptOnArc), 0.5);

            Vec seg1 = Vec.Difference(ptOnArc, startPt);
            Vec seg2 = Vec.Difference(endPt, ptOnArc);

            Vec planeZ = Vec.Cross(seg1, seg2);

            Vec rad1 = Vec.Cross(planeZ, seg1);
            Vec rad2 = Vec.Cross(planeZ, seg2);

            Vec center = Vec.IntersectLines(midPt1, rad1, midPt2, rad2);
            Vec planeX = Vec.Difference(startPt, center);
            Vec planeY = Vec.Cross(planeZ, planeX);

            _plane      = new Plane(center, planeX, planeY, planeZ);
            _radius     = Vec.Difference(center, startPt).Length;
            _startAngle = 0;
            _endAngle   = 2 * Vec.AngleBetween(rad1, rad2);
        }
Ejemplo n.º 16
0
        public void ValueType_Vec()
        {
            var p1 = new Vec(1, 0, 0);
            var p2 = new Vec(0, 1, 0);

            Assert.IsFalse(p1.IsEqual(p2, 0.99, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 1.01, 0.1));
            Assert.IsTrue(p1.IsEqual(p2, 0.99, Math.PI / 2));
            Assert.IsTrue(p1.IsNormal(p2, 0.1));
            Assert.IsFalse(p1.IsOpposite(p2, 0.1));
            Assert.IsTrue(p1.IsOpposite(p2, Math.PI / 2));
            Assert.IsFalse(p1.IsParallel(p2, 0.1));
            Assert.IsTrue(p1.IsParallel(p2, Math.PI / 2));

            p1 = new Vec(1, 2, 3);
            p2 = new Vec(4, 5, 6);

            Assert.AreEqual(14, p1.SquareMagnitude());
            Assert.AreEqual(Math.Sqrt(14), p1.Magnitude());

            p2 = p1;
            p2.Add(new Vec(1, 2, 3));
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Added(new Vec(1, 2, 3)));

            p2 = new Vec(1, 2, 3);
            p2.Subtract(new Vec(3, 2, 1));
            Assert.AreEqual(new Vec(-2, 0, 2), p2);
            Assert.AreEqual(new Vec(-2, 0, 2), p1.Subtracted(new Vec(3, 2, 1)));

            p2 = new Vec(1, 2, 3);
            p2.Cross(new Vec(3, 2, 1));
            Assert.AreEqual(new Vec(-4, 8, -4), p2);
            Assert.AreEqual(new Vec(-4, 8, -4), p1.Crossed(new Vec(3, 2, 1)));

            Assert.AreEqual(Math.Sqrt(96), p1.CrossMagnitude(new Vec(3, 2, 1)));
            Assert.AreEqual(96, p1.CrossSquareMagnitude(new Vec(3, 2, 1)));

            p2 = new Vec(1, 2, 3);
            p2.CrossCross(new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(-24, -6, 12), p2);
            Assert.AreEqual(new Vec(-24, -6, 12), p1.CrossCrossed(new Vec(1, 2, 3), new Vec(4, 5, 6)));

            p2 = new Vec(1, 2, 3);
            p2.Divide(2);
            Assert.AreEqual(new Vec(0.5, 1, 1.5), p2);
            Assert.AreEqual(new Vec(0.5, 1, 1.5), p1.Divided(2));

            Assert.AreEqual(14, p1.Dot(new Vec(1, 2, 3)));
            Assert.AreEqual(0, p1.DotCross(new Vec(4, 5, 6), new Vec(4, 5, 6)));

            p2 = new Vec(1, 2, 3);
            p2.Multiply(2);
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Multiplied(2));

            p2 = new Vec(1, 2, 3);
            p2.Scale(2);
            Assert.AreEqual(new Vec(2, 4, 6), p2);
            Assert.AreEqual(new Vec(2, 4, 6), p1.Scaled(2));

            p2 = new Vec(1, 2, 3);
            p2.Normalize();
            Assert.IsTrue(p2.IsEqual(new Vec(0.26726, 0.53452, 0.80178), 0.00001, 0.00001));
            Assert.IsTrue(p1.Normalized().IsEqual(new Vec(0.26726, 0.53452, 0.80178), 0.00001, 0.00001));

            p2 = new Vec(1, 2, 3);
            p2.Reverse();
            Assert.AreEqual(new Vec(-1, -2, -3), p2);
            Assert.AreEqual(new Vec(-1, -2, -3), p1.Reversed());

            p2.SetLinearForm(new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(5, 7, 9), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(6, 9, 12), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6));
            Assert.AreEqual(new Vec(14, 19, 24), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), new Vec(7, 8, 9));
            Assert.AreEqual(new Vec(21, 27, 33), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), 4, new Vec(7, 8, 9));
            Assert.AreEqual(new Vec(42, 51, 60), p2);
            p2.SetLinearForm(2, new Vec(1, 2, 3), 3, new Vec(4, 5, 6), 4, new Vec(7, 8, 9), new Vec(10, 11, 12));
            Assert.AreEqual(new Vec(52, 62, 72), p2);

            p2 = new Vec(2, 0, 0);
            p2.Mirror(new Vec(0, 1, 0));
            Assert.AreEqual(new Vec(-2, 0, 0), p2);
            Assert.AreEqual(new Vec(2, 0, 0), p2.Mirrored(new Vec(0, 1, 0)));

            var m2 = new Ax1(new Pnt(-1, 2, -3), new Dir(-1, 0, 0));

            p2 = new Vec(2, 1, 3);
            Assert.AreEqual(new Vec(2, -1, -3), p2.Mirrored(m2));
            p2.Mirror(m2);
            Assert.AreEqual(new Vec(2, -1, -3), p2);

            var a2 = new Ax2(new Pnt(-1, 2, -3), new Dir(-1, 0, 0));

            p2 = new Vec(2, 1, 3);
            Assert.AreEqual("-2,1,3", p2.Mirrored(a2).ToString());
            p2.Mirror(a2);
            Assert.AreEqual("-2,1,3", p2.ToString());

            p2 = new Vec(2, 1, 3);
            Assert.IsTrue(new Vec(2, 3, -1).IsEqual(p2.Rotated(m2, Math.PI / 2), 0.0001, 0.0001));
            p2.Rotate(m2, Math.PI / 2);
            Assert.IsTrue(new Vec(2, 3, -1).IsEqual(p2, 0.0001, 0.0001));

            //TestContext.WriteLine(string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", gp2.x, gp2.y, gp2.z));

            Trsf t1 = new Trsf();

            t1.SetRotation(Ax1.OZ, Math.PI / 2);
            p2 = new Vec(4, 5, 6);
            Assert.AreEqual("-5,4,6", p2.Transformed(t1).ToString());
            p2.Transform(t1);
            Assert.AreEqual("-5,4,6", p2.ToString());
        }
Ejemplo n.º 17
0
 /// <summary>
 /// Creates a plane from 3 independent points.
 /// A normalized normal vector is computed and stored.
 /// </summary>
 public Plane3d(V3d p0, V3d p1, V3d p2)
 {
     Normal   = Vec.Cross(p1 - p0, p2 - p0).Normalized;
     Distance = Vec.Dot(Normal, p0);
 }
Ejemplo n.º 18
0
        public static unsafe Vec radiance(ref Ray r, int depth, ref RandomLCG rand)
        {
            double  t;                                          // distance to intersection
            Sphere *obj = intersect(ref r, out t);

            if (obj == null)
            {
                return(Vec_Zero);                // if miss, return black
            }
            else
            {
                int  newDepth   = depth + 1;
                bool isMaxDepth = newDepth > 100;

                // Russian roulette for path termination
                bool isUseRR = newDepth > 5;
                bool isRR    = isUseRR && rand.NextNumber() < obj->maxC;

                if (isMaxDepth || (isUseRR && !isRR))
                {
                    return(obj->e);
                }
                else
                {
                    Vec f    = (isUseRR && isRR) ? obj->cc : obj->c;
                    var tmp1 = r.d.Mul(t);
                    Vec x    = r.o.Add(ref tmp1);
                    Vec n    = (x.Sub(ref obj->p)).Norm();
                    Vec nl   = n.Dot(ref r.d) < 0 ? n : n.Mul(-1);

                    if (obj->refl == MatType.DIFF)
                    {                     // Ideal DIFFUSE reflection
                        double r1  = 2 * M_PI * rand.NextNumber();
                        double r2  = rand.NextNumber();
                        double r2s = MathSqrt(r2);

                        Vec w  = nl;
                        Vec wo = w.x <-0.1 || w.x> 0.1 ? Vec_YAxis : Vec_XAxis;
                        Vec u  = (wo.Cross(ref w)).Norm();
                        Vec v  = w.Cross(ref u);

                        var tmp2 = v.Mul(MathSin(r1)).Mul(r2s);
                        var tmp3 = w.Mul(MathSqrt(1 - r2));
                        Vec d    = (u.Mul(MathCos(r1)).Mul(r2s).Add(ref tmp2).Add(ref tmp3)).Norm();

                        var tmp4 = new Ray(ref x, ref d);
                        var tmp5 = radiance(ref tmp4, newDepth, ref rand);
                        var tmp6 = f.Mul(ref tmp5);
                        return(obj->e.Add(ref tmp6));
                    }
                    else if (obj->refl == MatType.SPEC)                     // Ideal SPECULAR reflection
                    {
                        var tmp8  = n.Mul(2 * (n.Dot(ref r.d)));
                        var tmp9  = r.d.Sub(ref tmp8);
                        var tmp7  = new Ray(ref x, ref tmp9);
                        var tmp10 = radiance(ref tmp7, newDepth, ref rand);
                        var tmp11 = f.Mul(ref tmp10);
                        return(obj->e.Add(ref tmp11));
                    }
                    else
                    {                     // Ideal dielectric REFRACTION
                        var    tmp100  = n.Mul(2 * (n.Dot(ref r.d)));
                        var    tmp101  = r.d.Sub(ref tmp100);
                        Ray    reflRay = new Ray(ref x, ref tmp101);
                        bool   into    = n.Dot(ref nl) > 0;                     // Ray from outside going in?
                        double nc      = 1;
                        double nt      = 1.5;
                        double nnt     = into ? nc / nt : nt / nc;
                        double ddn     = r.d.Dot(ref nl);
                        double cos2t   = 1 - nnt * nnt * (1 - ddn * ddn);

                        if (cos2t < 0)                         // Total internal reflection
                        {
                            var tmp12 = radiance(ref reflRay, newDepth, ref rand);
                            var tmp13 = f.Mul(ref tmp12);
                            return(obj->e.Add(ref tmp13));
                        }
                        else
                        {
                            var    tmp14 = n.Mul((into ? 1 : -1) * (ddn * nnt + MathSqrt(cos2t)));
                            Vec    tdir  = (r.d.Mul(nnt).Sub(ref tmp14)).Norm();
                            double a     = nt - nc;
                            double b     = nt + nc;
                            double R0    = (a * a) / (b * b);
                            double c     = 1 - (into ? -ddn : tdir.Dot(ref n));
                            double Re    = R0 + (1 - R0) * c * c * c * c * c;
                            double Tr    = 1 - Re;
                            double P     = .25 + .5 * Re;
                            double RP    = Re / P;
                            double TP    = Tr / (1 - P);

                            Vec result;
                            if (newDepth > 2)
                            {
                                // Russian roulette and splitting for selecting reflection and/or refraction
                                if (rand.NextNumber() < P)
                                {
                                    result = radiance(ref reflRay, newDepth, ref rand).Mul(RP);
                                }
                                else
                                {
                                    var tmp15 = new Ray(ref x, ref tdir);
                                    result = radiance(ref tmp15, newDepth, ref rand).Mul(TP);
                                }
                            }
                            else
                            {
                                var tmp16 = new Ray(ref x, ref tdir);
                                var tmp17 = radiance(ref tmp16, newDepth, ref rand).Mul(Tr);
                                result = radiance(ref reflRay, newDepth, ref rand).Mul(Re).Add(ref tmp17);
                            }

                            var tmp18 = f.Mul(ref result);
                            return(obj->e.Add(ref tmp18));
                        }
                    }
                }
            }
        }