public Sphere(vect3d pos, double r, Shader shader) { this.shader = shader; this.radius = r; this.radius2 = r * r; this.pos = pos; }
public static matrix4d rotaxis(ref vect3d axis, double rad) { double c = System.Math.Cos(rad); double s = System.Math.Sin(rad); double t = 1 - c; double x = axis.x; double y = axis.y; double z = axis.z; matrix4d ret = new matrix4d(); ret.m[0] = t * x * x + c; ret.m[1] = t * x * y - s * z; ret.m[2] = t * x * z + s * y; ret.m[4] = t * x * y + s * z; ret.m[5] = t * y * y + c; ret.m[6] = t * y * z - s * x; ret.m[8] = t * x * z - s * y; ret.m[9] = t * y * z + s * x; ret.m[10] = t * z * z + c; return(ret); }
public static matrix4d rotaxis(ref vect3d axis, double rad) { double c = System.Math.Cos(rad); double s = System.Math.Sin(rad); double t = 1 - c; double x = axis.x; double y = axis.y; double z = axis.z; matrix4d ret = new matrix4d(); ret.m[0] = t * x * x + c; ret.m[1] = t * x * y - s * z; ret.m[2] = t * x * z + s * y; ret.m[4] = t * x * y + s * z; ret.m[5] = t * y * y + c; ret.m[6] = t * y * z - s * x; ret.m[8] = t * x * z - s * y; ret.m[9] = t * y * z + s * x; ret.m[10] = t * z * z + c; return ret; }
public override vect3d sample(vect3d pos) { // find modulo value (texture wrapping) vect2d p = new vect2d((pos.x % 1) * bmp.Width, ((1 - pos.y) % 1) * bmp.Height); if (p.x < 0) p.x += bmp.Width; if (p.y < 0) p.y += bmp.Height; // get color out of bmp int i = (int)p.x, j = (int)p.y; int ip = (i + 1) % bmp.Width, jp = (j + 1) % bmp.Height; double dx = p.x - i, dy = p.y - j; Color color; color = bmp.GetPixel(i, j); vect3d c00 = new vect3d(color.R, color.G, color.B); color = bmp.GetPixel(i, jp); vect3d c01 = new vect3d(color.R, color.G, color.B); color = bmp.GetPixel(ip, j); vect3d c10 = new vect3d(color.R, color.G, color.B); color = bmp.GetPixel(ip, jp); vect3d c11 = new vect3d(color.R, color.G, color.B); // combine samples with lerp return ((1 - dx) * (1 - dy) * c00 + (1 - dx) * dy * c01 + dx * (1 - dy) * c10 + dx * dy * c11) * (1.0/ 255.0); }
public void normalize() { double mag = 1.0 / System.Math.Sqrt(magnitudeSq()); s *= mag; v *= mag; }
public static bool rayBoxIntersectDist(vect3d ray_pos, vect3d ray_dir, box3d box, out double dist, out int face_d, out int face_n) { vect3d box_low = box[0]; vect3d box_high = box[1]; dist = 0; double Tnear = -1e30; double Tfar = 1e30; double T1, T2; face_d = -1; face_n = -1; // check bounding box to see if it enters level // this method assumes bounding box is already in coordinate system of the level for (int d = 0; d < 3; d++) { int n_temp = 0; if (ray_dir[d] == 0) { if (ray_pos[d] > box_high[d] || ray_pos[d] < box_low[d]) return false; //int dp = (d + 1) % 3; //int dpp = (d + 2) % 3; //if (ray_pos[dp] > box_high[dp] || ray_pos[dp] < box_low[dp]) // return false; //if (ray_pos[dpp] > box_high[dpp] || ray_pos[dpp] < box_low[dpp]) // return false; } else { T1 = (box_low[d] - ray_pos[d]) / ray_dir[d]; T2 = (box_high[d] - ray_pos[d]) / ray_dir[d]; if (T1 > T2) { //swap(T1, T2); // since T1 intersection should be the nearest double t = T1; T1 = T2; T2 = t; n_temp = (n_temp + 1) % 2; } if (T1 > Tnear) { face_d = d; face_n = n_temp; Tnear = T1; // largest Tnear } if (T2 < Tfar) Tfar = T2; // smallest Tfar if (Tnear > Tfar) // box is missed return false; if (Tfar < 0) return false; // box is behind ray } } dist = Tnear; if (dist < 0) return false; return true; }
public vect3d times(vect3d a) { vect3d r; r.x = x * a.x; r.y = y * a.y; r.z = z * a.z; return(r); }
public override void colorize(Ray r) { vect3d diff_accum = new vect3d(0, 0, 0); vect3d spec_accum = new vect3d(0, 0, 0); lightDirectPointSpecNoShadow(r, specular_coeff, ref diff_accum, ref spec_accum); r.color = diff_accum.times(diffuse_color) + spec_accum.times(specular_color); }
public static matrix4d scale(ref vect3d s) { matrix4d ret = new matrix4d(); ret.m[0] = s.x; ret.m[5] = s.y; ret.m[10] = s.z; return ret; }
public static matrix4d scale(ref vect3d s) { matrix4d ret = new matrix4d(); ret.m[0] = s.x; ret.m[5] = s.y; ret.m[10] = s.z; return(ret); }
public vect3d transformPoint(ref vect3d p) { vect3d vecTemp = p; double mag = -(vecTemp * v); vecTemp = ((vecTemp * s) + ((v % vecTemp))); quaternion temp = new quaternion(mag, vecTemp); return((temp * conjugate()).v); }
public vect3d mult_vec(ref vect3d src) { vect3d ret = new vect3d(); ret.x = m[0] * src.x + m[1] * src.y + m[2] * src.z; ret.y = m[4] * src.x + m[5] * src.y + m[6] * src.z; ret.z = m[8] * src.x + m[9] * src.y + m[10] * src.z; return(ret); }
matrix4d translate(ref vect3d t) { matrix4d ret = new matrix4d(); ret.m[3] = t.x; ret.m[7] = t.y; ret.m[11] = t.z; return(ret); }
public static bool rayBoxIntersectPos(vect3d ray_pos, vect3d ray_dir, box3d box, out double dist, out vect3d pos, out int d, out int n) { if (rayBoxIntersectDist(ray_pos, ray_dir, box, out dist, out d, out n)) { pos = ray_pos + ray_dir * dist; return true; } pos = new vect3d(0); return false; }
public box3d(vect3d mine, vect3d maxe) { xl = mine.x; yl = mine.y; zl = mine.z; xh = maxe.x; yh = maxe.y; zh = maxe.z; }
public box3d(vect3d mine, vect3d maxe) { xl = mine.x; yl = mine.y; zl = mine.z; xh = maxe.x; yh = maxe.y; zh = maxe.z; }
public vect3d transformPoint(ref vect3d p) { vect3d vecTemp = p; double mag = -(vecTemp * v); vecTemp = ((vecTemp * s) + ((v % vecTemp))); quaternion temp = new quaternion(mag, vecTemp); return (temp * conjugate()).v; }
public static vect3d rand_in_sphere() { vect3d p; do { p = new vect3d(rand.NextDouble() * 2 - 1, rand.NextDouble() * 2 - 1, rand.NextDouble() * 2 - 1); } while (p.length2() > 1); return p; }
public override void colorize(Ray r) { vect3d diff_accum = new vect3d(0, 0, 0); vect3d spec_accum = new vect3d(0, 0, 0); lightDirectPointSpec(r, specular_coeff, ref diff_accum, ref spec_accum); vect3d diffuse_color = tex.sample(r.hit_tex_coord); r.color = diff_accum.times(diffuse_color) + spec_accum.times(specular_color); }
public vect3d mult_pos(ref vect3d src) { vect3d ret = new vect3d(); double div = 1.0 / (m[12] * src.x + m[13] * src.y + m[14] * src.z + m[15]); ret.x = (m[0] * src.x + m[1] * src.y + m[2] * src.z + m[3]) * div; ret.y = (m[4] * src.x + m[5] * src.y + m[6] * src.z + m[7]) * div; ret.z = (m[8] * src.x + m[9] * src.y + m[10] * src.z + m[11]) * div; return(ret); }
public Plane(vect3d p0, vect3d p1, vect3d p2, Shader shader) { this.shader = shader; this.pos = p0; z = (p1 - p0) % (p2 - p0); z.normalize(); x = p2 % z; x.normalize(); y = z % x; }
public override vect3d sample(vect3d pos) { // find modulo value (texture wrapping) vect2d p = new vect2d((pos.x % 1) * bmp.Width, ((1 - pos.y) % 1) * bmp.Height); if (p.x < 0) p.x += bmp.Width; if (p.y < 0) p.y += bmp.Height; // get color out of bmp Color color = bmp.GetPixel((int)p.x, (int)p.y); return new vect3d(color.R / 255.0, color.G / 255.0, color.B / 255.0); }
vect3d norm; // unit normal for getting plane intersection public Triangle(vect3d p0, vect3d p1, vect3d p2, Shader shader) { this.shader = shader; this.p0 = p0; this.p1 = p1; this.p2 = p2; N = (p1 - p0) % (p2 - p0); N /= N * N; norm = N; norm.normalize(); n0 = n1 = n2 = norm; }
public override void colorize(Ray r) { vect3d diff_accum = new vect3d(0, 0, 0); vect3d spec_accum = new vect3d(0, 0, 0); lightDirectPointSpec(r, specular_coeff, ref diff_accum, ref spec_accum); // calculate the polar coordinates vect3d sp; sp.x = -Math.Atan2(r.hit_tex_coord.z, r.hit_tex_coord.x) / (2 * Math.PI); sp.y = -Math.Atan2(Math.Sqrt(r.hit_tex_coord.x * r.hit_tex_coord.x + r.hit_tex_coord.z * r.hit_tex_coord.z), r.hit_tex_coord.y) / (Math.PI); sp.z = 0; vect3d diffuse_color = tex.sample(sp); r.color = diff_accum.times(diffuse_color) + spec_accum.times(specular_color); }
public vect3d vertPos(int i) { vect3d p = this[0]; if ((i & 1) != 0) { p[0] = this[1, 0]; } if ((i & 2) != 0) { p[1] = this[1, 1]; } if ((i & 4) != 0) { p[2] = this[1, 2]; } return(p); }
protected void lightDirectPointSpecNoShadow(Ray r, double specular_coeff, ref vect3d diff_accum, ref vect3d spec_accum) { Ray shadow_ray = new Ray(); shadow_ray.pos = r.hit_pos; foreach (var l in r.scene.lights) { vect3d dir = l.pos - r.hit_pos; double dist2 = 1.0 / dir.length2(); dir *= Math.Sqrt(dist2); // diffuse double incidence_dif = (dir * r.hit_norm); if (incidence_dif > 0) diff_accum += l.color * incidence_dif * dist2; // specular highlight vect3d dir_r = r.hit_norm * ((dir * r.hit_norm) * 2) - dir; double incidence_spec = (dir_r * r.hit_norm); if (incidence_spec > 0) spec_accum += l.color * Math.Pow(incidence_spec, specular_coeff) * dist2; } }
protected void lightDirectPointSpec(Ray r, double specular_coeff, ref vect3d diff_accum, ref vect3d spec_accum) { Ray shadow_ray = new Ray(); shadow_ray.pos = r.hit_pos; foreach (var l in r.scene.lights) { vect3d dir = l.pos - r.hit_pos; double dist2 = dir.length2(); double dist2_inv = 1.0 / dist2; dir *= Math.Sqrt(dist2_inv); // calculate incidences to do early reject of shadow ray double incidence_dif = (dir * r.hit_norm); vect3d dir_r = r.hit_norm * ((dir * r.hit_norm) * 2) - dir; double incidence_spec = (dir_r * r.hit_norm); if (incidence_dif < 0 && incidence_spec < 0) continue; // shadow ray test shadow_ray.dir = dir; shadow_ray.hit_dist = Double.MaxValue; r.scene.trace(shadow_ray); if (shadow_ray.hit_dist * shadow_ray.hit_dist < dist2) continue; // diffuse if (incidence_dif > 0) diff_accum += l.color * incidence_dif * dist2_inv; // specular highlight if (incidence_spec > 0) spec_accum += l.color * Math.Pow(incidence_spec, specular_coeff) * dist2_inv; } }
public static bool rayTriangleIntersect(vect3d ray_pos, vect3d ray_dir, vect3d v0, vect3d v1, vect3d v2, out double dist) { vect3d u = v1 - v0; vect3d v = v2 - v0; vect3d n = u % v; // normal dist = -((ray_pos - v0) * n) / (ray_dir * n); // distance to plane vect3d pos = ray_pos + ray_dir * dist; // point in plane of triangle vect3d w = pos - v0; double uv = u * v; double wv = w * v; double vv = v * v; double wu = w * u; double uu = u * u; double denom = uv * uv - uu * vv; double s = (uv * wv - vv * wu) / denom; double t = (uv * wu - uu * wv) / denom; if (s >= 0 && t >= 0 && s + t <= 1) return true; else return false; }
public quaternion(double s, double x, double y, double z) { this.s = s; v = new vect3d(x, y, z); }
public bool Equals(vect3d b) { return(x == b.x && y == b.y && z == b.z); }
public bool Equals(vect3d b) { return x == b.x && y == b.y && z == b.z; }
public vect3d(vect3d v) { x = v.x; y = v.y; z = v.z; }
public vect3d mult_pos(ref vect3d src) { vect3d ret = new vect3d(); double div = 1.0 / (m[12] * src.x + m[13] * src.y + m[14] * src.z + m[15]); ret.x = (m[0] * src.x + m[1] * src.y + m[2] * src.z + m[3]) * div; ret.y = (m[4] * src.x + m[5] * src.y + m[6] * src.z + m[7]) * div; ret.z = (m[8] * src.x + m[9] * src.y + m[10] * src.z + m[11]) * div; return ret; }
matrix4d translate(ref vect3d t) { matrix4d ret = new matrix4d(); ret.m[3] = t.x; ret.m[7] = t.y; ret.m[11] = t.z; return ret; }
public vect2d(vect3d v) { x = v.x; y = v.y; }
public void normalize() { double mag = 1.0 / System.Math.Sqrt(magnitudeSq()); s *= mag; v *= mag; }
public virtual vect3d sample(vect3d p) { return new vect3d(1, 1, 1); }
/// <summary> /// Makes a quaterion representing a rotation of an angle about a vector. Note that this must be a unit vector! /// </summary> /// <returns></returns> public static quaternion makeRotation(double angle, vect3d axis) { return makeRotation(angle, axis.x, axis.y, axis.z); }
public quaternion(double s, vect3d v) { this.s = s; this.v = v; }
public quaternion(double s, double x, double y, double z) { this.s = s; v = new vect3d(x, y, z); }
public quaternion(double s, vect3d v) { this.s = s; this.v = v; }
public Bitmap create_image(Scene scene) { Bitmap bmp = new Bitmap(width, height); // get the orientation of the camera matrix4d rotmat = orient.getMatrix(); vect3d rt = new vect3d(rotmat.m[0], rotmat.m[1], rotmat.m[2]); vect3d up = new vect3d(rotmat.m[4], rotmat.m[5], rotmat.m[6]); vect3d fwd = new vect3d(rotmat.m[8], rotmat.m[9], rotmat.m[10]); // convert the orientation to a 3D screen double aspect = (double)width / (double)height; double h = Math.Tan(fov_y * Math.PI / 360.0); up *= -h * 2; rt *= aspect * h * 2; fwd *= -1; // 2D screen conversions vect3d dx = rt / width; vect3d dy = up / height; vect3d corner = fwd - rt * .5 - up * .5; // expose each pixel Ray r = new Ray(); r.scene = scene; double subsample_res = 1.0 / subsamples; for (int j = 0; j < bmp.Height; j++) { for (int i = 0; i < bmp.Width; i++) { vect3d color = new vect3d(0, 0, 0); for (int jj = 0; jj < subsamples; jj++) { for (int ii = 0; ii < subsamples; ii++) { // set ray properties r.pos = this.pos; r.hit_dist = Double.MaxValue; r.color = new vect3d(0, 0, 0); r.hit_object = null; r.dir = corner + dx * (i + (ii+.5/*Rand.rand.NextDouble()*/) * subsample_res) + dy * (j + (jj+.5/*Rand.rand.NextDouble()*/) * subsample_res); r.dir.normalize(); // trace the ray scene.trace(r); if (r.hit_object != null) { r.hit_object.shader.colorize(r); color += r.color; } } } color *= subsample_res * subsample_res; // gamma correct the color double brightness = color.length(); color /= Math.Sqrt(brightness); // store the color int red = clamp(color.x); int green = clamp(color.y); int blue = clamp(color.z); bmp.SetPixel(i, j, Color.FromArgb(255, red, green, blue)); } } return bmp; }
/// <summary> /// Makes a quaterion representing a rotation of an angle about a vector. Note that this must be a unit vector! /// </summary> /// <returns></returns> public static quaternion makeRotation(double angle, vect3d axis) { return(makeRotation(angle, axis.x, axis.y, axis.z)); }
public static bool intersect_aabb_tri(vect3d mine, vect3d maxe, vect3d v0, vect3d v1, vect3d v2) { //** use separating axes to determine intersection // create points vect3d[] tri = { v0, v1, v2 }; vect3d[] box_ext = { mine, maxe }; vect3d[] box = new vect3d[8]; for (int i = 0; i < 8; i++) box[i] = new vect3d((box_ext[i & 1])[0], (box_ext[(i >> 1) & 1])[1], (box_ext[i >> 2])[2]); // create axes vect3d[] axes = new vect3d[13]; axes[0] = new vect3d(1, 0, 0); axes[1] = new vect3d(0, 1, 0); axes[2] = new vect3d(0, 0, 1); axes[3] = (v1 - v0) % (v2 - v0); for (int i = 0; i < 3; i++) { int ip = (i + 1) % 3; for (int j = 0; j < 3; j++) { axes[4 + i * 3 + j] = axes[j] % ((tri[i]) - (tri[ip])); } } // check overlaps for (int i = 0; i < 13; i++) { // tri extents double tri_min, tri_max; tri_min = tri_max = (tri[0]) * axes[i]; for (int k = 1; k < 3; k++) { double d = (tri[k]) * axes[i]; if (d < tri_min) tri_min = d; if (d > tri_max) tri_max = d; } // box extents double box_min, box_max; box_min = box_max = box[0] * axes[i]; for (int j = 1; j < 8; j++) { double d = box[j] * axes[i]; if (d < box_min) box_min = d; if (d > box_max) box_max = d; } // if disjoint, they don't intersect if (box_max < tri_min || tri_max < box_min) return false; } return true; }
public vect3d mult_vec(ref vect3d src) { vect3d ret = new vect3d(); ret.x = m[0] * src.x + m[1] * src.y + m[2] * src.z; ret.y = m[4] * src.x + m[5] * src.y + m[6] * src.z; ret.z = m[8] * src.x + m[9] * src.y + m[10] * src.z; return ret; }
public static double dist2_aabb_pt(vect3d mine, vect3d maxe, vect3d pt) { double d2 = 0; for (int i = 0; i < 3; i++) { double d = pt[i] - mine[i]; if (d < 0) { d2 += d * d; continue; } d = pt[i] - maxe[i]; if (d > 0) d2 += d * d; } return d2; }