Advertisement
codisinmyvines

RayTracing

Dec 15th, 2021
816
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 14.22 KB | None | 0 0
  1. package RayTracing;
  2.  
  3. import javax.swing.*;
  4. import java.awt.*;
  5. import java.util.Objects;
  6.  
  7. class Constants {
  8.     public static int canvasHeight = 600;
  9.     public static int canvasWidth = 800;
  10.     public static int viewPortHeight = 1;
  11.     public static int viewPortWidth = 1;
  12. }
  13.  
  14. class Vector3d {
  15.     double x, y, z;
  16.  
  17.     public Vector3d() {
  18.         x = y = z = 0;
  19.     }
  20.  
  21.     public Vector3d(double x, double y, double z) {
  22.         this.x = x;
  23.         this.y = y;
  24.         this.z = z;
  25.     }
  26.  
  27.     public static double Dot(Vector3d v1, Vector3d v2) {
  28.         return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
  29.     }
  30.  
  31.     public static double Length(Vector3d v) {
  32.         return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
  33.     }
  34.  
  35.     public static Vector3d MultMatrixVect(Vector3d v, double[][] matrixRot) {
  36.         return new Vector3d(matrixRot[0][0] * v.x + matrixRot[0][1] * v.y + matrixRot[0][2] * v.z,
  37.                 matrixRot[1][0] * v.x + matrixRot[1][1] * v.y + matrixRot[1][2] * v.z,
  38.                 matrixRot[2][0] * v.x + matrixRot[2][1] * v.y + matrixRot[2][2] * v.z);
  39.     }
  40. }
  41.  
  42. class Vector2d {
  43.     double x, y;
  44.  
  45.     public Vector2d() {
  46.         x = y = 0;
  47.     }
  48.  
  49.     public Vector2d(double x, double y) {
  50.         this.x = x;
  51.         this.y = y;
  52.     }
  53. }
  54.  
  55. class Sphere_t {
  56.     Sphere sphere;
  57.     double t;
  58.  
  59.     public Sphere_t(Sphere sphere, double t) {
  60.         this.sphere = sphere;
  61.         this.t = t;
  62.     }
  63. }
  64.  
  65. class Sphere {
  66.     Vector3d center;
  67.     Color color;
  68.     double radius;
  69.     int specular; //зеркальность
  70.  
  71.     public Sphere(Vector3d center, double radius, Color color, int specular) {
  72.         this.center = center;
  73.         this.radius = radius;
  74.         this.color = color;
  75.         this.specular = specular;
  76.     }
  77. }
  78.  
  79. class Plane {
  80.     Vector3d point;
  81.     Vector3d n;
  82.     Color color;
  83.  
  84.     public Plane(Vector3d point, Vector3d n, Color color) {
  85.         this.point = point;
  86.         this.n = n;
  87.         this.color = color;
  88.     }
  89. }
  90.  
  91. class Light {
  92.     String type;
  93.     float intensity;
  94.     Vector3d position;
  95.     Vector3d direction;
  96.  
  97.     public Light(String type, float intensity, Vector3d position, Vector3d direction) {
  98.         this.type = type;
  99.         this.intensity = intensity;
  100.         this.position = position;
  101.         this.direction = direction;
  102.     }
  103. }
  104.  
  105. class DrawComponent extends JComponent {
  106.     public void paint(Graphics g) {
  107.         Graphics2D g2 = (Graphics2D) g;
  108.         Vector3d O = new Vector3d(0, 0, 0); //положение камеры
  109.         double projection_plane_d = 1;
  110.         double degrees = 0; //уголь поворота
  111.         double radians = Math.toRadians(degrees);
  112.         //матрицы поворота
  113.         double Mupdown[][] = {{1, 0, 0}, {0, Math.cos(radians), -Math.sin(radians)}, {0, Math.sin(radians), Math.cos(radians)}};
  114.         double Mrightleft[][] = {{Math.cos(radians), 0, Math.sin(radians)}, {0, 1, 0}, {-Math.sin(radians), 0, Math.cos(radians)}};
  115.         //инициализация наших объектов
  116.         Sphere[] spheres = {
  117.                 new Sphere(new Vector3d(0, -1, 3), 1, new Color(255, 0, 0), 50),
  118.                 new Sphere(new Vector3d(2, 0, 4), 1, new Color(0, 0, 255), 5),
  119.                 new Sphere(new Vector3d(-2, 0, 4), 1, new Color(0, 255, 0), 10)
  120.         };
  121.         Plane[] planes = {
  122.                 new Plane(new Vector3d(0, 0, 5), new Vector3d(0, 0, 1), new Color(200, 162, 200)),
  123.                 //new Plane(new Vector3d(0,0,10), new Vector3d(0,0,1), new Color(200,162,200))
  124.         };
  125.         Light[] lights = {
  126.                 new Light("ambient", 0.2f, null, null),
  127.                 new Light("point", 0.6f, new Vector3d(2, 4, 0), null),
  128.                 new Light("directional", 0.2f, null, new Vector3d(1, 4, 4))
  129.         };
  130.         for (int S_x = 0; S_x <= Constants.canvasWidth; S_x++) {
  131.             int x = S_x - Constants.canvasWidth / 2;
  132.             for (int S_y = 0; S_y <= Constants.canvasHeight; S_y++) {
  133.                 int y = Constants.canvasHeight / 2 - S_y;
  134.                 Vector3d D = CanvasToViewport(x, y, projection_plane_d);
  135.                 Vector3d nD = Vector3d.MultMatrixVect(D, Mrightleft);
  136.                 //для сфер
  137.                 //Color color = TraceRay(O, nD, 1, Double.POSITIVE_INFINITY, spheres, lights);
  138.                 //для плоскости
  139.                 Color color = TraceRay_Plane(O, nD, 1, Double.POSITIVE_INFINITY, planes, lights);
  140.                 g2.setPaint(color);
  141.                 g2.fillRect(S_x, S_y, 1, 1);
  142.             }
  143.         }
  144.     }
  145.  
  146.     private Vector3d CanvasToViewport(double x, double y, double d) { //d-расстояние до плоскости проекции
  147.         return new Vector3d(x * Constants.viewPortWidth / Constants.canvasWidth, y * Constants.viewPortHeight / Constants.canvasHeight, d);
  148.     }
  149.  
  150.     //вычисляет пересечение луча с каждой сферой и возвращает цвет сферы в ближайшей точке пересечения
  151.     private Color TraceRay(Vector3d O, Vector3d D, double tMin, double tMax, Sphere[] spheres, Light[] lights) {
  152.         Sphere_t st = ClosestIntersection(O, D, tMin, tMax, spheres);
  153.         Sphere closest_sphere = st.sphere;
  154.         double closest_t = st.t;
  155.         if (closest_sphere == null) {
  156.             return getBackground();
  157.         }
  158.         Vector3d P = new Vector3d(O.x + closest_t * D.x, O.y + closest_t * D.y, O.z + closest_t * D.z); //вычисление пересечения
  159.         //вычисление нормали сферы в точке пересечения
  160.         Vector3d N = new Vector3d(P.x - closest_sphere.center.x, P.y - closest_sphere.center.y, P.z - closest_sphere.center.z);
  161.         Vector3d N_real = new Vector3d(N.x / Vector3d.Length(N), N.y / Vector3d.Length(N), N.z / Vector3d.Length(N));
  162.         int argb = closest_sphere.color.getRGB();
  163.         int alpha = (argb >> 24) & 0xff;
  164.         int red = (argb >> 16) & 0xff;
  165.         int green = (argb >> 8) & 0xff;
  166.         int blue = (argb) & 0xff;
  167.         float r, g, b;
  168.         r = (float) red / 255;
  169.         g = (float) green / 255;
  170.         b = (float) blue / 255;
  171.         Vector3d _D = new Vector3d(-D.x, -D.y, -D.z);
  172.         float f_red = r * ComputeLighting(P, N_real, _D, closest_sphere.specular, lights, spheres);
  173.         float f_green = g * ComputeLighting(P, N_real, _D, closest_sphere.specular, lights, spheres);
  174.         float f_blue = b * ComputeLighting(P, N_real, _D, closest_sphere.specular, lights, spheres);
  175.         if (f_red > 1)
  176.             f_red = 1;
  177.         if (f_green > 1)
  178.             f_green = 1;
  179.         if (f_blue > 1)
  180.             f_blue = 1;
  181.         return new Color(f_red, f_green, f_blue);
  182.     }
  183.  
  184.     private Sphere_t ClosestIntersection(Vector3d O, Vector3d D, double tMin, double tMax, Sphere[] spheres) {
  185.         double closest_t = Double.POSITIVE_INFINITY;
  186.         Sphere closest_sphere = null;
  187.         for (Sphere sphere :
  188.                 spheres) {
  189.             Vector2d t1andt2 = IntersectRaySphere(O, D, sphere);
  190.             if (t1andt2.x >= tMin && t1andt2.x <= tMax && t1andt2.x < closest_t) {
  191.                 closest_t = t1andt2.x;
  192.                 closest_sphere = sphere;
  193.             }
  194.             if (t1andt2.y >= tMin && t1andt2.y <= tMax && t1andt2.y < closest_t) {
  195.                 closest_t = t1andt2.y;
  196.                 closest_sphere = sphere;
  197.             }
  198.         }
  199.         return new Sphere_t(closest_sphere, closest_t);
  200.     }
  201.  
  202.     private Vector2d IntersectRaySphere(Vector3d O, Vector3d D, Sphere s) {
  203.         Vector3d C = s.center;
  204.         double r = s.radius;
  205.         Vector3d oc = new Vector3d(O.x - C.x, O.y - C.y, O.z - C.z);
  206.  
  207.         double k1, k2, k3, disc, t1, t2;
  208.         k1 = Vector3d.Dot(D, D);
  209.         k2 = 2 * Vector3d.Dot(oc, D);
  210.         k3 = Vector3d.Dot(oc, oc) - r * r;
  211.  
  212.         disc = k2 * k2 - 4 * k1 * k3;
  213.         if (disc < 0)
  214.             return new Vector2d(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
  215.  
  216.         t1 = (-k2 + Math.sqrt(disc)) / (2 * k1);
  217.         t2 = (-k2 - Math.sqrt(disc)) / (2 * k1);
  218.         return new Vector2d(t1, t2);
  219.     }
  220.  
  221.     private float ComputeLighting(Vector3d P, Vector3d N, Vector3d V, int s, Light[] lights, Sphere[] spheres) {
  222.         float i = 0;
  223.         Vector3d L;
  224.         double tMax;
  225.         for (Light light : lights) {
  226.             if (Objects.equals(light.type, "ambient")) {
  227.                 i += light.intensity;
  228.             } else {
  229.                 if (Objects.equals(light.type, "point")) {
  230.                     L = new Vector3d(light.position.x - P.x, light.position.y - P.y, light.position.z - P.z);
  231.                     tMax = 1;
  232.                 } else {
  233.                     L = new Vector3d(light.direction.x, light.direction.y, light.direction.z);
  234.                     tMax = Double.POSITIVE_INFINITY;
  235.                 }
  236.                 double n_dot_l = Vector3d.Dot(N, L);
  237.                 //проверка тени
  238.                 Sphere_t st = ClosestIntersection(P, L, 0.001, tMax, spheres);
  239.                 if (st.sphere != null)
  240.                     continue;
  241.                 //диффузность
  242.                 if (n_dot_l > 0)
  243.                     i += light.intensity * n_dot_l / (Vector3d.Length(N) * Vector3d.Length(L));
  244.                 //зеркальность
  245.                 if (s != 1) {
  246.                     Vector3d R = new Vector3d(2 * Vector3d.Dot(N, L) * N.x - L.x,
  247.                             2 * Vector3d.Dot(N, L) * N.y - L.y,
  248.                             2 * Vector3d.Dot(N, L) * N.z - L.z);
  249.                     double r_dot_v = Vector3d.Dot(R, V);
  250.                     if (r_dot_v > 0) {
  251.                         i += light.intensity * Math.pow(r_dot_v / (Vector3d.Length(R) * Vector3d.Length(V)), s);
  252.                     }
  253.                 }
  254.             }
  255.         }
  256.         return i;
  257.     }
  258.  
  259.     private Color TraceRay_Plane(Vector3d O, Vector3d D, double tMin, double tMax, Plane[] planes, Light[] lights) {
  260.         double closest_t = Double.POSITIVE_INFINITY;
  261.         Plane closest_plane = null;
  262.         for (Plane plane : planes) {
  263.             double t = IntersectRayPlane(O, D, plane);
  264.             if (t >= tMin && t <= tMax && t < closest_t) {
  265.                 closest_t = t;
  266.                 closest_plane = plane;
  267.             }
  268.         }
  269.         if (closest_plane == null) {
  270.             return getBackground();
  271.         }
  272.         Vector3d P = new Vector3d(O.x + closest_t * D.x, O.y + closest_t * D.y, O.z + closest_t * D.z); //вычисление пересечения
  273.         //вычисление нормали сферы в точке пересечения
  274.         Vector3d N = new Vector3d(P.x - closest_plane.point.x, P.y - closest_plane.point.y, P.z - closest_plane.point.z);
  275.         Vector3d N_real = new Vector3d(N.x / Vector3d.Length(N), N.y / Vector3d.Length(N), N.z / Vector3d.Length(N));
  276.         int argb = closest_plane.color.getRGB();
  277.         int alpha = (argb >> 24) & 0xff;
  278.         int red = (argb >> 16) & 0xff;
  279.         int green = (argb >> 8) & 0xff;
  280.         int blue = (argb) & 0xff;
  281.         float r, g, b;
  282.         r = (float) red / 255;
  283.         g = (float) green / 255;
  284.         b = (float) blue / 255;
  285.         Vector3d _D = new Vector3d(-D.x, -D.y, -D.z);
  286.         float f_red = r * ComputeLightingPlane(P, N_real, lights);
  287.         float f_green = g * ComputeLightingPlane(P, N_real, lights);
  288.         float f_blue = b * ComputeLightingPlane(P, N_real, lights);
  289.         if (f_red > 1)
  290.             f_red = 1;
  291.         if (f_green > 1)
  292.             f_green = 1;
  293.         if (f_blue > 1)
  294.             f_blue = 1;
  295.         return new Color(f_red, f_green, f_blue);
  296.     }
  297.  
  298.     private double IntersectRayPlane(Vector3d O, Vector3d D, Plane plane) {
  299.         Vector3d nPlane = plane.n;
  300.         double c = Vector3d.Dot(D, nPlane);
  301.         if (c == 0) {
  302.             return Double.POSITIVE_INFINITY;
  303.         }
  304.         double d = Vector3d.Dot(plane.point, nPlane);
  305.         double alpha = (d - Vector3d.Dot(O, nPlane)) / c;
  306.         if (alpha < 0) {
  307.             return Double.POSITIVE_INFINITY;
  308.         }
  309.         return alpha;
  310.     }
  311.  
  312.     private float ComputeLightingPlane(Vector3d P, Vector3d N, Light[] lights) {
  313.         float i = 0;
  314.         Vector3d L;
  315.         //double tMax;
  316.         for (Light light : lights) {
  317.             if (Objects.equals(light.type, "ambient")) {
  318.                 i += light.intensity;
  319.             } else {
  320.                 if (Objects.equals(light.type, "point")) {
  321.                     L = new Vector3d(light.position.x - P.x, light.position.y - P.y, light.position.z - P.z);
  322.                     //tMax=1;
  323.                 } else {
  324.                     L = new Vector3d(light.direction.x, light.direction.y, light.direction.z);
  325.                     //tMax=Double.POSITIVE_INFINITY;
  326.                 }
  327.                 double n_dot_l = Vector3d.Dot(N, L);
  328.                 //проверка тени
  329.                 /*
  330.                 Sphere_t st = ClosestIntersection(P,L,0.001,tMax,spheres);
  331.                 if(st.sphere!=null)
  332.                     continue;
  333.  
  334.                  */
  335.                 //диффузность
  336.                 if (n_dot_l > 0)
  337.                     i += light.intensity * n_dot_l / (Vector3d.Length(N) * Vector3d.Length(L));
  338.                 //зеркальность
  339.                 /*
  340.                 if(s!=1) {
  341.                     Vector3d R = new Vector3d(2*Vector3d.Dot(N,L)*N.x-L.x,
  342.                             2*Vector3d.Dot(N,L)*N.y-L.y,
  343.                             2*Vector3d.Dot(N,L)*N.z-L.z);
  344.                     double r_dot_v = Vector3d.Dot(R,V);
  345.                     if(r_dot_v>0) {
  346.                         i+=light.intensity*Math.pow(r_dot_v/(Vector3d.Length(R)*Vector3d.Length(V)),s);
  347.                     }
  348.                 }
  349.                  */
  350.             }
  351.         }
  352.         return i;
  353.     }
  354. }
  355.  
  356. class MyFrame extends JFrame {
  357.  
  358.     public MyFrame() {
  359.         setSize(Constants.canvasWidth, Constants.canvasHeight);
  360.         setTitle("MyPicture");
  361.         setDefaultCloseOperation(EXIT_ON_CLOSE);
  362.         setVisible(true);
  363.         DrawComponent dc = new DrawComponent();
  364.         add(dc);
  365.     }
  366. }
  367.  
  368. public class RayTracing {
  369.     public static void main(String[] args) {
  370.         new MyFrame();
  371.     }
  372. }
  373.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement