public void render(EIn objIn) { //screen rotation() //screen translation() float[] tmp_colour0 = { 0, 0, 0 }; Sphere sph_tmp = new Sphere(0, 0, 0, -1, tmp_colour0); Plane plane_tmp = new Plane(0, 0, 0, -1, tmp_colour0); Sphere sph_tmp2 = new Sphere(0, 0, 0, -1, tmp_colour0); Plane plane_tmp2 = new Plane(0, 0, 0, -1, tmp_colour0); int startx = objIn.start % 2001; int starty = objIn.start / 2001; int endx = objIn.end % 2001; int endy = objIn.end / 2001; //camera translation() for (int y_dir = starty - 1000; y_dir <= endy - 1000; y_dir++) { int row_start, row_end; if (y_dir == starty) row_start = startx; else row_start = 0; if (y_dir == endy) row_end = endx; else row_end = 2000; for (int x_dir = row_start - 1000; x_dir <= row_end - 1000; x_dir++) { float intensity = 1; float reflectionValue = 1; bool temp_pixel_val = true; int reflectDepth = 0; float lightingMultiplier; double[] reflectedRay = { 0, 0, 0 }; //ambient Lighting float[] pixelColour = { 0, 0, 0 }; double[] t_in = { 0, 0, 0, 0, 0, 0, 0 }; double[] t_in_tmp = { 0, 0, 0, 0, 0, 0, 0 }; foreach (Sphere sph in scene.spheres) { t_in_tmp = sphereIntersect(x_dir, y_dir, sph); if (t_in_tmp[3] != 0 && ((t_in_tmp[3] < t_in[3]) || t_in[3] == 0)) { Array.Copy(t_in_tmp, t_in, 7); sph_tmp = (Sphere)sph.clone(); //1st is not plane plane_tmp.dist = -1; } } foreach (Plane plane in scene.planes) { t_in_tmp = planeIntersect(x_dir, y_dir, plane); if (t_in_tmp[3] != 0 && ((t_in_tmp[3] < t_in[3]) || t_in[3] == 0)) { Array.Copy(t_in_tmp, t_in, 7); plane_tmp = (Plane)plane.clone(); //1st is not sphere sph_tmp.radius = -1; } } if (t_in[3] != 0) { intensity = (float)Math.Pow(0.9995, t_in[3] + 1); foreach (Sphere sph in scene.spheres) { temp_pixel_val &= ShadowRaySph(t_in, sph); } foreach (Plane plane in scene.planes) { temp_pixel_val &= ShadowRayPlane(t_in, plane); } //no obstruction between first intersection and light source if (temp_pixel_val) { //if the first object intersected is a sphere if (sph_tmp.radius != -1) { lightingMultiplier = scene.light.intensity * intensity; pixelColour[0] += lightingMultiplier * sph_tmp.colour[0]; pixelColour[1] += lightingMultiplier * sph_tmp.colour[1]; pixelColour[2] += lightingMultiplier * sph_tmp.colour[2]; } //if the first object intersected is a plane else if (plane_tmp.dist != -1) { lightingMultiplier = scene.light.intensity * intensity; pixelColour[0] += lightingMultiplier * plane_tmp.colour[0]; pixelColour[1] += lightingMultiplier * plane_tmp.colour[1]; pixelColour[2] += lightingMultiplier * plane_tmp.colour[2]; } } //obstruction between first intersection and light source else { if (sph_tmp.radius != -1) { lightingMultiplier = scene.light.intensity * 0.65f * intensity; pixelColour[0] += lightingMultiplier * sph_tmp.colour[0]; pixelColour[1] += lightingMultiplier * sph_tmp.colour[1]; pixelColour[2] += lightingMultiplier * sph_tmp.colour[2]; } else if (plane_tmp.dist != -1) { lightingMultiplier = scene.light.intensity * 0.65f * intensity; pixelColour[0] += lightingMultiplier * plane_tmp.colour[0]; pixelColour[1] += lightingMultiplier * plane_tmp.colour[1]; pixelColour[2] += lightingMultiplier * plane_tmp.colour[2]; } } temp_pixel_val = true; } while (reflectDepth < 3) { double[] t_in_new = { 0, 0, 0, 0, 0, 0, 0 }; if (sph_tmp.radius != -1) reflectedRay = FindReflectedRaySph(t_in, sph_tmp); else if (plane_tmp.dist != -1) reflectedRay = FindReflectedRayPlane(t_in, plane_tmp); foreach (Sphere sph in scene.spheres) { t_in_tmp = reflectionRecursiveSph(t_in, sph, reflectedRay); if (t_in_tmp[3] != 0 && (t_in_tmp[3] < t_in_new[3] || t_in_new[3] == 0)) { Array.Copy(t_in_tmp, t_in_new, 7); sph_tmp2 = (Sphere)sph.clone(); plane_tmp2.dist = -1; } } foreach (Plane plane in scene.planes) { t_in_tmp = reflectionRecursivePlane(t_in, plane, reflectedRay); if (t_in_tmp[3] != 0 && (t_in_tmp[3] < t_in_new[3] || t_in_new[3] == 0)) { Array.Copy(t_in_tmp, t_in_new, 7); plane_tmp2 = (Plane)plane.clone(); sph_tmp2.radius = -1; } } Array.Copy(t_in_new, t_in, 7); for (int i = 0; i < 7; i++) t_in_new[i] = 0; plane_tmp = (Plane)plane_tmp2.clone(); sph_tmp = (Sphere)sph_tmp2.clone(); plane_tmp2.dist = -1; sph_tmp2.radius = -1; if (!isNearZero(t_in[3])) { intensity = intensity * (float)Math.Pow(0.9995, t_in[3] + 1); foreach (Sphere sph in scene.spheres) { temp_pixel_val &= ShadowRaySph(t_in, sph); } foreach (Plane plane in scene.planes) { temp_pixel_val &= ShadowRayPlane(t_in, plane); } if (temp_pixel_val) { if (sph_tmp.radius != -1) { reflectionValue = reflectionValue * sph_tmp.attributes[0]; lightingMultiplier = scene.light.intensity * reflectionValue * intensity; pixelColour[0] += lightingMultiplier * sph_tmp.colour[0]; pixelColour[1] += lightingMultiplier * sph_tmp.colour[1]; pixelColour[2] += lightingMultiplier * sph_tmp.colour[2]; } else if (plane_tmp.dist != -1) { reflectionValue = reflectionValue * plane_tmp.attributes[0]; lightingMultiplier = scene.light.intensity * reflectionValue * intensity; pixelColour[0] += lightingMultiplier * plane_tmp.colour[0]; pixelColour[1] += lightingMultiplier * plane_tmp.colour[1]; pixelColour[2] += lightingMultiplier * plane_tmp.colour[2]; } } else { if (sph_tmp.radius != -1) { reflectionValue = reflectionValue * sph_tmp.attributes[0]; lightingMultiplier = scene.light.intensity * reflectionValue * 0.65f * intensity; pixelColour[0] += lightingMultiplier * sph_tmp.colour[0]; pixelColour[1] += lightingMultiplier * sph_tmp.colour[1]; pixelColour[2] += lightingMultiplier * sph_tmp.colour[2]; } else if (plane_tmp.dist != -1) { reflectionValue = reflectionValue * plane_tmp.attributes[0]; lightingMultiplier = scene.light.intensity * reflectionValue * 0.65f * intensity; pixelColour[0] += lightingMultiplier * plane_tmp.colour[0]; pixelColour[1] += lightingMultiplier * plane_tmp.colour[1]; pixelColour[2] += lightingMultiplier * plane_tmp.colour[2]; } } temp_pixel_val = true; reflectDepth++; } else reflectDepth = 99; } //inversion from crossing plane //pixelb[x_dir + 1000, -y_dir + 1000, 0] = Convert.ToByte(pixelColour[2]); //pixelb[x_dir + 1000, -y_dir + 1000, 1] = Convert.ToByte(pixelColour[1]); //pixelb[x_dir + 1000, -y_dir + 1000, 2] = Convert.ToByte(pixelColour[0]); pixelb[-y_dir + 1000, x_dir + 1000 , 0] = Convert.ToByte(pixelColour[2]); pixelb[-y_dir + 1000, x_dir + 1000, 1] = Convert.ToByte(pixelColour[1]); pixelb[-y_dir + 1000, x_dir + 1000, 2] = Convert.ToByte(pixelColour[0]); } } }
private bool ShadowRayPlane(double[] t_in, Plane pl_in) { double[] ray_dir = new double[3]; ray_dir[0] = -t_in[0] + scene.light.pos[0]; //temp ray_dir[1] = -t_in[1] + scene.light.pos[1]; //temp ray_dir[2] = -t_in[2] + scene.light.pos[2]; //temp float[] ret = { 0, 0, 0 }; double offsetStart = t_in[0] * pl_in.normal[0] + t_in[1] * pl_in.normal[1] + t_in[2] * pl_in.normal[2]; double t1 = (pl_in.dist - offsetStart) / (ray_dir[0] * pl_in.normal[0] + ray_dir[1] * pl_in.normal[1] + ray_dir[2] * pl_in.normal[2]); if (t1 > 0.00001 && t1 < 0.9999)// take into account NaN { return false; //ret[0] = scene.light.intensity * s_in.attributes[0]; //ret[1] = scene.light.intensity * s_in.attributes[0]; //ret[2] = scene.light.intensity * s_in.attributes[0]; } return true; }
private double[] FindReflectedRayPlane(double[] sur_in, Plane pl_in) { double[] ret = new double[3]; double[] normal = new double[3]; normal[0] = pl_in.normal[0]; normal[1] = pl_in.normal[1]; normal[2] = pl_in.normal[2]; //comment out for performance, input normal should already be unit size //double normal_unit_multiplier = 1 / Math.Sqrt(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); ////unit normal //normal[0] = normal_unit_multiplier * normal[0]; //normal[1] = normal_unit_multiplier * normal[1]; //normal[2] = normal_unit_multiplier * normal[2]; double n_dot_d = normal[0] * sur_in[4] + normal[1] * sur_in[5] + normal[2] * sur_in[6]; ret[0] = sur_in[4] - 2 * n_dot_d * normal[0]; ret[1] = sur_in[5] - 2 * n_dot_d * normal[1]; ret[2] = sur_in[6] - 2 * n_dot_d * normal[2]; double ret_unit_multiplier = 1 / Math.Sqrt(ret[0] * ret[0] + ret[1] * ret[1] + ret[2] * ret[2]); ret[0] = ret[0] * ret_unit_multiplier; ret[1] = ret[1] * ret_unit_multiplier; ret[2] = ret[2] * ret_unit_multiplier; return ret; }
private double[] reflectionRecursivePlane(double[] t_in, Plane pl_in, double[] ray_dir) { double[] ret = { 0, 0, 0, 0, ray_dir[0], ray_dir[1], ray_dir[2] }; double offsetStart = t_in[0] * pl_in.normal[0] + t_in[1] * pl_in.normal[1] + t_in[2] * pl_in.normal[2]; double t1 = (pl_in.dist - offsetStart - 0) / (ray_dir[0] * pl_in.normal[0] + ray_dir[1] * pl_in.normal[1] + ray_dir[2] * pl_in.normal[2]); if (isPositive(t1)) { ret[0] = t1 * ray_dir[0] + t_in[0]; ret[1] = t1 * ray_dir[1] + t_in[1]; ret[2] = t1 * ray_dir[2] + t_in[2]; ret[3] = t1; } return ret; }
private double[] planeIntersect(int x_count, int y_count, Plane p_in) { double[] ray_dir = new double[3]; ray_dir[0] = x_count; //temp ray_dir[1] = 1000; //temp ray_dir[2] = y_count; //temp double unit_mult = 1 / Math.Sqrt(ray_dir[0] * ray_dir[0] + ray_dir[1] * ray_dir[1] + ray_dir[2] * ray_dir[2]); ray_dir[0] = ray_dir[0] * unit_mult; ray_dir[1] = ray_dir[1] * unit_mult; ray_dir[2] = ray_dir[2] * unit_mult; //3 surface point, 1 t_length, 3 ray direction double[] ret = { 0, 0, 0, 0, ray_dir[0], ray_dir[1], ray_dir[2] }; double t1 = (p_in.dist - 0) / (ray_dir[0] * p_in.normal[0] + ray_dir[1] * p_in.normal[1] + ray_dir[2] * p_in.normal[2]); if (isPositive(t1)) { ret[0] = t1 * ray_dir[0]; ret[1] = t1 * ray_dir[1]; ret[2] = t1 * ray_dir[2]; ret[3] = t1; } return ret; }