public void TupleDotProductTest() { var t1 = new Tuple4(-1, 7, 3, TupleFlavour.Vector); var t2 = new Tuple4(4, 5, 6, TupleFlavour.Vector); Assert.Equal(49.0, Tuple4.DotProduct(t1, t2)); }
protected override Intersection[] GetBaseIntersections(Ray ray) { var dir_cross_e2 = Tuple4.CrossProduct(ray.dir, E2); var det = Tuple4.DotProduct(E1, dir_cross_e2); if (Constants.EpsilonZero(Math.Abs(det))) { return(null); } var f = 1.0 / det; var p1_to_origin = Tuple4.Subtract(ray.origin, P1); var u = f * Tuple4.DotProduct(p1_to_origin, dir_cross_e2); if ((u < 0.0) || (u > 1.0)) { return(null); } var origin_cross_e1 = Tuple4.CrossProduct(p1_to_origin, E1); var v = f * Tuple4.DotProduct(ray.dir, origin_cross_e1); if ((v < 0.0) || ((u + v) > 1.0)) { return(null); } var t = f * Tuple4.DotProduct(E2, origin_cross_e1); return(new Intersection[] { new Intersection(t, this) }); }
public static double Schlick(HitResult hit, double refractiveIndexEntering, double refractiveIndexExiting) { // find the cosine of the angle between the eye and normal vectors double cosI = Tuple4.DotProduct(hit.EyeVector, hit.SurfaceNormal); // total internal reflection can only occur if n1 > n2 if (refractiveIndexEntering > refractiveIndexExiting) { double ration = refractiveIndexEntering / refractiveIndexExiting; double sinTheta2 = ration * ration * (1.0 - cosI * cosI); if (sinTheta2 > 1.0) { return(1.0); } // compute cosine of theta_t using trig identity var cosTheta = Math.Sqrt(1.0 - sinTheta2); // when n1 > n2, use cos(theta_t) instead cosI = cosTheta; } var r0 = Math.Pow((refractiveIndexEntering - refractiveIndexExiting) / (refractiveIndexEntering + refractiveIndexExiting), 2); return(r0 + (1 - r0) * Math.Pow((1 - cosI), 5)); }
private static Lighting GetIntensity(IMaterial material, Tuple4 lightDirection, double intensity, Tuple4 eyeVector, Tuple4 pointOnSurface, Tuple4 surfaceNormal) { var diffuse = 0.0; var specular = 0.0; var cosine = Tuple4.DotProduct(lightDirection, surfaceNormal); if (cosine >= 0) { diffuse = cosine * material.Diffuse; if (material.IsShining()) { // var reflected = Tuple4.Subtract(Tuple4.Scale(surfaceNormal, 2 * Tuple4.DotProduct(surfaceNormal, lightDirection)), lightDirection); var reflected = Tuple4.Reflect(Tuple4.Negate(lightDirection), surfaceNormal); var reflectedDotDir = Tuple4.DotProduct(reflected, eyeVector); if (reflectedDotDir > 0) { specular = material.Specular * Math.Pow(reflectedDotDir / (reflected.Length() * eyeVector.Length()), material.Shininess); } } } return(diffuse, specular, intensity); }
public virtual HitResult[] AllHits(Tuple4 origin, Tuple4 dir) { var intersections = GetIntersections(new Ray(origin, dir)); if (intersections == null) { return(new HitResult[] { HitResult.NoHit }); } var result = new HitResult[intersections.Length]; for (int i = 0; i < intersections.Length; ++i) { var figure = intersections[i].figure; var distance = intersections[i].t; var pointOnSurface = Tuple4.Geometry3D.MovePoint(origin, dir, distance); // orig + dir*dist // TODO: Remove this cast to BaseFigure (var surfaceNormal, var objectPoint) = ((BaseFigure)figure).GetTransformedNormal(figure, pointOnSurface, intersections[i].u, intersections[i].v); var eyeVector = Tuple4.Negate(dir); var isInside = false; if (Tuple4.DotProduct(surfaceNormal, eyeVector) < 0) { isInside = true; surfaceNormal = Tuple4.Negate(surfaceNormal); } var pointOverSurface = Tuple4.Add(pointOnSurface, Tuple4.Scale(surfaceNormal, Constants.Epsilon)); var pointUnderSurface = Tuple4.Subtract(pointOnSurface, Tuple4.Scale(surfaceNormal, Constants.Epsilon)); var reflectionVector = Tuple4.Reflect(dir, surfaceNormal); result[i] = new HitResult(true, figure, distance, intersections[i].u, intersections[i].v, objectPoint, pointOnSurface, pointOverSurface, pointUnderSurface, surfaceNormal, eyeVector, reflectionVector, isInside); } return(result); }
private Tuple4 CalculateRefractedColorAt(HitResult hit, double refractiveIndexEntering, double refractiveIndexExiting, int remaining) { if (!hit.IsHit || remaining <= 0) { return(colors.Black); } var material = hit.Figure.Material; if (Constants.EpsilonZero(material.Transparency)) { return(colors.Black); } // Calculations are based on Snell's law var ration = refractiveIndexEntering / refractiveIndexExiting; var cosI = Tuple4.DotProduct(hit.EyeVector, hit.SurfaceNormal); // sin(t) * sin(t) = (ration * ration) * (1 - cos(I) * cos(I)) var sinTheta2 = ration * ration * (1 - cosI * cosI); if (sinTheta2 > 1.0) { // Total internal reflection return(colors.Black); } var cosTheta = Math.Sqrt(1 - sinTheta2); var dir = Tuple4.Subtract(Tuple4.Scale(hit.SurfaceNormal, ration * cosI - cosTheta), Tuple4.Scale(hit.EyeVector, ration)); var refractedRay = new Ray(hit.PointUnderSurface, dir); var refractedColor = CastRay(refractedRay, remaining - 1); return(Tuple4.Scale(refractedColor, material.Transparency)); }
public void Then_dot(string a, string b, double expected) { Assert.True(Constants.EpsilonCompare(expected, Tuple4.DotProduct(cache[a], cache[b]))); }