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); } }
/** * 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))); }
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(); } }
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); }
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); }