public PointLight(Color clr, Vector3D position, double constant, double range, double linear, double quadratic) : base(clr, position, 1 / constant) { this.range = range; this.linear = linear; this.quadratic = quadratic; }
public Light(Color clr, Vector3D position, double intensity) { this.clr = clr; this.position = position; this.intensity = intensity; clr3D = new Vector3D((double)clr.R / 255, (double)clr.G / 255, (double)clr.B / 255); }
public override double LuminosityForPoint(Vector3D point) { double distance = (position - point).Length(); if (distance > range) return 0; double attenuation = intensity + linear * distance + quadratic * (distance * distance); return 1 / attenuation; }
public RGBA_D Shade(Ray ray, Vector3D pos, uint subIdx, out Ray reflection, out Ray refraction, ISceneManager scene) { if (shader != null) return shader.Shade(ray, pos, subIdx, this, scene, out reflection, out refraction); reflection = null; refraction = null; return RGBA_D.Empty; }
public bool IntersectWithLimitedLine(Vector3D linePoint1, Vector3D linePoint2, Vector3D lineDir, out Vector3D intersectPoint) { // first intersect with plane if (plane.GetIntersectionWithLimitedLine(linePoint1, linePoint2, lineDir, out intersectPoint)) { // check within rectangle area if (intersectPoint >= min && intersectPoint <= max) { return true; } } return false; }
public bool GetFirstIntersection(Vector3D origin, Vector3D dir, double maxLength, out IOpticalSceneObject obj, out Vector3D iPos, out double iDistance, out uint subIdx) { // intersect all bounds Vector3D endPt = origin + (dir * maxLength); double nDist = double.MaxValue; int nIdx = -1; Vector3D nPt = Vector3D.Empty; subIdx = 0; for (int i = 0; i < objects.Count; i++) { double dist = 0; if (objects[i].Radius == -1 || (SphereSceneObject.IntersectRaySphere(origin, dir, objects[i].Origin, objects[i].Radius * objects[i].Radius, out dist) && dist < nDist)) { // try actual intesection Vector3D pt; if (objects[i].GetIntersect(origin, endPt, dir, out pt, out dist, out subIdx) && dist < nDist && dist > 0.01) { nDist = dist; nIdx = i; nPt = pt; } /*else { nDist = dist; nIdx = i; nPt = pt; subIdx = 3; }*/ } } // pass back intersection if falls within rays remaining length if (nIdx != -1 && nDist < maxLength) { obj = objects[nIdx]; iPos = nPt; // even needed? iDistance = nDist; return true; } obj = null; iPos = Vector3D.Empty; iDistance = double.NaN; return false; }
public bool IntersectWithLine(Vector3D linePoint, Vector3D lineDir, out Vector3D intersectPoint) { // first intersect with plane // TODO: Select if backfacing allowed or not if (/*plane.IsFrontFacting(-lineDir) &&*/ plane.GetIntersectionWithLineIgnoreBackfacing(linePoint, lineDir, out intersectPoint)) { // round the intersection off slightly intersectPoint.Round(10); // check within rectangle area if (intersectPoint >= min && intersectPoint <= max) { return true; } } intersectPoint = Vector3D.Empty; return false; }
public HeightFieldObject(Vector3D origin, MaterialShader shader, Vector2D size, Bitmap bitmapSrc) : base(origin, shader, -1) { this.bitmapSrc = bitmapSrc; // calculate bounds areaExtent = size; Vector2D halfSize = size * 0.5; areaStart = origin - halfSize; areaEnd = origin + halfSize; double szLen = size.Length(); radius = Math.Sqrt((szLen * szLen) + (1.1 * 1.1)) / 2; hField = HeightField.FromBitmap(bitmapSrc); onePx = new Vector2D(areaExtent.X / hField.Width, areaExtent.Y / hField.Height); this.origin.Y = 0.5; zMin = 0; zTop = 1; rectangles = new Rectangle3D[] { new Rectangle3D(new Vector3D(areaStart.X, zTop, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 1, 0), -zTop)), // top new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zMin, areaEnd.Y), new PlaneD(new Vector3D(0, -1, 0), zMin)), // bottom new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaStart.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(-1, 0, 0), halfSize.X)), // left new Rectangle3D(new Vector3D(areaEnd.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(1, 0, 0), -halfSize.X)), // right new Rectangle3D(new Vector3D(areaStart.X, zMin, areaStart.Y), new Vector3D(areaEnd.X, zTop, areaStart.Y), new PlaneD(new Vector3D(0, 0, -1), halfSize.Y)), // front new Rectangle3D(new Vector3D(areaStart.X, zMin, areaEnd.Y), new Vector3D(areaEnd.X, zTop, areaEnd.Y), new PlaneD(new Vector3D(0, 0, 1), -halfSize.Y)), // back }; }
public TriangleGroupSceneObject(Vector3D origin, MaterialShader shader, double radius) : base(origin, shader, radius) { // determine scaling factor double scale = Math.Sqrt((radius * radius) / 2); this.radius *= 2; points = new Vector3D[] { new Vector3D(-1, -1, 1), new Vector3D(-1, 1, 1), new Vector3D(1, 1, 1), new Vector3D(1, -1, 1), new Vector3D(-1, -1, -1), new Vector3D(-1, 1, -1), new Vector3D(1, 1, -1), new Vector3D(1, -1, -1) }; // tansform points for (int i = 0; i < points.Length; i++) { points[i].X *= scale; points[i].X += origin.X; points[i].Y *= scale; points[i].Y += origin.Y; points[i].Z *= scale; points[i].Z += origin.Z; } triangles = new Triangle[] { new Triangle(4, 7, 6), new Triangle(6, 5, 4), new Triangle(2, 3, 0), new Triangle(0, 1, 2), new Triangle(1, 0, 4), new Triangle(4, 5, 1), new Triangle(7, 3, 2), new Triangle(2, 6, 7), new Triangle(0, 3, 7), new Triangle(7, 4, 0), new Triangle(6, 2, 1), new Triangle(1, 5, 6) }; tCoords = new Vector2D[] { new Vector2D(0, 0), new Vector2D(0, 1), new Vector2D(1, 1), new Vector2D(1, 1), new Vector2D(1, 0), new Vector2D(0, 0), }; CalcFaceNormals(); CalcVertexNormals(); }
public static Vector3D Reflect(Vector3D i, Vector3D n) { return Normalize(new Vector3D(i.X - (2.0 * n.X * Dot(n, i)), i.Y - (2.0 * n.Y * Dot(n, i)), i.Z - (2.0 * n.Z * Dot(n, i)))); }
public static Vector3D Cross(Vector3D u, Vector3D w) { // u x w return new Vector3D(w.Z * u.Y - w.Y * u.Z, w.X * u.Z - w.Z * u.X, w.Y * u.X - w.X * u.Y); }
public static double modv(Vector3D v) { return Math.Sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z); }
public static Vector3D Normalize(Vector3D source) { double mod_v = modv(source); if (Math.Abs(mod_v) < 1.0E-10) return Empty; return new Vector3D(source.X / mod_v, source.Y / mod_v, source.Z / mod_v); }
public RGBA_D Shade(Ray ray, Vector3D hitPoint, uint subIdx, IOpticalSceneObject obj, ISceneManager scene, out Ray reflection, out Ray refraction) { RGBA_D color = RGBA_D.Empty; // needed? // normal.Normalize(); Vector3D normal = obj.GetNormal(hitPoint, subIdx); //color.R = normal.X * 255; //color.G = normal.Y * 255; //color.B = normal.Z * 255; //color.A = 255; //refraction = null; //reflection = null; //return color; /*double len = (ray.Origin - hitPoint).Length(); len -= 2; color.R = color.G = color.B = len * 42.5;*/ foreach (Light light in scene.Lights) { Vector3D lv = light.Position - hitPoint; lv.Normalize(); // deal with light ray first (diffuse) if (true)//ray.TraceRayToLight(hitPoint, light.Position)) { // light pixel double cost = Vector3D.GetCosAngle(lv, normal); Vector3D vRefl = Vector3D.Reflect(-lv, normal); vRefl.Normalize(); double cosf = Vector3D.GetCosAngle(ray.DirectionUV, vRefl); double result1 = Math.Max(0, cost) * 255; double result2 = Math.Pow(Math.Max(0, cosf), shininess) * 255; double luminosity = light.LuminosityForPoint(hitPoint); double r = ((clr.R * diffuse * light.Clr3D.X * result1) + (light.Clr3D.X * result2)) * luminosity; double g = ((clr.G * diffuse * light.Clr3D.Y * result1) + (light.Clr3D.Y * result2)) * luminosity; double b = ((clr.B * diffuse * light.Clr3D.Z * result1) + (light.Clr3D.Z * result2)) * luminosity; color.R += r; color.G += g; color.B += b; } } // add ambient double alpha = 1 - transmission; color.R += (diffuse * scene.Ambient.R + (clr.R * emmissive)) * 255; //color.R *= alpha; color.G += (diffuse * scene.Ambient.G + (clr.G * emmissive)) * 255; //color.G *= alpha; color.B += (diffuse * scene.Ambient.B + (clr.B * emmissive)) * 255; //color.B *= alpha; color.A = alpha * 255; // blend texture (if any) /*if (texture != null) { Vector2D tCoord = obj.GetTexCoord(hitPoint, subIdx); // clamp for now if (tCoord.X < 0) tCoord.X = 0; if (tCoord.Y < 0) tCoord.Y = 0; if (tCoord.X > 1) tCoord.X = 1; if (tCoord.Y > 1) tCoord.Y = 1; int tX = (int)(tCoord.X * (texture.Width - 1)); int tY = (int)(tCoord.Y * (texture.Height - 1)); Color tClr = ((Bitmap)texture).GetPixel(tX, tY); color.R = (color.R + tClr.R) / 2; color.G = (color.G + tClr.G) / 2; color.B = (color.B + tClr.B) / 2; }*/ if (ray.Intensity > 0) { /*if (this.reflection > 0) { Vector3D refl = Vector3D.Reflect(ray.DirectionUV, normal); reflection = new Ray(hitPoint, refl, ray.Intensity * this.reflection, ray.Length, ray.MaxLength, ray.scene); } else*/ reflection = null; /*if (transmission > 0) refraction = new Ray(hitPoint, Vector3D.Normalize(Vector3D.Refract(1, 1.33, -ray.DirectionUV, normal)), ray.Intensity * transmission, ray.Length, ray.MaxLength, ray.scene); else*/ refraction = null; } else reflection = refraction = null; ray.Intensity = 0; return color; }
public static double Dot(Vector3D a, Vector3D b) { return (a.X * b.X) + (a.Y * b.Y) + (a.Z * b.Z); }
public abstract Vector3D GetNormal(Vector3D pos, uint subIdx);
public abstract bool GetIntersect(Vector3D p1, Vector3D p2, Vector3D uv, out Vector3D iPos, out double iDist, out uint subIdx);
/// <summary> /// Returns if the point represented by this vector is between to points ///</summary> ///<param name="begin">Start point of line</param> ///<param name="end">End point of line</param> ///<returns> True if between points, false if not. </returns> public bool IsBetweenPoints(Vector3D begin, Vector3D end) { double f = (end - begin).Length(); return GetDistanceFromSQ(begin) < f && GetDistanceFromSQ(end) < f; }
public abstract Vector2D GetTexCoord(Vector3D p, uint subIdx);
public double Dot(Vector3D b) { return (X * b.X) + (Y * b.Y) + (Z * b.Z); }
public static double GetCosAngle(Vector3D v1, Vector3D v2) { /* incident angle // inters pt (i) double ix, iy, iz; ix = px+t*vx; iy = py+t*vy; iz = pz+t*vz; // normal at i double nx, ny, nz; nx = ix - cx; ny = iy - cy; nz = iz - cz; */ v1.Normalize(); v2.Normalize(); // cos(t) = (v.w) / (|v|.|w|) double n = (v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z); double d = (modv(v1) * modv(v2)); if (Math.Abs(d) < 1.0E-10) return 0; return n / d; }
public override bool GetIntersect(Vector3D p1, Vector3D p2, Vector3D uv, out Vector3D iPos, out double iDist, out uint subIdx) { subIdx = 0; if (IntersectRaySphere(p1, uv, origin, radius * radius, out iDist)) { iPos = p1 - (iDist * uv); return true; } iPos = Vector3D.Empty; return false; /*subIdx = 0; Vector3D dst = p1 - origin; double B = Vector3D.Dot(dst, uv); double C = Vector3D.Dot(dst, dst) - (radius * radius); double D = B * B - C; if (D > 0) { iDist = -B - Math.Sqrt(D); iPos = p1 + (uv * iDist); return true; } iDist = -1; iPos = Vector3D.Empty; return false;*/ // x-xo 2 + y-yo 2 + z-zo 2 = r 2 // x,y,z = p+tv // At2 + Bt + C = 0 /*double vx = p2.X - p1.X; double vy = p2.Y - p1.Y; double vz = p2.Z - p1.Z; double A = (vx * vx + vy * vy + vz * vz); double B = 2.0 * (p1.X * vx + p1.Y * vy + p1.Z * vz - vx * origin.X - vy * origin.Y - vz * origin.Z); double C = p1.X * p1.X - 2 * p1.X * origin.X + origin.X * origin.X + p1.Y * p1.Y - 2 * p1.Y * origin.Y + origin.Y * origin.Y + p1.Z * p1.Z - 2 * p1.Z * origin.Z + origin.Z * origin.Z - radius * radius; double D = B * B - 4 * A * C; iDist = -1.0; subIdx = 0; if (D >= 0) { double t1 = (-B - Math.Sqrt(D)) / (2.0 * A); double t2 = (-B + Math.Sqrt(D)) / (2.0 * A); if (t1 < t2) iDist = t1; else iDist = t2; Vector3D hLen = new Vector3D(iDist * vx, iDist * vy, iDist * vz); iDist = hLen.Length(); iPos = p1 + hLen;//new Vector3D(p1.X + (iDist * vx), p1.Y + (iDist * vy), p1.Z + (iDist * vz)); return true; } iPos = Vector3D.Empty; return false;*/ }
public override Vector3D GetNormal(Vector3D pos, uint subIdx) { return Vector3D.Normalize(new Vector3D(pos.X - origin.X, pos.Y - origin.Y, pos.Z - origin.Z)); }
public SphereSceneObject(Vector3D origin, MaterialShader shader, double radius) : base(origin, shader, radius) { }
public static Vector3D Refract(double n1, double n2, Vector3D i, Vector3D mirror) { double c1 = -Dot(mirror, i); double n = n1 / n2; double c2 = Math.Sqrt(1.0 - n * n * (1.0 - c1 * c1)); return new Vector3D((n * i.X) + (n * c1 - c2) * mirror.X, (n * i.Y) + (n * c1 - c2) * mirror.Y, (n * i.Z) + (n * c1 - c2) * mirror.Z); }
public abstract double LuminosityForPoint(Vector3D point);
public Vector3D Cross(Vector3D w) { // u x w return new Vector3D(w.Z * Y - w.Y * Z, w.X * Z - w.Z * X, w.Y * X - w.X * Y); }
public DirectionalLight(Color clr, Vector3D position, double intensity) : base(clr, position, intensity) { }
/// <summary> /// Returns squared distance from an other point. /// Here, the vector is interpreted as point in 3 dimensional space. /// </summary> public double GetDistanceFromSQ(Vector3D other) { double vx = X - other.X; double vy = Y - other.Y; double vz = Z - other.Z; return (vx*vx + vy*vy + vz*vz); }
public override double LuminosityForPoint(Vector3D point) { throw new System.NotImplementedException(); }