コード例 #1
0
        public void SimpleCameraTest()
        {
            // Ray cast for screen coordinate 0,0
            {
                var camera      = new SimpleCamera(new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), 6.0, 600, 800);
                var ray         = camera.GetRay(0, 0);
                var expectedRay = new Ray(
                    new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point),
                    Tuple4.Normalize(new Tuple4(-3.0, 3.0, 1.0, TupleFlavour.Vector)));
                Assert.Equal(expectedRay.origin, ray.origin);
                Assert.Equal(expectedRay.dir, ray.dir);

                var t = Tuple4.Add(ray.origin, Tuple4.Scale(ray.dir, 4.35890));
                Assert.Equal(new Tuple4(-3.0, 3.0, -3.0, TupleFlavour.Point), t);
            }

            // Ray cast for screen coordinate width,height
            {
                var camera      = new SimpleCamera(new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), 6.0, 600, 800);
                var ray         = camera.GetRay(600, 800);
                var expectedRay = new Ray(
                    new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point),
                    Tuple4.Normalize(new Tuple4(3.0, -3.0, 1.0, TupleFlavour.Vector)));
                Assert.Equal(expectedRay.origin, ray.origin);
                Assert.Equal(expectedRay.dir, ray.dir);
            }

            {
                var camera = new SimpleCamera(new Tuple4(0, 0, -1.0, TupleFlavour.Point), 2.0, 600, 600);
                var ray    = camera.GetRay(0, 0);

                var t = Tuple4.Add(ray.origin, Tuple4.Scale(ray.dir, 1.73205));
                Assert.Equal(new Tuple4(-1.0, 1.0, 0.0, TupleFlavour.Point), t);
            }
        }
コード例 #2
0
        public void TupleScaleByTest()
        {
            var t1 = new Tuple4(1, 7, 3, TupleFlavour.Vector);

            var expected = new Tuple4(0.5, 3.5, 1.5, TupleFlavour.Vector);

            Assert.Equal(expected, Tuple4.Scale(t1, 0.5));
        }
コード例 #3
0
        public void Then_scale_scalar3(string a, double s, double t1, double t2, double t3)
        {
            var c = Tuple4.Scale(cache[a], s);

            Assert.True(Constants.EpsilonCompare(t1, c.X));
            Assert.True(Constants.EpsilonCompare(t2, c.Y));
            Assert.True(Constants.EpsilonCompare(t3, c.Z));
        }
コード例 #4
0
        public void TupleScaleTest()
        {
            var t1 = new Tuple4(1, 7, 3, TupleFlavour.Vector);
            var t2 = new Tuple4(4, 5, 6, TupleFlavour.Vector);

            var expected = new Tuple4(4, 35, 18, TupleFlavour.Vector);

            Assert.Equal(expected, Tuple4.Scale(t1, t2));
        }
コード例 #5
0
        public void Then_scale_vector(string a, string b, double t1, double t2, double t3)
        {
            var c = Tuple4.Scale(cache[a], cache[b]);

            Assert.True(Constants.EpsilonCompare(t1, c.X));
            Assert.True(Constants.EpsilonCompare(t2, c.Y));
            Assert.True(Constants.EpsilonCompare(t3, c.Z));
            Assert.True(c.IsVector());
        }
コード例 #6
0
        public static Tuple4 GetShadedColor(Tuple4 objectPoint, IMaterial material, Tuple4 white, Tuple4 lightDirection, double intensity, Tuple4 eyeVector, Tuple4 pointOnSurface, Tuple4 surfaceNormal)
        {
            Tuple4   color       = material.GetColor(objectPoint);
            Lighting lighting    = GetIntensity(material, lightDirection, intensity, eyeVector, pointOnSurface, surfaceNormal);
            var      shadedColor = Tuple4.Add(
                Tuple4.Scale(color, lighting.intensity * lighting.diffuse),
                Tuple4.Scale(white, lighting.specular)
                );

            return(shadedColor);
        }
コード例 #7
0
        public virtual HitResult[] AllHits(Tuple4 origin, Tuple4 dir)
        {
            var intersections = GetIntersections(new Ray(origin, dir));

            if (intersections == null)
            {
                return(new HitResult[] { HitResult.NoHit });
            }

            var result = new HitResult[intersections.Length];

            for (int i = 0; i < intersections.Length; ++i)
            {
                var figure         = intersections[i].figure;
                var distance       = intersections[i].t;
                var pointOnSurface = Tuple4.Geometry3D.MovePoint(origin, dir, distance); // orig + dir*dist
                // TODO: Remove this cast to BaseFigure
                (var surfaceNormal, var objectPoint) = ((BaseFigure)figure).GetTransformedNormal(figure, pointOnSurface, intersections[i].u, intersections[i].v);
                var eyeVector = Tuple4.Negate(dir);
                var isInside  = false;
                if (Tuple4.DotProduct(surfaceNormal, eyeVector) < 0)
                {
                    isInside      = true;
                    surfaceNormal = Tuple4.Negate(surfaceNormal);
                }
                var pointOverSurface  = Tuple4.Add(pointOnSurface, Tuple4.Scale(surfaceNormal, Constants.Epsilon));
                var pointUnderSurface = Tuple4.Subtract(pointOnSurface, Tuple4.Scale(surfaceNormal, Constants.Epsilon));
                var reflectionVector  = Tuple4.Reflect(dir, surfaceNormal);

                result[i] = new HitResult(true,
                                          figure,
                                          distance,
                                          intersections[i].u,
                                          intersections[i].v,
                                          objectPoint,
                                          pointOnSurface,
                                          pointOverSurface,
                                          pointUnderSurface,
                                          surfaceNormal,
                                          eyeVector,
                                          reflectionVector,
                                          isInside);
            }

            return(result);
        }
コード例 #8
0
        public bool IsShadowed(ILight light, Tuple4 pointOverSurface)
        {
            var lightDir = light.GetLightDirection(pointOverSurface);

            if (!lightDir.Equals(Tuple4.ZeroVector))
            {
                var lh = CalculateIntersection(Tuple4.Add(pointOverSurface, Tuple4.Scale(lightDir, Constants.Epsilon)), lightDir);
                if (lh.IsHit)
                {
                    var distance = light.GetLightDistance(pointOverSurface);
                    if (lh.Distance < distance)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
コード例 #9
0
        private Tuple4 CalculateReflectedColorAt(HitResult hit, int remaining)
        {
            if (!hit.IsHit || remaining <= 0)
            {
                return(colors.Black);
            }

            var material = hit.Figure.Material;

            if (Constants.EpsilonZero(material.Reflective))
            {
                return(Tuple4.ZeroVector);
            }

            var reflectedRay   = new Ray(hit.PointOverSurface, hit.ReflectionVector);
            var reflectedColor = CastRay(reflectedRay, remaining - 1);

            return(Tuple4.Scale(reflectedColor, material.Reflective));
        }
コード例 #10
0
        private Tuple4 CalculateColorAt(HitResult hit, double refractiveIndexEntering, double refractiveIndexExiting, int remaining)
        {
            if (!hit.IsHit)
            {
                return(colors.Black);
            }

            var material = hit.Figure.Material;
            var surface  = Tuple4.ZeroVector;

            foreach (var light in lights)
            {
                // Shadow
                if (castShadows && IsShadowed(light, hit.PointOverSurface))
                {
                    continue;
                }
                surface = Tuple4.Add(surface, light.GetShadedColor(hit.ObjectPoint, material, hit.EyeVector, hit.PointOnSurface, hit.SurfaceNormal));
            }

            var reflected = CalculateReflectedColorAt(hit, remaining);
            var refracted = CalculateRefractedColorAt(hit, refractiveIndexEntering, refractiveIndexExiting, remaining);

            Tuple4 color;

            if (material.Reflective > 0 && material.Transparency > 0)
            {
                var reflectance = Schlick(hit, refractiveIndexEntering, refractiveIndexExiting);
                color = Tuple4.Add(surface, Tuple4.Add(Tuple4.Scale(reflected, reflectance), Tuple4.Scale(refracted, 1.0 - reflectance)));
            }
            else
            {
                color = Tuple4.Add(surface, Tuple4.Add(reflected, refracted));
            }

            return(new Tuple4(Math.Min(colors.White.X, color.X),
                              Math.Min(colors.White.X, color.Y),
                              Math.Min(colors.White.X, color.Z),
                              TupleFlavour.Vector));
        }
コード例 #11
0
        private Tuple4 CalculateRefractedColorAt(HitResult hit, double refractiveIndexEntering, double refractiveIndexExiting, int remaining)
        {
            if (!hit.IsHit || remaining <= 0)
            {
                return(colors.Black);
            }

            var material = hit.Figure.Material;

            if (Constants.EpsilonZero(material.Transparency))
            {
                return(colors.Black);
            }

            // Calculations are based on Snell's law

            var ration = refractiveIndexEntering / refractiveIndexExiting;
            var cosI   = Tuple4.DotProduct(hit.EyeVector, hit.SurfaceNormal);

            // sin(t) * sin(t) = (ration * ration) * (1 - cos(I) * cos(I))
            var sinTheta2 = ration * ration * (1 - cosI * cosI);

            if (sinTheta2 > 1.0)
            {
                // Total internal reflection
                return(colors.Black);
            }

            var cosTheta = Math.Sqrt(1 - sinTheta2);
            var dir      = Tuple4.Subtract(Tuple4.Scale(hit.SurfaceNormal, ration * cosI - cosTheta),
                                           Tuple4.Scale(hit.EyeVector, ration));

            var refractedRay   = new Ray(hit.PointUnderSurface, dir);
            var refractedColor = CastRay(refractedRay, remaining - 1);

            return(Tuple4.Scale(refractedColor, material.Transparency));
        }
コード例 #12
0
 protected override Tuple4 GetBaseNormal(IFigure figure, Tuple4 pointOnSurface, double u, double v)
 {
     return(Tuple4.Add(Tuple4.Scale(N2, u),
                       Tuple4.Add(Tuple4.Scale(N3, v), Tuple4.Scale(N1, (1.0 - u - v)))));
 }
コード例 #13
0
 public static Tuple4 GetAmbientColor(Tuple4 objectPoint, IMaterial material)
 {
     return(Tuple4.Scale(material.GetColor(objectPoint), material.Ambient));
 }
コード例 #14
0
 protected override Tuple4 GetColorAtPattern(Tuple4 pointInPatternSpace)
 {
     return(Tuple4.Add(ColorA, Tuple4.Scale(colorDelta, Math.Abs(pointInPatternSpace.X) - Math.Floor(Math.Abs(pointInPatternSpace.X)))));
 }