public Sphere(DoublePoint3D center, double radius, ColorRGB color, int specular, float reflective, float transparency) : base(color, specular, transparency, reflective) { Center = center; Radius = radius; }
//private Closest private double IntersectRayEdge(DoublePoint3D[] edgePoints, DoublePoint3D rayPoint, DoublePoint3D rayVector) { var ab = edgePoints[1] - edgePoints[0]; var ac = edgePoints[3] - edgePoints[0]; /*try * { * var a = (edgePoints[0].X - rayPoint.X) / rayVector.X; * var b = ab.X / rayVector.X; * var c = ac.X / rayVector.X; * var d = (edgePoints[0].Y - rayPoint.Y - a * rayVector.Y) / (b * rayVector.Y - ab.Y); * var e = (ac.Y - c * rayVector.Y) / (b * rayVector.Y - ab.Y); * * var h = (edgePoints[0].Z + d * ab.Z - rayPoint.Z - a * rayVector.Z - d * rayVector.Z) / (e * rayVector.Z + c * rayVector.Z - e * ab.Z - ac.Z); * var w = d + e * h; * var t = a + b * w + c * h; * * * if ((0 <= h) && (h <= 1) && (0 <= w) && (w <= 1)) * return t; * } * catch * { * return -1; * }*/ var n = ab.VecMultiply(ac); var v = edgePoints[0] - rayPoint; var d = n.ScalMultiply(v); var e = n.ScalMultiply(rayVector); if (e != 0) { var a = (rayPoint.X + d / e * rayVector.X - edgePoints[0].X) / ab.X; var b = ac.X / ab.X; var h = (rayPoint.Y + d / e * rayVector.Y - edgePoints[0].Y - a * ab.Y) / (b * ab.Y + ac.Y); var w = a + b * h; if ((0 <= w) && (w <= 1) && (0 <= h) && (h <= 1)) { return(d / e); } } return(-1); }
private void RenderScene(DoublePoint3D position, DoublePoint2D rotation) { const double distance = 1; const byte recursionDepth = 3; var interval = new double[] { 0.0001, Inf }; var cameraPosition = position; //new DoublePoint3D(0, 0, 0);// (0, 5, 2); var cameraAngle = rotation; //new DoublePoint2D(0, 0);// (Math.PI / 2, Math.PI); for (var x = 0; x < Source.Width; x++) { for (var y = 0; y < Source.Height; y++) { DoublePoint3D viewPortPoint = CanvasToViewport(new DoublePoint2D(x, y), distance).RotateX(cameraAngle.X).RotateY(cameraAngle.Y); ColorRGB color = TraceRay(cameraPosition, viewPortPoint, interval, recursionDepth); Source.SetPixel(x, y, Color.FromArgb(color.R, color.G, color.B)); } } }
private double[] IntersectRaySphere(DoublePoint3D cameraPosition, DoublePoint3D viewVector, Sphere sphere) { var oc = cameraPosition - sphere.Center; //vector from camera to sphere center var a = viewVector.ScalMultiply(viewVector); //viewVector length var b = 2 * oc.ScalMultiply(viewVector); var c = oc.ScalMultiply(oc) - sphere.Radius * sphere.Radius; var discriminant = b * b - 4 * a * c; if (discriminant < 0) { return new double[] { Inf, Inf } } ; var root1 = (-b + Math.Sqrt(discriminant)) / (2 * a); var root2 = (-b - Math.Sqrt(discriminant)) / (2 * a); return(new double[] { root1, root2 }); }
public double Intercept(DoublePoint3D vector, DoublePoint3D normal, DoublePoint3D[] vertex) { double d = Dot(normal, vector); if (d > 0) { double k = Dot(normal, vertex[0]) / d; DoublePoint3D point = k * vector;//new DoublePoint3D( vector.X * k, vector.Y * k, vector.Z * k ); DoublePoint3D u = Sub(vertex[0], vertex[1]); DoublePoint3D v = Sub(vertex[0], vertex[2]); DoublePoint3D w = Sub(vertex[0], point); double uu = Dot(u, u); double uv = Dot(u, v); double vv = Dot(v, v); double wu = Dot(w, u); double wv = Dot(w, v); double D = uv * uv - uu * vv; double s, t; s = (uv * wv - vv * wu) / D; if (s < 0.0 || s > 1.0) { return(-1); } else { t = (uv * wu - uu * wv) / D; if (t < 0.0 || (s + t) > 1.0) { return(-1); } else { return(point.X / vector.X); } } } return(-1); }
private ColorRGB TraceRay(DoublePoint3D cameraPosition, DoublePoint3D viewPortPoint, double[] interval, int recursionDerpth) { var closest = ClosestIntersection(cameraPosition, viewPortPoint, interval); //Sphere=0, Point=1 if (closest.Object == -1) { return(BackGroundColor); } //Compute local color var intersectPoint = cameraPosition + closest.Point * viewPortPoint; //Compute intersection point var normalVector = (GraphicalObjects[closest.Object].ToString().Contains("Sphere")) ? intersectPoint - (GraphicalObjects[closest.Object] as Sphere).Center : closest.Normal; normalVector /= normalVector.Length(); ColorRGB localColor = ComputeLightning(intersectPoint, normalVector, -viewPortPoint, GraphicalObjects[closest.Object].Specular) * GraphicalObjects[closest.Object].Color; //Transparency var transparency = GraphicalObjects[closest.Object].Transparency; ColorRGB transparentColor = BackGroundColor; if (transparency > 0) { transparentColor = TraceRay(intersectPoint, viewPortPoint, interval, recursionDerpth); } //Reflection var reflection = GraphicalObjects[closest.Object].Reflective; if ((recursionDerpth <= 0) || (reflection <= 0)) { return((1 - transparency) * localColor + transparency * transparentColor); } var reflectedVector = ReflectRay(-viewPortPoint, normalVector); var reflectedColor = TraceRay(intersectPoint, reflectedVector, interval, recursionDerpth - 1); return((1 - reflection) * (1 - transparency) * localColor + reflection * (1 - transparency) * reflectedColor + transparency * transparentColor); }
public Closest(int obj, double point, DoublePoint3D normal) { Object = obj; Point = point; Normal = normal; }
public Closest(int obj, double point) { Object = obj; Point = point; Normal = new DoublePoint3D(); }
public static DoublePoint3D Sub(DoublePoint3D firstPoint, DoublePoint3D secondPoint) { return(secondPoint - firstPoint); }
public static double Dot(DoublePoint3D firstVec, DoublePoint3D secondVec) { return(firstVec.X * secondVec.X + firstVec.Y * secondVec.Y + firstVec.Z * secondVec.Z); }
public DirectLight(DoublePoint3D vector, float intense) : base(intense) { Vector = vector; }
/// <summary> /// Initializes a new instance of the CoordinateSphere class. /// </summary> /// <param name="x">The x of center point.</param> /// <param name="y">The y of center point.</param> /// <param name="z">The z of center point.</param> /// <param name="r">The radius.</param> public CoordinateSphere(double x, double y, double z, double r) { center = new(x, y, z); Radius = double.IsNaN(r) ? 0 : r; }
private float ComputeLightning(DoublePoint3D intersectPoint, DoublePoint3D normalVector, DoublePoint3D vector, int specular) { var result = 0f; var interval = new double[] { 0.001, Inf }; foreach (LightSource light in LightSources) { if (light.ToString().Contains("Ambient")) { result += light.Intense; } else { DoublePoint3D lightVector; if (light.ToString().Contains("Point")) { lightVector = (light as PointLight).Coord - intersectPoint; } else { lightVector = (light as DirectLight).Vector; } //Shadows Closest shadow = ClosestIntersection(intersectPoint, lightVector, interval); float transparency = 1; while (shadow.Object != -1) { if ((GraphicalObjects[shadow.Object].Transparency == 0) || (transparency == 0)) { transparency = 0; break; } transparency *= GraphicalObjects[shadow.Object].Transparency; shadow = ClosestIntersection(intersectPoint + shadow.Point * lightVector, lightVector, interval); } if (transparency == 0) { continue; } //Diffusal Illumination var scal = normalVector.ScalMultiply(lightVector); if (scal > 0) { result += (float)(light.Intense * scal / (normalVector.Length() * lightVector.Length())); } //Specular Illumination if (specular != -1) { var refleclectedVector = ReflectRay(lightVector, normalVector); scal = refleclectedVector.ScalMultiply(vector); if (scal > 0) { result += (float)(transparency * (light.Intense * Math.Pow(scal / (refleclectedVector.Length() * vector.Length()), specular))); } } } } return(result); }
private Closest ClosestIntersection(DoublePoint3D cameraPosition, DoublePoint3D viewPortPoint, double[] interval) { var closest = new Closest(-1, Inf); for (var i = 0; i < GraphicalObjects.Length; i++) { if (GraphicalObjects[i].ToString().Contains("Sphere")) { var intersections = IntersectRaySphere(cameraPosition, viewPortPoint, GraphicalObjects[i] as Sphere); if ((intersections[0] < closest.Point) && (interval[0] < intersections[0]) && (intersections[0] < interval[1])) { closest.Point = intersections[0]; closest.Object = i; } if ((intersections[1] < closest.Point) && (interval[0] < intersections[1]) && (intersections[1] < interval[1])) { closest.Point = intersections[1]; closest.Object = i; } } else { //var count = 0; var hex = GraphicalObjects[i] as Hexahedron; //First edge var mass = new DoublePoint3D[] { hex.Points[0].RotateX(hex.Rotation.X).RotateY(hex.Rotation.Y), hex.Points[1].RotateX(hex.Rotation.X).RotateY(hex.Rotation.Y), hex.Points[2].RotateX(hex.Rotation.X).RotateY(hex.Rotation.Y), hex.Points[3].RotateX(hex.Rotation.X).RotateY(hex.Rotation.Y) }; var intersection = Intercept(viewPortPoint, cameraPosition, mass);//IntersectRayEdge(mass, cameraPosition, viewPortPoint); if ((intersection > 1) && (intersection < closest.Point)) { closest.Point = intersection; closest.Object = i; closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); //count++; } //Second edge /*mass[0] = hex.Points[4]; * mass[1] = hex.Points[5]; * mass[2] = hex.Points[6]; * mass[3] = hex.Points[7]; * intersection = IntersectRayEdge(mass, cameraPosition, viewPortPoint); * if ((intersection > 1) && (intersection < closest.Point)) * { * closest.Point = intersection; * closest.Object = i; * closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); * count++; * if (count == 2) * continue; * } * * //Third edge * mass[0] = hex.Points[1]; * mass[1] = hex.Points[5]; * mass[2] = hex.Points[4]; * mass[3] = hex.Points[0]; * intersection = IntersectRayEdge(mass, cameraPosition, viewPortPoint); * if ((intersection > 1) && (intersection < closest.Point)) * { * closest.Point = intersection; * closest.Object = i; * closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); * count++; * if (count == 2) * continue; * } * * //Fourth edge * mass[0] = hex.Points[3]; * mass[1] = hex.Points[7]; * mass[2] = hex.Points[6]; * mass[3] = hex.Points[2]; * intersection = IntersectRayEdge(mass, cameraPosition, viewPortPoint); * if ((intersection > 1) && (intersection < closest.Point)) * { * closest.Point = intersection; * closest.Object = i; * closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); * count++; * if (count == 2) * continue; * } * * //Fifth edge * mass[0] = hex.Points[0]; * mass[1] = hex.Points[4]; * mass[2] = hex.Points[7]; * mass[3] = hex.Points[3]; * intersection = IntersectRayEdge(mass, cameraPosition, viewPortPoint); * if ((intersection > 1) && (intersection < closest.Point)) * { * closest.Point = intersection; * closest.Object = i; * closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); * count++; * if (count == 2) * continue; * } * * //Sixth edge * mass[0] = hex.Points[2]; * mass[1] = hex.Points[6]; * mass[2] = hex.Points[5]; * mass[3] = hex.Points[1]; * intersection = IntersectRayEdge(mass, cameraPosition, viewPortPoint); * if ((intersection > 1) && (intersection < closest.Point)) * { * closest.Point = intersection; * closest.Object = i; * closest.Normal = (mass[1] - mass[0]).VecMultiply(mass[2] - mass[0]); * count++; * if (count == 2) * continue; * }*/ } } return(closest); }
public PointLight(DoublePoint3D coord, float intense) : base(intense) { Coord = coord; }
/// <summary> /// Initializes a new instance of the CoordinateSphere class. /// </summary> public CoordinateSphere() { center = new(); Radius = 0; }
private DoublePoint3D ReflectRay(DoublePoint3D fallingVector, DoublePoint3D normalVector) { return(2 * normalVector * normalVector.ScalMultiply(fallingVector) - fallingVector); }
/// <summary> /// Initializes a new instance of the CoordinateSphere class. /// </summary> /// <param name="center">The center point.</param> /// <param name="r">The radius.</param> public CoordinateSphere(DoublePoint3D center, double r) { this.center = center ?? new(); Radius = double.IsNaN(r) ? 0 : r; }
/// <summary> /// Computes the distance between a point and a plane. /// </summary> /// <param name="point">The point.</param> /// <param name="a">The a parameter of plane.</param> /// <param name="b">The b parameter of plane.</param> /// <param name="c">The c parameter of plane.</param> /// <param name="d">The d parameter of plane.</param> /// <returns>The distance.</returns> public static double Distance(DoublePoint3D point, double a, double b, double c, double d) => Math.Abs(a * point.X + b * point.Y + c * point.Z + d) / Math.Sqrt(a * a + b * b + c * c);