public void SimpleCameraTest() { // Ray cast for screen coordinate 0,0 { var camera = new SimpleCamera(new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), 6.0, 600, 800); var ray = camera.GetRay(0, 0); var expectedRay = new Ray( new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), Tuple4.Normalize(new Tuple4(-3.0, 3.0, 1.0, TupleFlavour.Vector))); Assert.Equal(expectedRay.origin, ray.origin); Assert.Equal(expectedRay.dir, ray.dir); var t = Tuple4.Add(ray.origin, Tuple4.Scale(ray.dir, 4.35890)); Assert.Equal(new Tuple4(-3.0, 3.0, -3.0, TupleFlavour.Point), t); } // Ray cast for screen coordinate width,height { var camera = new SimpleCamera(new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), 6.0, 600, 800); var ray = camera.GetRay(600, 800); var expectedRay = new Ray( new Tuple4(0.0, 0.0, -4.0, TupleFlavour.Point), Tuple4.Normalize(new Tuple4(3.0, -3.0, 1.0, TupleFlavour.Vector))); Assert.Equal(expectedRay.origin, ray.origin); Assert.Equal(expectedRay.dir, ray.dir); } { var camera = new SimpleCamera(new Tuple4(0, 0, -1.0, TupleFlavour.Point), 2.0, 600, 600); var ray = camera.GetRay(0, 0); var t = Tuple4.Add(ray.origin, Tuple4.Scale(ray.dir, 1.73205)); Assert.Equal(new Tuple4(-1.0, 1.0, 0.0, TupleFlavour.Point), t); } }
public void TupleScaleByTest() { var t1 = new Tuple4(1, 7, 3, TupleFlavour.Vector); var expected = new Tuple4(0.5, 3.5, 1.5, TupleFlavour.Vector); Assert.Equal(expected, Tuple4.Scale(t1, 0.5)); }
public void Then_scale_scalar3(string a, double s, double t1, double t2, double t3) { var c = Tuple4.Scale(cache[a], s); Assert.True(Constants.EpsilonCompare(t1, c.X)); Assert.True(Constants.EpsilonCompare(t2, c.Y)); Assert.True(Constants.EpsilonCompare(t3, c.Z)); }
public void TupleScaleTest() { var t1 = new Tuple4(1, 7, 3, TupleFlavour.Vector); var t2 = new Tuple4(4, 5, 6, TupleFlavour.Vector); var expected = new Tuple4(4, 35, 18, TupleFlavour.Vector); Assert.Equal(expected, Tuple4.Scale(t1, t2)); }
public void Then_scale_vector(string a, string b, double t1, double t2, double t3) { var c = Tuple4.Scale(cache[a], cache[b]); Assert.True(Constants.EpsilonCompare(t1, c.X)); Assert.True(Constants.EpsilonCompare(t2, c.Y)); Assert.True(Constants.EpsilonCompare(t3, c.Z)); Assert.True(c.IsVector()); }
public static Tuple4 GetShadedColor(Tuple4 objectPoint, IMaterial material, Tuple4 white, Tuple4 lightDirection, double intensity, Tuple4 eyeVector, Tuple4 pointOnSurface, Tuple4 surfaceNormal) { Tuple4 color = material.GetColor(objectPoint); Lighting lighting = GetIntensity(material, lightDirection, intensity, eyeVector, pointOnSurface, surfaceNormal); var shadedColor = Tuple4.Add( Tuple4.Scale(color, lighting.intensity * lighting.diffuse), Tuple4.Scale(white, lighting.specular) ); return(shadedColor); }
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); }
public bool IsShadowed(ILight light, Tuple4 pointOverSurface) { var lightDir = light.GetLightDirection(pointOverSurface); if (!lightDir.Equals(Tuple4.ZeroVector)) { var lh = CalculateIntersection(Tuple4.Add(pointOverSurface, Tuple4.Scale(lightDir, Constants.Epsilon)), lightDir); if (lh.IsHit) { var distance = light.GetLightDistance(pointOverSurface); if (lh.Distance < distance) { return(true); } } } return(false); }
private Tuple4 CalculateReflectedColorAt(HitResult hit, int remaining) { if (!hit.IsHit || remaining <= 0) { return(colors.Black); } var material = hit.Figure.Material; if (Constants.EpsilonZero(material.Reflective)) { return(Tuple4.ZeroVector); } var reflectedRay = new Ray(hit.PointOverSurface, hit.ReflectionVector); var reflectedColor = CastRay(reflectedRay, remaining - 1); return(Tuple4.Scale(reflectedColor, material.Reflective)); }
private Tuple4 CalculateColorAt(HitResult hit, double refractiveIndexEntering, double refractiveIndexExiting, int remaining) { if (!hit.IsHit) { return(colors.Black); } var material = hit.Figure.Material; var surface = Tuple4.ZeroVector; foreach (var light in lights) { // Shadow if (castShadows && IsShadowed(light, hit.PointOverSurface)) { continue; } surface = Tuple4.Add(surface, light.GetShadedColor(hit.ObjectPoint, material, hit.EyeVector, hit.PointOnSurface, hit.SurfaceNormal)); } var reflected = CalculateReflectedColorAt(hit, remaining); var refracted = CalculateRefractedColorAt(hit, refractiveIndexEntering, refractiveIndexExiting, remaining); Tuple4 color; if (material.Reflective > 0 && material.Transparency > 0) { var reflectance = Schlick(hit, refractiveIndexEntering, refractiveIndexExiting); color = Tuple4.Add(surface, Tuple4.Add(Tuple4.Scale(reflected, reflectance), Tuple4.Scale(refracted, 1.0 - reflectance))); } else { color = Tuple4.Add(surface, Tuple4.Add(reflected, refracted)); } return(new Tuple4(Math.Min(colors.White.X, color.X), Math.Min(colors.White.X, color.Y), Math.Min(colors.White.X, color.Z), TupleFlavour.Vector)); }
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)); }
protected override Tuple4 GetBaseNormal(IFigure figure, Tuple4 pointOnSurface, double u, double v) { return(Tuple4.Add(Tuple4.Scale(N2, u), Tuple4.Add(Tuple4.Scale(N3, v), Tuple4.Scale(N1, (1.0 - u - v))))); }
public static Tuple4 GetAmbientColor(Tuple4 objectPoint, IMaterial material) { return(Tuple4.Scale(material.GetColor(objectPoint), material.Ambient)); }
protected override Tuple4 GetColorAtPattern(Tuple4 pointInPatternSpace) { return(Tuple4.Add(ColorA, Tuple4.Scale(colorDelta, Math.Abs(pointInPatternSpace.X) - Math.Floor(Math.Abs(pointInPatternSpace.X))))); }