public override Vector Normal(Vector p) { //Assuming sphere at origin as (norm(P-C)==norm(P)) return p.Normalize(); //return Vector(); }
public Hit(Vector source, Vector d, float t, SceneObject scObject) { this.source = source; this.d = d; this.t = t; this.scObject = scObject; }
public override float Intersect(Vector source, Vector d) { float t = (a - Vector.Dot(source, n))/Vector.Dot(d, n); if( (t >= 0) && (Vector.Dot(d, n) != 0) ) return t; return -1; }
public static float Dot(Vector f, Vector v) { /** dot product *************************************/ float ret = 0; ret += v.x * f.x; ret += v.y * f.y; ret += v.z * f.z; return ret; }
public static Vector Cross(Vector f, Vector v) { /** cross product ***********************************/ float a=0, b=0, c=0; a = f.y*v.z - f.z*v.y; b = f.z*v.x - f.x*v.z; c = f.x*v.y - f.y*v.x; return new Vector(a, b, c); }
public Vector HitPoint() { //x = x0 + t*dx x0 = source_X, dx = direction of ray (x1 - x0) //y = y0 + t*dy //z = z0 + t*dz float x = source.x + t*d.x; float y = source.y + t*d.y; float z = source.z + t*d.z; Vector hitVect = new Vector(x, y, z); return hitVect; }
public override float Intersect(Vector source, Vector d) { float A = Vector.Dot(d, d); float B = Vector.Dot(2*source, d); //NB C determines that this spere is positioned at the origin and has radius 1 float C = Vector.Dot(source, source) - 1; if(B*B - 4*A*C <= 0) return -1; // no hit float t1; if(B>0) // for numerical precision t1 = (-B - Convert.ToSingle( Math.Sqrt(B*B - 4*A*C)) ) / (2*A); else t1 = (-B + Convert.ToSingle( Math.Sqrt(B*B - 4*A*C)) ) / (2*A); float t2 = C/(A*t1); // easier way to get t2 if(t1<t2) return t1; // need only closer t else return t2; }
private void RayTracingLoop(int R, int C) { int increaseCount = 0; int len = (windowWidth * windowHeight * 3) / 10; int modelCount = ((R * windowWidth * 3) + C)/ len; if ((modelCount == 0)||(modelCount==5)) { modelCount--; } //Begin loop at correct Row and Column so that different threads calculate different areas for (int r=R; r < R + workWidth; r++) { for (int c=0; c < windowWidth; c++) { // construct ray through (c, r) using axis u,v,n and window constraints H,W Vector d = new Vector(0, 0, 0); //d = pixelPos - eye //d = -Nn +W(2c/ncols -1)u +H(2r/nrows -1)v d = (n * (-N) + u * (W * ((2 * (float)c / windowWidth) - 1)) + v * (H * ((2 * (float)r / windowHeight) - 1))); // intersect ray with scene objects Hit hit = intersect(eye, d); // shade pixel accordingly Color color = shade(hit); // add a purple haze to objects in the distance float hazeDistance = 8.0f; if (hit.scObject != null && hit.t > hazeDistance) { float logDist; if (this.caching) { // Caching for haze intensity depending upon distance from the camera if (HttpRuntime.Cache.Get("colorForHitT" + hit.t.ToString()) != null) { color = (Color)HttpRuntime.Cache.Get("colorForHitT" + hit.t.ToString()); } else { logDist = Convert.ToSingle(Math.Log((hit.t - hazeDistance) + 1)); if (logDist > 20) logDist = 20; color = color + (new Color(0.05f, 0.01f, 0.05f)) * logDist; HttpRuntime.Cache.Insert("colorForHitT" + hit.t.ToString(), color); } } else { logDist = Convert.ToSingle(Math.Log((hit.t - hazeDistance) + 1)); if (logDist > 20) logDist = 20; color = color + (new Color(0.05f, 0.01f, 0.05f)) * logDist; } } if (((r * windowWidth * 3) + c) % len == 0) { modelCount++; } try { //Store double array of RGB values pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 0 - modelCount * len] = AddColor(color.r); //Red pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 1 - modelCount * len] = AddColor(color.g); //Green pixelArray[modelCount][((r * windowWidth) * 3) + (c * 3) + 2 - modelCount * len] = AddColor(color.b); //Blue increaseCount++; if ((increaseCount == (len*2.5)) && (parallel)) { return; } } catch (IndexOutOfRangeException rangeEx) { Debug.WriteLine(((r * windowWidth) * 3) + (c * 3) + 0 - modelCount * len, "Position 1"); Debug.WriteLine(modelCount, "ModelCount"); Debug.WriteLine(rangeEx.StackTrace, "STACK TRACE"); } } } }
Hit intersect(Vector source, Vector d) { // initially hit scObject==NULL (no hit) Hit hit = new Hit(source, d, -1f, null); // for every scObject, check if ray hits it for(int i=0; i<numObjects; i++) { float t = sceneObjects[i].Intersect(source, d); // 1. only use hits visible for the camera // 2. only overwrite hit if either there is // no hit yet, or the hit is closer if(t>0.00001 && (hit.scObject==null || t<hit.t)) hit = new Hit(source, d, t, sceneObjects[i]); } return hit; }
// returns the normal at the given point p // if p is not on the object the result is undefined public abstract Vector Normal(Vector p);
// returns the t value of the closest ray-object intersection, or -1 otherwise public abstract float Intersect(Vector source, Vector d);
public override Vector Normal(Vector p) { return n; }
public double Distance(Vector p) { return Vector.Dot(n, p) - a; }
public void Set(Vector v) { x = v.x; y = v.y; z = v.z; }