public override bool RayIntersection(Ray r, out float t, out Point3D normal) { t = 0; normal = null; Point3D k = r.start - position; float b = Point3D.scalar(k, r.dir); float c = Point3D.scalar(k, k) - rad * rad; float d = b * b - c; if (d >= 0) { float sqrtfd = (float)Math.Sqrt(d); float t1 = -b + sqrtfd; float t2 = -b - sqrtfd; float min_t = Math.Min(t1, t2); float max_t = Math.Max(t1, t2); t = (min_t > Ray.EPSILON) ? min_t : max_t; if (t > Ray.EPSILON) { normal = Point3D.norm(r.tpos(t) - position); return(true); } } return(false); }
Point3D RayTrace(Ray r, int rec, float env = 1, float impact = 1) { bool BackToAir = false; Point3D clr = new Point3D(0, 0, 0); if (rec <= 0 || impact < EPS) { return(clr); } Hit h = GenerateHit(r); if (!h.succes) { return(clr); } if (Point3D.scalar(r.dir, h.normal) > 0) { h.normal = h.normal * -1; BackToAir = true; } Point3D hit_pos = r.tpos(h.hit_point); foreach (var l in lights) { clr += Point3D.blend(h.mat.clr, l.amb * h.mat.amb_coef); if (IsVisibleLight(l.points[0], hit_pos)) { clr += h.Shade(l, hit_pos, f); } } if (h.mat.reflection_coef > 0) { Ray reflRay = h.Reflect(hit_pos); clr += h.mat.reflection_coef * RayTrace(reflRay, rec - 1, env, impact * h.mat.reflection_coef); } if (h.mat.refraction_coef > 0) { Ray refrRay = h.Refract(hit_pos, BackToAir ? env / 1 : env / h.mat.env_coef); if (refrRay != null) { clr += h.mat.refraction_coef * RayTrace(refrRay, rec - 1, impact * h.mat.reflection_coef); } } return(clr); }