public List <double> GetIntersection(Ray ray) { //Intersection Ray / Sphere //Sphere eq = dot((P - c)(P - c)) = RR (P = [x, y, z], c = [cx, cy, cz]) //Intersection then: dot((ray - c)(ray - c)) = RR -> dot((A + Bt -C)(A+Bt-C)) = RR //tt*dot(B,B) +2t *dot(B, A-C ) + dot(A-C, A-C) - RR = 0; var oc = ray.Origin - this.Center; var a = Vector3D.DotProduct(ray.Direction, ray.Direction); var b = 2 * Vector3D.DotProduct(oc, ray.Direction); var c = Vector3D.DotProduct(oc, oc) - this.Radius * this.Radius; var discriminant = b * b - 4 * a * c; // No solution! if (discriminant < 0) { return(null); } List <double> result = new List <double>(); var temp = Math.Sqrt(discriminant); var temp2 = 2 * a; var negativeSolution = (-b - temp) / temp2; var positiveSolution = (-b + temp) / temp2; if (negativeSolution > MinOffset && negativeSolution < MaxOffset) { result.Add(negativeSolution); } if (positiveSolution > MinOffset && positiveSolution < MaxOffset) { result.Add(positiveSolution); } return(result); }
/// <summary> /// Calculate the intesection point between the ray and the plane of the rectangle. /// </summary> /// <param name="ray">The ray to check</param> /// <param name="intersectionPoint">The result intersection point</param> /// <returns>True if the intersection is in the rectangle</returns> override public bool Intersects(Ray ray, ref Vector3D intersectionPoint) { var normalDotProduct = Vector3D.DotProduct(Normal, ray.Direction); // Do the intersection test as for a Plane. if (normalDotProduct != 0) { //Give the right orientation to the normal vector if (normalDotProduct > 0) { normal = -Normal; normalDotProduct = -normalDotProduct; } Vector3D Point = (Vector3D)Point1; double t = (Vector3D.DotProduct(Normal, (Vector3D.Subtract(Point, ray.Source)))) / normalDotProduct; if (t >= 0) { intersectionPoint = ray.Source + (ray.Direction * t); var vec1 = (Point3D)intersectionPoint - Point1; var vec2 = Point2 - Point1; var vec3 = Point4 - Point1; var alpha = Vector3D.DotProduct(vec1, vec2) / vec2.LengthSquared; var beta = Vector3D.DotProduct(vec1, vec3) / vec3.LengthSquared; if (alpha >= 0 && alpha <= 1 && beta >= 0 && beta <= 1) { return(true); } } } return(false); }
public override bool Intersects(Ray ray, ref Vector3D intersectionPoint) { double distance = double.NaN; Vector3D originOffset = ray.Source - Center; // a = 1 since ray.D.Dot() = 1 double b = 2.0 * (Vector3D.DotProduct(ray.Direction, originOffset)); double c = Vector3D.DotProduct(originOffset, originOffset) - (Radius * Radius); double discriminant = b * b - 4.0 * c; if (discriminant < 0) { return(false); } // compute q as described above double distSqrt = Math.Sqrt(discriminant); double q; if (b > 0) { q = (-b - distSqrt) / 2.0; } else { q = (-b + distSqrt) / 2.0; } // compute t0 and t1 double t0 = q; double t1 = c / q; // make sure t0 is smaller than t1 if (t0 > t1) { // if t0 is bigger than t1 swap them around double temp = t0; t0 = t1; t1 = temp; } // if t1 is less than zero, the object is in the ray's negative direction // and consequently the ray misses the sphere if (t1 < 0) { return(false); } // if t0 is less than zero, the intersection point is at t1 if (t0 < 0) { distance = t1; } else { // else the intersection point is at t0 distance = t0; } intersectionPoint = ray.Source + ray.Direction * distance; return(true); }
private void GetColor(HitInfo info, Light light, ColorAccumulator colorAccu, int count) { Vector3D lightLocation = light.Location; Vector3D lightNormal = info.hitPoint - lightLocation; lightNormal.Normalize(); double lambert = Vector3D.DotProduct(lightNormal, info.normal); if (lambert <= 0) { int r, g, b; r = g = b = 0; int r2 = 0; int g2 = 0; int b2 = 0; info.hitObject.GetColor(info.hitPoint, ref r, ref g, ref b); if (info.hitObject.Material != null) { var objectMaterial = info.hitObject.Material; //Phong if (objectMaterial is SolidColor) { if (InShadow(info, lightLocation, lightNormal)) { return; } double phongTerm = Math.Pow(lambert, 20) * (objectMaterial as SolidColor).Phong * 2 * light.Intensity; r2 = (int)(light.Color.R * phongTerm); g2 = (int)(light.Color.G * phongTerm); b2 = (int)(light.Color.B * phongTerm); var intensityFactor = light.Intensity * -lambert / 255; colorAccu.R += (int)(light.Color.R * r * intensityFactor) + r2; colorAccu.G += (int)(light.Color.G * g * intensityFactor) + g2; colorAccu.B += (int)(light.Color.B * b * intensityFactor) + b2; } //Reflection else if (objectMaterial is Metal) { var metal = objectMaterial as Metal; //double phongTerm = Math.Pow(lambert, 20) * 0.6 * 2 * light.Intensity; //r2 = (int)(light.Color.R * phongTerm); //g2 = (int)(light.Color.G * phongTerm); //b2 = (int)(light.Color.B * phongTerm); double reflet = 2.0f * (Vector3D.DotProduct(info.normal, info.ray.Direction)); Vector3D direction = info.ray.Direction - info.normal * reflet; direction.Normalize(); direction += metal.Fuzz * StaticRandom.RandomVectorInUnitSphere(); //Random in cone //direction.Normalize(); Ray reflect = new Ray(info.hitPoint + direction / 100000, direction); ColorAccumulator reflectedColorAccu = CastRay(reflect, ++count); if (reflectedColorAccu != null) { var attenuation = metal.Reflection * light.Intensity; colorAccu.R += (int)(reflectedColorAccu.R * attenuation) + r2; colorAccu.G += (int)(reflectedColorAccu.G * attenuation) + g2; colorAccu.B += (int)(reflectedColorAccu.B * attenuation) + b2; } } } } }