Beispiel #1
0
        Vector3 reflect(OpticalSurface surface, Vector3Pair ray, Vector3 normal)
        {
            // Algorithm from Bram de Greve article "Reflections & Refractions in
            // Raytracing" http://www.bramz.org/

            // assert (Math.abs(normal.len() - 1.0) < 1e-10);
            // assert (Math.abs((ray.direction().len()) - 1.0) < 1e-10);

            double cosi = normal.dot(ray.direction());

            return(ray.direction().minus(normal.times(2.0 * cosi)));
        }
        public Distribution get_distribution(OpticalSurface s)
        {
            Distribution d;

            if (!_s_distribution.TryGetValue(s, out d))
            {
                return(_default_distribution);
            }
            else
            {
                return(d);
            }
        }
Beispiel #3
0
        /**
         * Compute refracted ray direction given
         *
         * @param ray    Original ray - position and direction
         * @param normal Normal to the intercept
         * @param mu     Ration of refractive index
         */
        Vector3 compute_refraction(OpticalSurface surface, Vector3Pair ray, Vector3 normal, double mu)
        {
            Vector3 N = normal.times(-1.0); // Because we changed sign at intersection
            // See Feder paper p632
            double O2  = N.dot(N);
            double E1  = ray.direction().dot(N);
            double E1_ = Math.Sqrt(O2 * (1.0 - mu * mu) + mu * mu * E1 * E1);

            if (Double.IsNaN(E1_))
            {
                return(null);
            }

            double g1 = (E1_ - mu * E1) / O2;

            return(ray.direction().times(mu).plus(N.times(g1)));
        }
Beispiel #4
0
        Vector3 refract(OpticalSurface surface, Vector3Pair ray,
                        Vector3 normal,
                        double refract_index)
        {
            // Algorithm from Bram de Greve article "Reflections & Refractions in
            // Raytracing" http://www.bramz.org/

            // assert (Math.abs(normal.len() - 1.0) < 1e-10);
            // assert (Math.abs((ray.direction().len()) - 1.0) < 1e-10);

            double cosi  = normal.dot(ray.direction());
            double sint2 = MathUtils.square(refract_index) * (1.0 - MathUtils.square(cosi));

            if (sint2 > 1.0)
            {
                return(null); // total internal reflection
            }
            Vector3 dir = ray.direction().times(refract_index).minus(
                normal.times(refract_index * cosi + Math.Sqrt(1.0 - sint2)));

            // This uses Feder refractive formula
            Vector3 dir2 = compute_refraction(surface, ray, normal, refract_index);

//        if ((fabs (dir.x () - dir2.x ()) > 1e-14
//                || fabs (dir.y () - dir2.y ()) > 1e-14
//                || fabs (dir.z () - dir2.z ()) > 1e-14))
//        {
//            printf ("Refract Orig  %.16f, %.16f, %.16f\n", dir.x (), dir.y (),
//                    dir.z ());
//            printf ("Refract Feder %.16f, %.16f, %.16f\n", dir2.x (), dir2.y (),
//                    dir2.z ());
//        }

            dir = dir2;
            return(dir);
        }
        void draw_2d_e(Renderer r, Lens lens, Element ref_)
        {
            bool grp = false;

            if (lens.stop() != null)
            {
                draw_2d_e(r, lens.stop(), ref_);
            }

            if (lens.elements().Count == 0)
            {
                return;
            }

            List <OpticalSurface> surfaces = lens.surfaces();
            OpticalSurface        first    = surfaces[0];

            if (first.get_material(1) != first.get_material(0))
            {
                if (!grp)
                {
                    r.group_begin("");
                    grp = true;
                }

                draw_2d_e(r, first, ref_);
            }

            for (int i = 0; i < surfaces.Count - 1; i++)
            {
                OpticalSurface left  = surfaces[i];
                OpticalSurface right = surfaces[i + 1];

                if (left.get_material(1) == null || !(left.get_material(1) is Solid))
                {
                    if (grp)
                    {
                        r.group_end();
                        grp = false;
                    }
                }
                else
                {
                    // draw outter edges
                    double left_top_edge
                        = left.get_shape().get_outter_radius(Vector2.vector2_01);
                    double left_bot_edge
                        = -left.get_shape().get_outter_radius(Vector2.vector2_01.negate());
                    double right_top_edge
                        = right.get_shape().get_outter_radius(Vector2.vector2_01);
                    double right_bot_edge
                        = -right.get_shape().get_outter_radius(Vector2.vector2_01.negate());

                    draw_2d_edge(r, left, left_top_edge, right, right_top_edge,
                                 Lens.LensEdge.StraightEdge, ref_);
                    draw_2d_edge(r, left, left_bot_edge, right, right_bot_edge,
                                 Lens.LensEdge.StraightEdge, ref_);

                    // draw hole edges if not coincident
                    double left_top_hole
                        = left.get_shape().get_hole_radius(Vector2.vector2_01);
                    double left_bot_hole
                        = -left.get_shape().get_hole_radius(Vector2.vector2_01.negate());
                    double right_top_hole
                        = right.get_shape().get_hole_radius(Vector2.vector2_01);
                    double right_bot_hole
                        = -right.get_shape().get_hole_radius(Vector2.vector2_01.negate());

                    if (Math.Abs(left_bot_hole - left_top_hole) > 1e-6 ||
                        Math.Abs(right_bot_hole - right_top_hole) > 1e-6)
                    {
                        draw_2d_edge(r, left, left_top_hole, right, right_top_hole,
                                     Lens.LensEdge.SlopeEdge, ref_);
                        draw_2d_edge(r, left, left_bot_hole, right, right_bot_hole,
                                     Lens.LensEdge.SlopeEdge, ref_);
                    }
                }

                if (right.get_material(1) != right.get_material(0))
                {
                    if (!grp)
                    {
                        r.group_begin("");
                        grp = true;
                    }

                    draw_2d_e(r, right, ref_);
                }
            }

            if (grp)
            {
                r.group_end();
            }
        }
Beispiel #6
0
        private TracedRay trace_ray_simple(OpticalSurface surface, RayTraceResults result, TracedRay incident,
                                           Vector3Pair local, Vector3Pair intersect)
        {
            bool   right_to_left = intersect.normal().z() > 0;
            Medium prev_mat      = surface.get_material(right_to_left ? 1 : 0);
            Medium next_mat      = surface.get_material(!right_to_left ? 1 : 0);

            // check ray didn't "escaped" from its material
            // std::cout << prev_mat->name << " " << next_mat->name <<
            //          " " << incident.get_material()->name << std::endl;

            if (prev_mat != incident.get_material())
            {
                return(null);
            }

            double wl    = incident.get_wavelen();
            double index = prev_mat.get_refractive_index(wl)
                           / next_mat.get_refractive_index(wl);

            // refracted ray direction
            Vector3 direction = refract(surface, local, intersect.normal(), index);

            if (direction == null)
            {
                // total internal reflection
                Vector3   o   = intersect.origin();
                Vector3   dir = reflect(surface, local, intersect.normal());
                TracedRay r   = result.newRay(o, dir);

                r.set_wavelen(wl);
                r.set_intensity(incident.get_intensity());
                r.set_material(prev_mat);

                r.set_creator(surface);
                incident.add_generated(r);

                return(r);
            }

            // transmit
            if (!next_mat.is_opaque())
            {
                Vector3   o = intersect.origin();
                TracedRay r = result.newRay(o, direction);

                r.set_wavelen(wl);
                r.set_intensity(incident.get_intensity());
                r.set_material(next_mat);

                r.set_creator(surface);
                incident.add_generated(r);
                return(r);
            }

            // reflect
            if (next_mat.is_reflecting())
            {
                Vector3 o   = intersect.origin();
                Vector3 dir = reflect(surface, local, intersect.normal());

                TracedRay r = result.newRay(o, dir);

                r.set_wavelen(wl);
                r.set_intensity(incident.get_intensity());
                r.set_material(prev_mat);
                r.set_creator(surface);
                incident.add_generated(r);
                return(r);
            }

            return(null);
        }
Beispiel #7
0
        List <TracedRay> generate_rays(
            RayTraceResults result,
            RayTraceParameters parameters,
            PointSource source,
            Element target,
            PointSource.SourceInfinityMode mode)
        {
            if (!(target is OpticalSurface))
            {
                return(new());
            }

            OpticalSurface   target_surface = (OpticalSurface)target;
            double           rlen           = parameters.get_lost_ray_length();
            Distribution     d    = parameters.get_distribution(target_surface);
            List <TracedRay> rays = new();
            ConsumerVector3  de   = (Vector3 v) =>
            {
                Vector3 r = target_surface.get_transform_to(source).transform(v); // pattern point on target surface
                Vector3 direction;
                Vector3 position;

                switch (mode)
                {
                case PointSource.SourceInfinityMode.SourceAtFiniteDistance:
                    position  = Vector3.vector3_0;
                    direction = r.normalize();
                    break;

                default:
                case PointSource.SourceInfinityMode.SourceAtInfinity:
                    direction = Vector3.vector3_001;
                    position  = new Vector3Pair(
                        target_surface.get_position(source).minus(Vector3.vector3_001.times(rlen)),
                        Vector3.vector3_001)
                                .pl_ln_intersect(new Vector3Pair(r, direction));
                    break;
                }

                foreach (SpectralLine l in source.spectrum())
                {
                    // generated rays use source coordinates
                    TracedRay ray = result.newRay(position, direction);
                    ray.set_creator(source);
                    ray.set_intensity(l.get_intensity()); // FIXME depends on distance from
                    // source and pattern density
                    ray.set_wavelen(l.get_wavelen());
                    Medium material = source.get_material();
                    if (material == null)
                    {
                        material = Air.air; // FIXME centralize as env - original uses env proxy.
                    }

                    ray.set_material(material);
                    rays.Add(ray);
                }
            };

            target_surface.get_pattern(de, d, parameters.get_unobstructed());
            return(rays);
        }