public Sphere(Point3D p, float r) { points.Add(p); radius = r; }
public Point3D color_light; // цвет источника света public Light(Point3D p, Point3D c) { point_light = new Point3D(p); color_light = new Point3D(c); }
/// <summary> /// rotate figure line /// </summary> /// <param name="ang">angle in degrees</param> /// <param name="p1">line start</param> /// <param name="p2">line end</param> public void line_rotate(float ang, Point3D p1, Point3D p2) { ang = ang * (float)Math.PI / 180; line_rotate_rad(ang, p1, p2); }
/// /// ----------------------------- STATIC BACKEND FOR TRANSFROMS -------------------------------- /// private static float[,] rotate_around_line(float[,] transform_matrix, Point3D start, Point3D dir, float angle) { float cos_angle = (float)Math.Cos(angle); float sin_angle = (float)Math.Sin(angle); float val00 = dir.x * dir.x + cos_angle * (1 - dir.x * dir.x); float val01 = dir.x * (1 - cos_angle) * dir.y + dir.z * sin_angle; float val02 = dir.x * (1 - cos_angle) * dir.z - dir.y * sin_angle; float val10 = dir.x * (1 - cos_angle) * dir.y - dir.z * sin_angle; float val11 = dir.y * dir.y + cos_angle * (1 - dir.y * dir.y); float val12 = dir.y * (1 - cos_angle) * dir.z + dir.x * sin_angle; float val20 = dir.x * (1 - cos_angle) * dir.z + dir.y * sin_angle; float val21 = dir.y * (1 - cos_angle) * dir.z - dir.x * sin_angle; float val22 = dir.z * dir.z + cos_angle * (1 - dir.z * dir.z); float[,] rotateMatrix = new float[, ] { { val00, val01, val02, 0 }, { val10, val11, val12, 0 }, { val20, val21, val22, 0 }, { 0, 0, 0, 1 } }; return(apply_offset(multiply_matrix(apply_offset(transform_matrix, -start.x, -start.y, -start.z), rotateMatrix), start.x, start.y, start.z)); }
public static float scalar(Point3D p1, Point3D p2) { return(p1.x * p2.x + p1.y * p2.y + p1.z * p2.z); }
public void CalculateSideNormal() { Normal = norm(this); }
public void build_scene() { Figure room = Figure.get_Hexahedron(10); up_left = room.sides[0].get_point(0); up_right = room.sides[0].get_point(1); down_right = room.sides[0].get_point(2); down_left = room.sides[0].get_point(3); Point3D normal = Side.norm(room.sides[0]); // нормаль стороны комнаты Point3D center = (up_left + up_right + down_left + down_right) / 4; // центр стороны комнаты focus = center + normal * 10; room.set_pen(new Pen(Color.Gray)); room.sides[0].drawing_pen = new Pen(Color.Green); room.sides[1].drawing_pen = new Pen(Color.Gold); room.sides[2].drawing_pen = new Pen(Color.DeepPink); room.sides[3].drawing_pen = new Pen(Color.BlueViolet); room.figure_material = new Material(0f, 0, 0.05f, 0.7f); Light l1 = new Light(new Point3D(0f, 2f, 4.9f), new Point3D(1f, 1f, 1f)); Light l2 = new Light(new Point3D(-4.9f, -4.9f, 4.9f), new Point3D(1f, 1f, 1f)); lights.Add(l1); lights.Add(l2); Sphere s1 = new Sphere(new Point3D(-2.5f, 1.7f, -3.7f), 1.4f); s1.set_pen(new Pen(Color.White)); s1.figure_material = new Material(0.05f, 0.9f, 0f, 0f, 1.05f); Sphere s2 = new Sphere(new Point3D(-2.5f, -2, 2.5f), 2f); s2.set_pen(new Pen(Color.White)); s2.figure_material = new Material(0.9f, 0f, 0f, 0.1f, 1f); Figure cube1 = Figure.get_Hexahedron(2.8f); cube1.offset(-0.5f, -1, -3.9f); cube1.rotate_around(55, "CZ"); cube1.set_pen(new Pen(Color.Aqua)); cube1.figure_material = new Material(0f, 0f, 0.1f, 0.7f, 1.5f); Figure cube2 = Figure.get_Hexahedron(1.5f); cube2.offset(-0.5f, -0.9f, -1.7f); cube2.rotate_around(120, "CZ"); cube2.set_pen(new Pen(Color.White)); cube2.figure_material = new Material(0.9f, 0f, 0f, 0.1f, 1.2f); Figure cube3 = Figure.get_Hexahedron(2f); cube3.offset(2.7f, 2.5f, -3.95f); cube3.rotate_around(-10, "CZ"); cube3.set_pen(new Pen(Color.Red)); cube3.figure_material = new Material(0, 0.7f, 0.1f, 0.5f, 1f); scene.Add(room); scene.Add(cube1); scene.Add(cube2); scene.Add(cube3); scene.Add(s1); scene.Add(s2); }
// отражение public Ray reflect(Point3D hit_point, Point3D normal) { Point3D reflect_dir = direction - 2 * normal * Point3D.scalar(direction, normal); return(new Ray(hit_point, hit_point + reflect_dir)); }
public Ray(Ray r) { start = r.start; direction = r.direction; }
public Ray(Point3D st, Point3D end) { start = new Point3D(st); direction = Point3D.norm(end - st); }
public Point3D RayTrace(Ray r, int iter, float env) { if (iter <= 0) { return(new Point3D(0, 0, 0)); } float t = 0; // позиция точки пересечения луча с фигурой на луче Point3D normal = null; Material m = new Material(); Point3D res_color = new Point3D(0, 0, 0); bool refract_out_of_figure = false; foreach (Figure fig in scene) { if (fig.figure_intersection(r, out float intersect, out Point3D n)) { if (intersect < t || t == 0) // нужна ближайшая фигура к точке наблюдения { t = intersect; normal = n; m = new Material(fig.figure_material); } } } if (t == 0) { return(new Point3D(0, 0, 0)); } if (Point3D.scalar(r.direction, normal) > 0) { normal *= -1; refract_out_of_figure = true; } Point3D hit_point = r.start + r.direction * t; foreach (Light l in lights) { Point3D amb = l.color_light * m.ambient; amb.x = (amb.x * m.clr.x); amb.y = (amb.y * m.clr.y); amb.z = (amb.z * m.clr.z); res_color += amb; // диффузное освещение if (is_visible(l.point_light, hit_point)) { res_color += l.shade(hit_point, normal, m.clr, m.diffuse); } } if (m.reflection > 0) { Ray reflected_ray = r.reflect(hit_point, normal); res_color += m.reflection * RayTrace(reflected_ray, iter - 1, env); } if (m.refraction > 0) { float eta; if (refract_out_of_figure) { eta = m.environment; } else { eta = 1 / m.environment; } Ray refracted_ray = r.refract(hit_point, normal, eta); if (refracted_ray != null) { res_color += m.refraction * RayTrace(refracted_ray, iter - 1, m.environment); } } return(res_color); }