// Create sphere public Sphere(VPoint location, float radius, Material mat) { Mat = mat; Location = location; Radius = radius; Radius2 = radius * radius; }
// Intersects with a ray, returns the length at which the ray hits the sphere, -1 if no intersection override public float Intersect(Ray ray) { // If the ray starts inside of the sphere if ((Location - ray.Location).Length < Radius - 0.001f) { float a = ray.Direction * ray.Direction; float b = ray.Direction * (ray.Location - Location) * 2; float c = (ray.Location - Location) * (ray.Location - Location) - Radius2; float d = b * b - 4 * a * c; d = (float)Math.Sqrt(d); float distance = Math.Max((-b + d) / (2 * a), (-b - d) / (2 * a)); return(distance); } // Otherwise the ray starts outside of the sphere else { VPoint c = Location - ray.Location; float t = c * ray.Direction; VPoint q = c - t * ray.Direction; float p = q * q; if (p > Radius2) { return(-1); } t -= (float)Math.Sqrt(Radius2 - p); return(t); } }
abstract public float Intersect(Ray ray); // Misschien naar abstract public void Intersect en de intersection opslaan in class Intersect? // Reflect a ray public Ray Reflect(Ray ray, VPoint location) { VPoint d = ray.Direction; VPoint n = normal(location).Direction; return(new Ray(location, (d - (2 * (d * n) * n)).Normalize())); }
// Create a light source public Light(VPoint location, float r, float g, float b) { Location = location; Red = r; Green = g; Blue = b; }
// Create ray public Ray(VPoint Locationinit, VPoint Directioninit) { Location = Locationinit; Direction = Directioninit.Normalize(); Distance = float.PositiveInfinity; recursion = 0; }
// Create an intersection public Intersection(Ray ray, VPoint location, Primitive p) { Distance = (location - ray.Location).Length; Ray = ray; Location = location; ThingWeIntersectedWith = p; }
public override void debug(Surface screen) { float newradius = (float)Math.Sqrt(Radius2 - Location.Y); VPoint middle = Location; middle.Y = 0; VPoint previousDrawPoint = new VPoint(0, 0, 1); previousDrawPoint = previousDrawPoint.Normalize() * Radius; previousDrawPoint += middle; for (int i = 1; i < 121; i++) { VPoint DrawPoint = new VPoint(Game.SinTable[(i * 3) % 360], 0, Game.SinTable[(i * 3 + 90) % 360]); DrawPoint = DrawPoint.Normalize() * Radius; DrawPoint += middle; int x1, x2; x1 = DrawPoint.transform("x"); x2 = previousDrawPoint.transform("x"); if (x1 <= 512 && x2 <= 512) { screen.Line(x1, DrawPoint.transform("y"), x2, previousDrawPoint.transform("y"), Mat.GetColor(new VPoint(0, 0, 0)).getColor()); } previousDrawPoint = DrawPoint; } }
//Sets the vertical direction of the virtual screen after the camera is rotated. private void setYDirection() { YDirection = XDirection % Orientation; if (YDirection.Y > 0) { YDirection *= -1; } }
// Get a ray through given coordinates public Ray getRay(float x, float y) { x /= 256; y /= 256; VPoint positionOnScreen = Upperleft; positionOnScreen += x * XDirection + y * YDirection; return(new Ray(Position, (positionOnScreen - Position).Normalize())); }
//To translate the camera public void moveCamera(VPoint direction) { Position += direction; Upperleft += direction; Upperright += direction; Lowerleft += direction; Lowerright += direction; Target += direction; }
//To rotate the camera public void turnCamera(VPoint direction) { Orientation = (Orientation + direction).Normalize(); Target = Position + Orientation; setXDirection(); setYDirection(); Upperleft = Target - XDirection - YDirection; Upperright = Target + XDirection - YDirection; Lowerleft = Target - XDirection + YDirection; Lowerright = Target + XDirection - YDirection; }
// Create camera public Camera() { Position = new VPoint(0, 0, 0); Orientation = new VPoint(0, 0, 1); Target = Position + Orientation; Upperleft = new VPoint(-1, 1, 1); XDirection = new VPoint(1, 0, 0); YDirection = new VPoint(0, -1, 0); Upperright = new VPoint(1, 1, 1); Lowerleft = new VPoint(-1, -1, 1); Lowerright = new VPoint(1, -1, 1); }
// Determine the colors on the scene public VPoint color(Scene scene) { if (ThingWeIntersectedWith != null) { ShadowRays = new Ray[scene.Lights.Length]; VPoint diffusion = new VPoint(); for (int i = 0; i < scene.Lights.Length; i++) { Light light = scene.Lights[i]; VPoint shadowRayDirection = (light.Location - Location); ShadowRays[i] = new Ray(Location + 0.00001f * shadowRayDirection.Normalize(), shadowRayDirection.Normalize()); ShadowRays[i].Distance = shadowRayDirection.Length; float distance = scene.intersect(ShadowRays[i]).Distance; if (distance >= shadowRayDirection.Length - 2 * 0.00001) { ShadowRays[i].Distance = distance; VPoint j = ThingWeIntersectedWith.normal(Location).Direction; if (j * Ray.Direction > 0) { j *= -1; } diffusion += light.reflectedColor(ThingWeIntersectedWith.Mat.GetColor(Location), 60 * Math.Max(0, j * ShadowRays[i].Direction.Normalize()) * (1 / (shadowRayDirection.Length * shadowRayDirection.Length))); } } diffusion = new VPoint(Math.Min(diffusion.X, 255), Math.Min(diffusion.Y, 255), Math.Min(diffusion.Z, 255)); if (ThingWeIntersectedWith.Mat.Reflects != 0 && Ray.recursion < Game.Recursion) { secondaryRay = ThingWeIntersectedWith.Reflect(Ray, Location); secondaryRay.recursion = Ray.recursion + 1; Intersection inter = scene.intersect(secondaryRay); if (inter.ThingWeIntersectedWith == scene.Primitives[0]) { secondaryRay.Distance = 3; } else { secondaryRay.Distance = inter.Distance; } return(VPoint.colorStuff(inter.color(scene), diffusion, ThingWeIntersectedWith.Mat.Reflects)); } else { return(diffusion); } } return(new VPoint()); }
//Sets the horizontal direction of the virtual screen after the camera is rotated. private void setXDirection() { float dX; if (Orientation.Z > 0) { dX = 1; } else if (Orientation.Z < 0) { dX = -1; } else { XDirection = new VPoint(0, 0, -Orientation.X).Normalize(); return; } XDirection = new VPoint(dX, 0, -Orientation.X * dX / Orientation.Z).Normalize(); }
public VPoint GetColor(VPoint p) { switch (Texture) { case 0: return(Color); case 1: return(new VPoint(231, 231, 231) * ((((Math.Abs((int)Math.Floor(p.X) + (int)Math.Floor(p.Z)))) % 2) + 0.1f)); case 2: { int x = Modulo((int)(p.X * 600) + 3000, 6000); int y = Modulo((int)(p.Z * 400) + 1600, 4000); Color Pixel = Game.Space.GetPixel(x, y); return(new VPoint(Pixel.R, Pixel.G, Pixel.B)); } default: return(Color); } }
public void debug(Surface screen, VPoint endPoint, int type) { int color = 0; switch (type) { case 0: color = 0xFF0000; break; case 1: color = 0x00FF00; break; case 2: color = 0x0000FF; break; case 3: color = 0xFFFFFF; break; case 4: color = 0x888800; break; } // Make sure that the debug output isn't drawn in the scene (in other words, limit the x value to 512, if it exceeds 512 don't draw the line in question) int x1, x2; x1 = Location.transform("x"); x2 = endPoint.transform("x"); if (x1 <= 512 && x2 <= 512) { screen.Line(x1, Location.transform("y"), x2, endPoint.transform("y"), color); } }
abstract public Ray normal(VPoint location);
// Determine the color based on reflection and diffusion public static VPoint colorStuff(VPoint reflection, VPoint diffusion, float r) { return(diffusion * (1 - r) + r * new VPoint((diffusion.X * reflection.X) / 255, (diffusion.Y * reflection.Y) / 255, (diffusion.Z * reflection.Z) / 255)); }
// Determine the reflected color public VPoint reflectedColor(VPoint colorOfObject, float intensity) { return(new VPoint((int)(colorOfObject.X * intensity * Red), (int)(colorOfObject.Y * intensity * Green), (int)(colorOfObject.Z * intensity * Blue))); }
// Since the plane is defined by its normal and distance to the origin, we simply return the normal as a ray public override Ray normal(VPoint location) { return(new Ray(location, Normal)); }
// Create the plane public Plane(VPoint normal, float distance, Material mat) { Mat = mat; Normal = normal.Normalize(); Distance = distance; }
// Normal on the sphere given the location of the intersection public override Ray normal(VPoint location) { return(new Ray(location, (location - Location).Normalize())); }
// Create reflective material public Material(VPoint c, float r) { Color = c; Reflects = r; Texture = 0; }