public float[] TraceRay(float[] origin, float[] direction, float min_t, float max_t, float depth) { var intersection = ClosestIntersection(origin, direction, min_t, max_t); if (intersection.Item1 == null && intersection.Item2 == 0) { return(background_color); } Figure closest_figure = intersection.Item1; float closest_t = intersection.Item2; float[] point = new float[3]; float[] sec_point = new float[3]; float[] res = new float[3]; point = Add(origin, Multiply(closest_t, direction, res), point); sec_point = Add(origin, Multiply(intersection.Item3, direction, res), sec_point); float[] normal = intersection.Item4; float[] view = new float[3]; //?? view = Multiply(-1, direction, view); float lightning; //для блеска lightning = ComputeLighting(point, normal, view, closest_figure.specular); float[] local_color = new float[3]; //вычисл лок цвет local_color = Multiply(lightning, closest_figure.color, local_color); if (closest_figure.reflective <= 0 || depth <= 0) { return(local_color); } float[] reflected_ray = new float[3]; reflected_ray = ReflectRay(view, normal, reflected_ray); float[] reflected_color = new float[3]; //вычисл цвет отражения reflected_color = TraceRay(point, reflected_ray, (float)0.001, float.MaxValue, depth - 1); float[] r1 = new float[3]; float[] r2 = new float[3]; float[] r3 = new float[3]; float[] result = new float[3]; float[] transparent_color = new float[3]; float[] transparent_ray = new float[3]; float[] a = new float[3]; float[] b = new float[3]; float[] c = new float[3]; float[] k = new float[3]; k = Multiply(-1, direction, k); a = Multiply(DotProduct(k, normal) * (float)1.49, k, a); b = Multiply((float)1.49, k, b); c = Multiply((float)Math.Sqrt(1 + (float)1.49 * (float)1.49 * DotProduct(k, normal) * DotProduct(k, normal) - 1), normal, c); transparent_ray = Subtract(a, b, transparent_ray); transparent_ray = Subtract(transparent_ray, c, transparent_ray); closest_figure.flag = 1; transparent_color = TraceRay(sec_point, transparent_ray, 1, float.MaxValue, depth); closest_figure.flag = 0; //смеш цветов? r1 = Multiply(1 - closest_figure.reflective, local_color, r1); r2 = Multiply(closest_figure.reflective, reflected_color, r2); r3 = Multiply(closest_figure.transparent, transparent_color, r3); result = Add(r1, r2, result); result = Add(result, r3, result); return(result); }
public Tuple <Figure, float, float, float[]> ClosestIntersection(float[] origin, float[] direction, float min_t, float max_t) { float sec_point = 0; float[] n = new float[3]; int[] flag = new int[2]; float[] point = new float[3]; float[] res = new float[3]; float[] ress = new float[3]; float[] normal = new float[3]; float[] ts = new float[2]; float[] tc = new float[2]; float tcc; float tt; float closest_t = float.MaxValue; Figure closest_figure = null; for (int i = 0; i < spheres.Length; i++) { if (spheres[i].flag == 0) { ts = IntersectRaySphere(origin, direction, spheres[i], ts); if (ts[0] < closest_t && min_t < ts[0] && ts[0] < max_t) { closest_t = ts[0]; closest_figure = spheres[i]; flag[0] = 1; flag[1] = i; sec_point = ts[1]; } if (ts[1] < closest_t && min_t < ts[1] && ts[1] < max_t) { closest_t = ts[1]; closest_figure = spheres[i]; flag[0] = 1; flag[1] = i; sec_point = ts[0]; } } } for (int i = 0; i < triangles.Length; i++) { if (triangles[i].flag == 0) { float[] AB = new float[3]; AB = Subtract(triangles[i].point2, triangles[i].point1, AB); float[] AC = new float[3]; AC = Subtract(triangles[i].point3, triangles[i].point1, AC); n = VecMultiply(AB, AC, n); tt = IntersectRayTriangle(origin, direction, triangles[i], n, AB); //normal = Multiply(1 / Length(n), n, n); if (tt < closest_t && min_t < tt && tt < max_t) { closest_t = tt; closest_figure = triangles[i]; flag[0] = 0; if (i % 2 != 0) { flag[1] = i - 1; } else { flag[1] = i; } //normal = Multiply(1 / Length(n), n, n); } } } for (int i = 0; i < cilinders.Length; i++) { if (cilinders[i].flag == 0) { tc = IntersectRayCilinder(origin, direction, cilinders[i], tc); if (tc[0] < closest_t && min_t < tc[0] && tc[0] < max_t) { closest_t = tc[0]; closest_figure = cilinders[i]; flag[0] = 2; flag[1] = i; } if (tc[1] < closest_t && min_t < tc[1] && tc[1] < max_t) { closest_t = tc[1]; closest_figure = cilinders[i]; flag[0] = 2; flag[1] = i; } } } if (closest_figure != null) { if (flag[0] == 1) { point = Add(origin, Multiply(closest_t, direction, res), point); normal = Subtract(point, spheres[flag[1]].center, normal); normal = Multiply(1 / Length(normal), normal, normal); } if (flag[0] == 2) { point = Add(origin, Multiply(closest_t, direction, ress), point); float[] M = new float[3]; M[0] = cilinders[flag[1]].center[0]; M[1] = point[1]; M[2] = cilinders[flag[1]].center[2]; normal = Subtract(point, M, normal); normal = Multiply(1 / Length(normal), normal, normal); } if (flag[0] == 0) { float[] AB = new float[3]; float[] AC = new float[3]; AB = Subtract(triangles[flag[1]].point2, triangles[flag[1]].point1, AB); AC = Subtract(triangles[flag[1]].point3, triangles[flag[1]].point1, AC); normal = VecMultiply(AB, AC, normal); //normal[0] = 2; //normal[1] = 0; //normal[2] = -2; normal = Multiply(1 / Length(normal), normal, normal); } return(new Tuple <Figure, float, float, float[]>(closest_figure, closest_t, sec_point, normal)); } return(new Tuple <Figure, float, float, float[]>(null, 0, 0, null)); }