public override RGBColor TraceRay(Ray ray, int depth) { // If depth exceeded maximum depth, no hits will occurr, and pixel will be black if(depth > worldPointer.CurrentViewPlane.MaximumRenderDepth) { return (GlobalVars.COLOR_BLACK); } // Otherwise fetch shader info for current ray, assuming a hit occurs else { ShadeRec shadeRec = worldPointer.HitObjects(ray); if(shadeRec.HitAnObject) { shadeRec.RecursionDepth = depth; shadeRec.Ray = ray; // apply shading and return color return (shadeRec.ObjectMaterial.Shade(shadeRec)); } else { // return background color if no hits return worldPointer.CurrentBackgroundColor; } } }
/// <summary> /// Returns color of a ray traced in the scene. /// </summary> /// <param name="ray">Ray for tracing</param> /// <returns>Color of the object intersected, or the background color if no intersection occurred.</returns> public override RGBColor TraceRay(Ray ray) { ShadeRec shadeRec = new ShadeRec(worldPointer.HitObjects(ray)); if(shadeRec.HitAnObject) { //Console.Write("hit"); //return new RGBColor(1.0, 0, 0); shadeRec.Ray = ray; //Store information for specular highlight. return (shadeRec.ObjectMaterial.Shade(shadeRec)); //Call shader function for object material. } else { return worldPointer.CurrentBackgroundColor; } //No need to call shader function if no intersection occurred. }
/// <summary> /// Renders the world on a single thread [deprecated, use RenderSceneMultiThreaded] /// </summary> /// <param name="world">World reference</param> public override void RenderScene(World worldRef) { RGBColor lightingSum; ViewPlane vp = worldRef.CurrentViewPlane; Ray ray = new Ray(_eye,new Vect3D(0,0,0)); int depth = 0; //Depth of recursion Point2D sp = new Point2D(); //Sample point on a unit square Point2D pp = new Point2D(); ; //Sample point translated into screen space worldRef.OpenWindow(vp.HorizontalResolution, vp.VerticalResolution); vp.PixelSize /= _zoom; for(int row = 0; row < vp.VerticalResolution; row++) { for(int column = 0; column < vp.HorizontalResolution; column++) { lightingSum = GlobalVars.COLOR_BLACK; //Start with no color, everything is additive for(int sample = 0; sample < vp.NumSamples; sample ++) { sp = worldRef.CurrentViewPlane.ViewPlaneSampler.SampleUnitSquare(); pp.coords.X = worldRef.CurrentViewPlane.PixelSize * (column - 0.5f * vp.HorizontalResolution + sp.coords.X); pp.coords.Y = worldRef.CurrentViewPlane.PixelSize * (row - 0.5f * vp.VerticalResolution + sp.coords.Y); ray.Direction = GetRayDirection(pp); lightingSum = lightingSum + worldRef.CurrentTracer.TraceRay(ray, depth); } lightingSum /= vp.NumSamples; lightingSum *= _exposureTime; worldRef.DisplayPixel(row, column, lightingSum); //Poll events in live render view worldRef.PollEvents(); } } }
/// <summary> /// Renders a single rectangular chunk of the scene /// </summary> /// <param name="worldRef">Reference to the world</param> /// <param name="xCoord1">Smallest x coordinate</param> /// <param name="xCoord2">Largest x coordinate</param> /// <param name="yCoord1">Smallest y coordinate</param> /// <param name="yCoord2">Largest y coordinate</param> /// <param name="threadNum">Thread number</param> public override void RenderSceneFragment(World worldRef, int xCoord1, int xCoord2, int yCoord1, int yCoord2, int threadNum) { //To avoid clashes with other threads accessing sampler, clone the main world sampler Sampler localSampler = worldRef.CurrentViewPlane.ViewPlaneSampler.Clone(); RGBColor L; ViewPlane vp = worldRef.CurrentViewPlane; Ray ray = new Ray(_eye, new Vect3D(0, 0, 0)); int depth = 0; //Depth of recursion Point2D unitSquareSample = new Point2D(); //Sample point on a unit square Point2D sampleInScreenSpace = new Point2D(); ; //Sample point translated into screen space int height = yCoord2 - yCoord1; int width = xCoord2 - xCoord1; for (int row = 0; row < height; row++) { for (int column = 0; column < width; column++) { L = GlobalVars.COLOR_BLACK; //Start with no color, everything is additive for (int sample = 0; sample < vp.NumSamples; sample++) { unitSquareSample = localSampler.SampleUnitSquare(); sampleInScreenSpace.coords.X = worldRef.CurrentViewPlane.PixelSize * (column + xCoord1 - 0.5f * vp.HorizontalResolution + unitSquareSample.coords.X); sampleInScreenSpace.coords.Y = worldRef.CurrentViewPlane.PixelSize * (row + yCoord1 - 0.5f * vp.VerticalResolution + unitSquareSample.coords.Y); ray.Direction = GetRayDirection(sampleInScreenSpace); L = L + worldRef.CurrentTracer.TraceRay(ray, depth); } L /= vp.NumSamples; L *= _exposureTime; worldRef.DisplayPixel(row + yCoord1, column + xCoord1, L); } } DequeueNextRenderFragment(); }
public override bool Hit(Ray r, float tmin) { /// Hit point on a torus as distance from point r.origin along vector r.direction /// can be solved for as a quartic equation of the form c4t^4 + c3t^3 + c2t^2 + c1t + c0 = 0 /// where: /// c4 = (xd^2 + yd^2 + zd^2)^2 /// c3 = 4(xd^2 + yd^2 + zd^2)(xoxd+yoyd+zozd) /// c2 = 2(xd^2 + yd^2 + zd^2)(xo^2+yo^2+zo^2-(a^2 + b^2))+4(xoxd + yoyd + zozd)^2 + 4a^2yd^2 /// c1 = 4(xo^2 + yo^2 + zo^2 - (a^2 + b^2))(xoxd + yoyd + zozd) + 8a^2yoyd /// c0 = 4(xo^2 + yo^2 + zo^2 - (a^2 + b^2))^2 - 4a^2(b^2 - yo^2) /// ///Using quartic solving algorithm /// float x1 = r.Origin.X; float y1 = r.Origin.Y; float z1 = r.Origin.Z; float d1 = r.Direction.X; float d2 = r.Direction.Y; float d3 = r.Direction.Z; float[] coefficients = new float[5]; float[] roots = new float[4]; float sum_d_sqrd = d1 * d1 + d2 * d2 + d3 * d3; float e = x1 * x1 + y1 * y1 + z1 * z1 - _a * _a - _b * _b; float f = x1 * d1 + y1 * d2 + z1 * d3; float four_a_sqrd = 4.0f * _a * _a; coefficients[0] = e * e - four_a_sqrd * (_b * _b - y1 * y1); coefficients[1] = 4.0f * f * e + 2.0f * four_a_sqrd * y1 * d2; coefficients[2] = 2.0f * sum_d_sqrd * e + 4.0f * f * f + four_a_sqrd * d2 * d2; coefficients[3] = 4.0f * sum_d_sqrd * f; coefficients[4] = sum_d_sqrd * sum_d_sqrd; //Find roots int numroots = FastMath.SolveQuartic(coefficients, roots); if (numroots == 0) { return false; } //Find the smallest root for (int i = 0; i < numroots; i++) { if (roots[i] > GlobalVars.K_EPSILON && roots[i] < tmin) { return true; } } return false; }
public virtual bool InShadow(ShadeRec sr, Ray ray) { return false; }
public override RGBColor TraceRay(Ray ray, int depth) { return TraceRay(ray); }
/// <summary> /// Renders a single rectangular chunk of the scene /// </summary> /// <param name="worldRef">Reference to the world</param> /// <param name="xCoord1">Smallest x coordinate</param> /// <param name="xCoord2">Largest x coordinate</param> /// <param name="yCoord1">Smallest y coordinate</param> /// <param name="yCoord2">Largest y coordinate</param> /// <param name="threadNum">Thread number</param> public override void RenderSceneFragment(World worldRef, int xCoord1, int xCoord2, int yCoord1, int yCoord2, int threadNum) { RGBColor L = new RGBColor(); Ray ray = new Ray(); ViewPlane vp = worldRef.CurrentViewPlane; int depth = 0; Point2D samplePoint = new Point2D(); Point2D samplePointPixelSpace = new Point2D(); Point2D samplePointOnDisk = new Point2D(); Point2D samplePointOnLens = new Point2D(); Sampler screenSamplerClone = GlobalVars.VIEWPLANE_SAMPLER.Clone(); Sampler lensSamplerClone = depthSampler.Clone(); //vp.s /= zoom; //Vector2 tmp2 = new Vector2(vp.hres * 0.5f, vp.vres*0.5f); for (int r = yCoord1; r < yCoord2; r++) { for (int c = xCoord1; c < xCoord2; c++) { L = GlobalVars.COLOR_BLACK; for (int n = 0; n < vp.NumSamples; n++) { //Sample on unit square samplePoint = screenSamplerClone.SampleUnitSquare(); //Sample in screenspace //Vector2 tmp1 = new Vector2(c, r); //pp.coords = vp.s * (tmp1 - tmp2 * sp.coords); samplePointPixelSpace.coords.X = vp.PixelSize * (c - vp.HorizontalResolution * 0.5f + samplePoint.coords.X); samplePointPixelSpace.coords.Y = vp.PixelSize * (r - vp.VerticalResolution * 0.5f + samplePoint.coords.Y); samplePointOnDisk = lensSamplerClone.SampleDisk(); samplePointOnLens.coords.X = samplePointOnDisk.coords.X * radius; samplePointOnLens.coords.Y = samplePointOnDisk.coords.Y * radius; //lp.coords = dp.coords * radius; ray.Origin = _eye + samplePointOnLens.coords.X * u + samplePointOnLens.coords.Y * v; ray.Direction = GetRayDirection(samplePointPixelSpace, samplePointOnLens); L += worldRef.CurrentTracer.TraceRay(ray, depth); } L /= vp.NumSamples; L *= _exposureTime; worldRef.DisplayPixel(r, c, L); } } DequeueNextRenderFragment(); }
/// <summary> /// /// </summary> /// <param name="sr">Shading parameters</param> /// <param name="ray">Ray to cast from object to point light</param> /// <returns></returns> public override bool InShadow(ShadeRec sr, Ray ray) { int num_objects = sr.WorldPointer.RenderList.Count; float tmin; //Find the closest intersection point along the given ray for (int i = 0; i < num_objects; i++) { tmin = (_location - sr.HitPoint).Coordinates.Length(); if (sr.WorldPointer.RenderList[i].Hit(ray, tmin)) { return true; } } return false; }
public override RGBColor TraceRay(Ray ray) { throw new NotImplementedException(); }
public override RGBColor TraceRay(Ray ray, float tMin, int depth) { throw new NotImplementedException(); }
//public float getA() { return _a; } //public float getB() { return _b; } //public BoundingBox getBB() { return _boundingBox; } public override bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { if(!_boundingBox.Hit(r, tmin)) { return false; } /// Hit point on a torus as distance from point r.origin along vector r.direction /// can be solved for as a quartic equation of the form c4t^4 + c3t^3 + c2t^2 + c1t + c0 = 0 /// where: /// c4 = (xd^2 + yd^2 + zd^2)^2 /// c3 = 4(xd^2 + yd^2 + zd^2)(xoxd+yoyd+zozd) /// c2 = 2(xd^2 + yd^2 + zd^2)(xo^2+yo^2+zo^2-(a^2 + b^2))+4(xoxd + yoyd + zozd)^2 + 4a^2yd^2 /// c1 = 4(xo^2 + yo^2 + zo^2 - (a^2 + b^2))(xoxd + yoyd + zozd) + 8a^2yoyd /// c0 = 4(xo^2 + yo^2 + zo^2 - (a^2 + b^2))^2 - 4a^2(b^2 - yo^2) /// ///Using quartic solving algorithm /// float x1 = r.Origin.X; float y1 = r.Origin.Y; float z1 = r.Origin.Z; float d1 = r.Direction.X; float d2 = r.Direction.Y; float d3 = r.Direction.Z; float[] coefficients = new float[5]; float[] roots = new float[4]; float sum_d_sqrd = d1 * d1 + d2 * d2 + d3 * d3; float e = x1 * x1 + y1 * y1 + z1 * z1 - _a * _a - _b * _b; float f = x1 * d1 + y1 * d2 + z1 * d3; float four_a_sqrd = 4.0f * _a * _a; coefficients[0] = e * e - four_a_sqrd * (_b * _b - y1 * y1); coefficients[1] = 4.0f * f * e + 2.0f * four_a_sqrd * y1 * d2; coefficients[2] = 2.0f * sum_d_sqrd * e + 4.0f * f * f + four_a_sqrd * d2 * d2; coefficients[3] = 4.0f * sum_d_sqrd * f; coefficients[4] = sum_d_sqrd * sum_d_sqrd; //Find roots int numroots = FastMath.SolveQuartic(coefficients, roots); bool hit = false; float t = GlobalVars.K_HUGE_VALUE; if (numroots == 0) { return false; } //Find the smallest root for(int i = 0;i< numroots;i++) { if(roots[i] > GlobalVars.K_EPSILON && roots[i] < t) { hit = true; t = roots[i]; } } if(!hit) { return false; } tmin = t; sr.HitPointLocal = r.Origin + (t * r.Direction); sr.ObjectMaterial = _material; //Compute the normal at the hit point (see Thomas and Finney, 1996) sr.Normal = CalculateNormal(sr.HitPointLocal); return hit; }
public override bool Hit(Ray r, float tmin) { float ox = r.Origin.X; float oy = r.Origin.Y; float oz = r.Origin.Z; float dx = r.Direction.X; float dy = r.Direction.Y; float dz = r.Direction.Z; float tx_min, ty_min, tz_min; float tx_max, ty_max, tz_max; //How this algorithm works: //Generate *x_min and *x_max values which indicate the minimum and maximum length a line segment //from origin in the ray direction can have and be within the volume of the bounding box. If all 3 //distance ranges overlap, then the bounding box was hit. float a = 1.0f / dx; if (a >= 0.0) { tx_min = (x0 - ox) * a; tx_max = (x1 - ox) * a; } else { tx_min = (x1 - ox) * a; tx_max = (x0 - ox) * a; } float b = 1.0f / dy; if (b >= 0.0) { ty_min = (y0 - oy) * b; ty_max = (y1 - oy) * b; } else { ty_min = (y1 - oy) * b; ty_max = (y0 - oy) * b; } float c = 1.0f / dz; if (c >= 0.0) { tz_min = (z0 - oz) * c; tz_max = (z1 - oz) * c; } else { tz_min = (z1 - oz) * c; tz_max = (z0 - oz) * c; } float t0, t1; //largest entering t value if (tx_min > ty_min) { t0 = tx_min; } else { t0 = ty_min; } if (tz_min > t0) { t0 = tz_min; } //smallest exiting t value if (tx_max < ty_max) { t1 = tx_max; } else { t1 = ty_max; } if (tz_max < t1) { t1 = tz_max; } //If the largest entering t value is less than the smallest exiting t value, then the ray is inside //the bounding box for the range of t values t0 to t1; return (t0 < t1 && t1 > GlobalVars.K_EPSILON && t1 < tmin); }
public override bool Hit(Ray ray, ref float tMin, ref ShadeRec sr) { //First verify intersection point of ray with bounding box. Vector3 o = ray.Origin.Coordinates; //float ox = r.origin.coords.X; //float oy = r.origin.coords.Y; //float oz = r.origin.coords.Z; Vector3 d = ray.Direction.Coordinates; //float dx = r.direction.coords.X; //float dy = r.direction.coords.Y; //float dz = r.direction.coords.Z; Vector3 c0 = boundingBox.corner0; Vector3 c1 = boundingBox.corner1; //float x0 = bbox.c0.X; //float y0 = bbox.c0.Y; //float z0 = bbox.c0.Z; //float x1 = bbox.c1.X; //float y1 = bbox.c1.Y; //float z1 = bbox.c1.Z; float tx_min, ty_min, tz_min; float tx_max, ty_max, tz_max; Vector3 inverseDenominator = new Vector3(1.0f)/d; //Vector3 min; //Vector3 max; float a = inverseDenominator.X; if (a >= 0) { tx_min = (c0.X - o.X) * a; tx_max = (c1.X - o.X) * a; } else { tx_min = (c1.X - o.X) * a; tx_max = (c0.X - o.X) * a; } float b = inverseDenominator.Y; if (b >= 0) { ty_min = (c0.Y - o.Y) * b; ty_max = (c1.Y - o.Y) * b; } else { ty_min = (c1.Y - o.Y) * b; ty_max = (c0.Y - o.Y) * b; } float c = inverseDenominator.Z; if (c >= 0) { tz_min = (c0.Z - o.Z) * c; tz_max = (c1.Z - o.Z) * c; } else { tz_min = (c1.Z - o.Z) * c; tz_max = (c0.Z - o.Z) * c; } //Determine if volume was hit float t0, t1; t0 = (tx_min > ty_min) ? tx_min : ty_min; if (tz_min > t0) t0 = tz_min; t1 = (tx_max < ty_max) ? tx_max : ty_max; if (tz_max < t1) t1 = tz_max; if (t0 > t1) { return false; } float tPosition; //Entry value of t for ray, lowest possible t value if (!boundingBox.inside(ray.Origin)) tPosition = t0; //Start casting from t0 if starting from outside bounding box else tPosition = GlobalVars.K_EPSILON; //Start casting from origin if starting from inside bounding box float tDistance = 0; //Value returned by the distance function approximation float tPositionPrevious = 0; float adjustedDistance = 0; //Adjusted distance scaled by distance adjustment parameter float currentDistanceFunctionValue = 0; float previousDistanceFunctionValue = 0; Point3D location; //Traverse space using raymarching algorithm do { location = ray.Origin + ray.Direction * tPosition; tDistance = EvaluateDistanceFunction(location,ray.Direction, ref currentDistanceFunctionValue); adjustedDistance = tDistance * distanceMultiplier; //Clamp the adjusted distance between the minimum and maximum steps adjustedDistance = FastMath.clamp(adjustedDistance, minimumRaymarchStep, maximumRaymarchStep); //Increment tpos by the adjusted distance tPosition += adjustedDistance; //Accidentally stepped over bounds, solve using bisection algorithm if(previousDistanceFunctionValue*currentDistanceFunctionValue < 0.0f) { SolveRootByBisection(ray, ref tMin, ref sr, tPositionPrevious, tPosition, RECURSIONDEPTH); return true; } tPositionPrevious = tPosition; previousDistanceFunctionValue = currentDistanceFunctionValue; } while (tPosition < t1 && tDistance > triggerDistance); //Hit if(tDistance < triggerDistance) { tMin = tPosition; sr.HitPointLocal = ray.Origin + tPosition * ray.Direction; sr.Normal = ApproximateNormal(sr.HitPointLocal, ray.Direction); sr.ObjectMaterial = _material; return true; } else { return false; } }
private bool ZeroExistsInInterval(Ray ray, float low, float high) { float f_low = EvaluateImplicitFunction(ray.Origin + ray.Direction * (float)low); float f_high = EvaluateImplicitFunction(ray.Origin + ray.Direction * (float)high); return (f_low * f_high) < 0.0f; }
private bool SolveRootByBisection(Ray ray, ref float tMin, ref ShadeRec sr, float lowBound, float highBound, int depth) { if(depth > 0) { //Find the mid point between the low and high bound float midbound; midbound = lowBound + ((highBound - lowBound) / 2.0f); if (ZeroExistsInInterval(ray, lowBound, midbound)) return SolveRootByBisection(ray, ref tMin, ref sr, lowBound, midbound, depth - 1); else if (ZeroExistsInInterval(ray, midbound, highBound)) return SolveRootByBisection(ray, ref tMin, ref sr, midbound, highBound, depth - 1); else { //Converged to correct location! tMin = lowBound; sr.HitPointLocal = ray.Origin + lowBound * ray.Direction; sr.Normal = ApproximateNormal(sr.HitPointLocal, ray.Direction); sr.ObjectMaterial = _material; return true; } } else { //Bottom of recursion stack, calculate relevant values tMin = lowBound; sr.HitPointLocal = ray.Origin + (float)lowBound * ray.Direction; sr.Normal = ApproximateNormal(sr.HitPointLocal, ray.Direction); sr.ObjectMaterial = sr.WorldPointer.MaterialList[0]; return true; } }
public override bool Hit(Ray r, float tmin) { float t = (_p - r.Origin) * _n / (r.Direction * _n); //Intersection is in front of camera if (t > GlobalVars.K_EPSILON && t < tmin) { return true; } //Intersection is behind camera return false; }
//Gets and sets /* public void setP(Point3D parg) { _p = parg; } public void setN(Normal narg) { _n = narg; } public Point3D getP() { return _p; } public Normal getN() { return _n; } */ /// <summary> /// Determines t value for intersection of plane and given ray, passes shading info back through sr; /// </summary> /// <param name="r">Ray to determine intersection</param> /// <param name="tmin">Passed by reference, minimum t value</param> /// <param name="sr">ShadeRec to store shading info in</param> /// <returns></returns> public override bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { float t = (_p - r.Origin) * _n / (r.Direction * _n); //Intersection is in front of camera if(t > GlobalVars.K_EPSILON && t < tmin) { tmin = t; sr.Normal = _n; sr.HitPointLocal = r.Origin + t * r.Direction; sr.ObjectMaterial = _material; return true; } //Intersection is behind camera else { return false; } }
public override bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { ///------------------------------------------------------------------------------------- /// same as colision code for axis aligned bounding box float ox = r.Origin.X; float oy = r.Origin.Y; float oz = r.Origin.Z; float dx = r.Direction.X; float dy = r.Direction.Y; float dz = r.Direction.Z; float tx_min, ty_min, tz_min; float tx_max, ty_max, tz_max; float a = 1.0f / dx; if (a >= 0.0) { tx_min = (x0 - ox) * a; tx_max = (x1 - ox) * a; } else { tx_min = (x1 - ox) * a; tx_max = (x0 - ox) * a; } float b = 1.0f / dy; if (b >= 0.0) { ty_min = (y0 - oy) * b; ty_max = (y1 - oy) * b; } else { ty_min = (y1 - oy) * b; ty_max = (y0 - oy) * b; } float c = 1.0f / dz; if (c >= 0.0) { tz_min = (z0 - oz) * c; tz_max = (z1 - oz) * c; } else { tz_min = (z1 - oz) * c; tz_max = (z0 - oz) * c; } ///code differs after this point ///-------------------------------------------------------------------------- /// float t0, t1; int face_in, face_out; //for handling both inside and outside collisions with box //Find the largest entering t value if(tx_min > ty_min) { t0 = tx_min; face_in = (a >= 0.0) ? 0 : 3; } else { t0 = ty_min; face_in = (b >= 0.0) ? 1 : 4; } if(tz_min > t0) { t0 = tz_min; face_in = (c >= 0.0) ? 2 : 5; } //Find the smallest exiting t value if(tx_max < ty_max) { t1 = tx_max; face_out = (a >= 0.0) ? 3 : 0; } else { t1 = ty_max; face_out = (b >= 0.0) ? 4 : 1; } if(tz_max < t1) { t1 = tz_max; face_out = (c >= 0.0) ? 5 : 2; } //Hit conditions if (t0 < t1 && t1 > GlobalVars.K_EPSILON) { if (t0 > GlobalVars.K_EPSILON) //Ray hits outside surface { tmin = t0; sr.Normal = GetNormal(face_in); } else//Ray hits inside surface { //Console.Write("hit inside"); tmin = t1; sr.Normal = GetNormal(face_out); } sr.HitPointLocal = r.Origin + tmin * r.Direction; sr.ObjectMaterial = _material; return true; } else return false; }
public virtual bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { return false; }
public virtual bool Hit(Ray r, float tmin) { return false; }
public override bool Hit(Ray r, float tmin) { //Calculate ray intersection with the Moller-Trumbore algorithm Vect3D e1, e2; //Edges Vect3D P, Q, T; float determinant, invDeterminant, u, v, t; e1 = Vertex2 - Vertex1; e2 = Vertex3 - Vertex1; //Vectors for the edges shared by vertex 1 P = r.Direction ^ e2; determinant = e1 * P; //Determinant calculation //If determinant is almost zero, then ray is parallel if (determinant > -GlobalVars.K_EPSILON && determinant < GlobalVars.K_EPSILON) { return false; } invDeterminant = 1.0f / determinant; //Distance from v1 to ray origin T = r.Origin - Vertex1; //U parameter calculation and test u = (T * P) * invDeterminant; //If u is negative or greater than 1, then intersection is outside of triangle if (u < 0.0 || u > 1.0) { return false; } Q = T ^ e1; //V parameter calculation and test v = (r.Direction * Q) * invDeterminant; //if v is negative or v+u is greater than 1, then intersection is outside of triangle if (v < 0.0 || u + v > 1.0) { return false; } t = e2 * Q * invDeterminant; if (t > GlobalVars.K_EPSILON && t < tmin) { return true; } else return false; }
public override void RenderScene(World w) { RGBColor L = new RGBColor(); Ray ray = new Ray(); ViewPlane vp = w.CurrentViewPlane; int depth = 0; Point2D sp = new Point2D(); Point2D pp = new Point2D(); Point2D dp = new Point2D(); Point2D lp = new Point2D(); //w.open_window(vp.hres, vp.vres); vp.PixelSize /= _zoom; for(int r = 0; r < vp.VerticalResolution-1; r++) { for(int c = 0; c < vp.HorizontalResolution-1; c++) { L = GlobalVars.COLOR_BLACK; for(int n = 0; n < vp.NumSamples; n++) { //Sample on unit square sp = vp.ViewPlaneSampler.SampleUnitSquare(); //Sample in screenspace pp.coords.X = vp.PixelSize * (c - vp.HorizontalResolution * 0.5f + sp.coords.X); pp.coords.Y = vp.PixelSize * (r - vp.VerticalResolution * 0.5f + sp.coords.Y); dp = depthSampler.SampleDisk(); lp.coords.X = dp.coords.X * radius; lp.coords.Y = dp.coords.Y * radius; ray.Origin = _eye + lp.coords.X * u + lp.coords.Y * v; ray.Direction = GetRayDirection(pp, lp); L += w.CurrentTracer.TraceRay(ray, depth); } L /= vp.NumSamples; L *= _exposureTime; w.DisplayPixel(r, c, L); w.PollEvents(); } } }
public override bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { //Calculate ray intersection with the Moller-Trumbore algorithm Vect3D edge1, edge2; //Edges Vect3D P, Q, T; float determinant, invDeterminant, u, v, t; edge1 = Vertex2 - Vertex1; edge2 = Vertex3 - Vertex1; //Vectors for the edges shared by vertex 1 P = r.Direction ^ edge2; determinant = edge1 * P; //Determinant calculation //If determinant is almost zero, then ray is parallel if(determinant > -GlobalVars.K_EPSILON && determinant < GlobalVars.K_EPSILON) { return false; } invDeterminant = 1.0f / determinant; //Distance from v1 to ray origin T = r.Origin - Vertex1; //U parameter calculation and test u = (T * P) * invDeterminant; //If u is negative or greater than 1, then intersection is outside of triangle if(u < 0.0 || u > 1.0) { return false; } Q = T ^ edge1; //V parameter calculation and test v = (r.Direction * Q) * invDeterminant; //if v is negative or v+u is greater than 1, then intersection is outside of triangle if(v < 0.0 || u+v > 1.0 ) { return false; } t = edge2 * Q * invDeterminant; if(t > GlobalVars.K_EPSILON && t < tmin) { //Ray hit something and intersection is in front of camera tmin = t; //Calculate normal, and ensure it's facing the direction that the ray came from Vect3D triNorm = (Vertex2 - Vertex1) ^ (Vertex3 - Vertex1); float triDotProd = triNorm * r.Direction; if(triDotProd < 0.0) { sr.Normal = new Normal(triNorm); } else { sr.Normal = new Normal(-triNorm); } sr.Normal.Normalize(); sr.HitPointLocal = r.Origin + t * r.Direction; sr.ObjectMaterial = _material; return true; } else { return false; } }
public override bool Hit(Ray r, ref float tMin, ref ShadeRec sr) { float t = GlobalVars.K_HUGE_VALUE; Normal normal = new Normal(); Point3D localHitPoint = new Point3D(); bool hit = false; tMin = GlobalVars.K_HUGE_VALUE; int countObjects = containedObjects.Count; Material closestObjectMaterial = null; //Traverse the list of renderable objects, and test for collisions in the same manner as in the world //hit function for(int i = 0; i < countObjects; i++) { if(containedObjects[i].Hit(r, ref t, ref sr) && (t<tMin)) { hit = true; tMin = t; closestObjectMaterial = sr.ObjectMaterial; normal = sr.Normal; localHitPoint = sr.HitPointLocal; } } if(hit) { sr.TMinimum = tMin; sr.Normal = normal; sr.HitPointLocal = localHitPoint; sr.ObjectMaterial = closestObjectMaterial; } return hit; }
public override bool Hit(Ray r, ref float tmin, ref ShadeRec sr) { //Apply inverse transformation to incident ray and test for intersection Ray tfRay = new Ray(r); tfRay.Origin = inverseNetTransformationMatrix * r.Origin; tfRay.Direction = inverseNetTransformationMatrix * r.Direction; if(payload.Hit(tfRay, ref tmin, ref sr)) { //Transform the computed normal into worldspace sr.Normal = inverseNetTransformationMatrix * sr.Normal; sr.Normal.Normalize(); if(_material != null) { sr.ObjectMaterial = _material; } return true; } else { return false; } }
/// <summary> /// Step 1 in rendering pipeline. /// Generic intersection detection for objectList called by a Tracer, returns ShadeRec describing intersection. /// </summary> /// <param name="ray">Ray for intersection calculation</param> /// <returns>ShadeRec object with all relevant information about object that was intersected for generating /// pixel data</returns> public ShadeRec HitObjects(Ray ray) { ShadeRec sr = new ShadeRec(this); // create shaderec // set normal and local hit point to non-null values Normal normal = new Normal(); Point3D local_hit_point = new Point3D(); float t = GlobalVars.K_HUGE_VALUE - 1.0f; // t value for corrent object float tmin = GlobalVars.K_HUGE_VALUE; // current lowest t value int num_objects = _renderList.Count; // store count of objects to minimize unecessary member access Material closestmat = null; // material reference for closest object //Find the closest intersection point along the given ray for(int i = 0; i < num_objects; i++) { // Intersect each object in render list // First term evaluated first, therefore (t < tmin) will be doing a comparison of t value // of present object vs minimum t value. if (_renderList[i].Hit(ray, ref t, ref sr) && (t < tmin)) { sr.HitAnObject = true; // at least one intersection has occurred // store temporary references to information about current object with minimum t tmin = t; closestmat = sr.ObjectMaterial; sr.HitPoint = ray.Origin + t * ray.Direction; // calculate hit point in world space by adding t*direction to origin normal = sr.Normal; local_hit_point = sr.HitPointLocal; } } //If we hit an object, store local vars for closest object with ray intersection in sr before returning if(sr.HitAnObject) { sr.TMinimum = tmin; sr.Normal = normal; sr.HitPointLocal = local_hit_point; sr.ObjectMaterial = closestmat; } return (sr); }
public override bool Hit(Ray r, float tmin) { //Apply inverse transformation to incident ray and test for intersection Ray tfRay = new Ray(r); tfRay.Origin = inverseNetTransformationMatrix * r.Origin; tfRay.Direction = inverseNetTransformationMatrix * r.Direction; if (payload.Hit(tfRay, tmin)) { return true; } else { return false; } }
public override bool InShadow(ShadeRec sr, Ray ray) { ShadeRec tempSr = sr.WorldPointer.HitObjects(ray); return tempSr.HitAnObject; }
public override bool Hit(Ray ray, ref float tMin, ref ShadeRec sr) { // // Code from Suffern (2007) // float ox = ray.Origin.X; float oy = ray.Origin.Y; float oz = ray.Origin.Z; float dx = ray.Direction.X; float dy = ray.Direction.Y; float dz = ray.Direction.Z; float x0 = _boundingBox.corner0.X; float y0 = _boundingBox.corner0.Y; float z0 = _boundingBox.corner0.Z; float x1 = _boundingBox.corner1.X; float y1 = _boundingBox.corner1.Y; float z1 = _boundingBox.corner1.Z; float tx_min, ty_min, tz_min; float tx_max, ty_max, tz_max; float a = 1.0f / dx; if(a >= 0) { tx_min = (x0 - ox) * a; tx_max = (x1 - ox) * a; } else { tx_min = (x1 - ox) * a; tx_max = (x0 - ox) * a; } float b = 1.0f / dy; if(b >= 0) { ty_min = (y0 - oy) * b; ty_max = (y1 - oy) * b; } else { ty_min = (y1 - oy) * b; ty_max = (y0 - oy) * b; } float c = 1.0f / dz; if(c >= 0) { tz_min = (z0 - oz) * c; tz_max = (z1 - oz) * c; } else { tz_min = (z1 - oz) * c; tz_max = (z0 - oz) * c; } //Determine if volume was hit float t0, t1; t0 = (tx_min > ty_min) ? tx_min : ty_min; if (tz_min > t0) t0 = tz_min; t1 = (tx_max < ty_max) ? tx_max : ty_max; if (tz_max < t1) t1 = tz_max; if(t0 > t1) { return false; } //Initial cell coordinates int ix, iy, iz; if(_boundingBox.inside(ray.Origin)) { ix = (int)Clamp((ox - x0) * nx / (x1 - x0), 0, nx - 1); //Get indices of ray origin if inside iy = (int)Clamp((oy - y0) * ny / (y1 - y0), 0, ny - 1); iz = (int)Clamp((oz - z0) * nz / (z1 - z0), 0, nz - 1); } else { Point3D p = ray.Origin + t0 * ray.Direction; ix = (int)Clamp((p.X - x0) * nx / (x1 - x0), 0, nx - 1); //Get indices of ray hitpoint if origin outside iy = (int)Clamp((p.Y - y0) * ny / (y1 - y0), 0, ny - 1); iz = (int)Clamp((p.Z - z0) * nz / (z1 - z0), 0, nz - 1); } //Get increments for ray marching float dtx = (tx_max - tx_min) / nx; float dty = (ty_max - ty_min) / ny; float dtz = (tz_max - tz_min) / nz; float tx_next, ty_next, tz_next; int ix_step, iy_step, iz_step; int ix_stop, iy_stop, iz_stop; if(dx > 0) { tx_next = tx_min + (ix + 1) * dtx; ix_step = 1; ix_stop = nx; } else { tx_next = tx_min + (nx - ix) * dtx; ix_step = -1; ix_stop = -1; } //Avoid divide by zero error if(dx == 0.0) { tx_next = GlobalVars.K_HUGE_VALUE; ix_step = -1; ix_stop = -1; } if(dy > 0) { ty_next = ty_min + (iy + 1) * dty; iy_step = 1; iy_stop = ny; } else { ty_next = ty_min + (ny - iy) * dty; iy_step = -1; iy_stop = -1; } //Avoid divide by zero error if(dy == 0.0) { ty_next = GlobalVars.K_HUGE_VALUE; iy_step = -1; iy_stop = -1; } if(dz > 0) { tz_next = tz_min + (iz + 1) * dtz; iz_step = +1; iz_stop = nz; } else { tz_next = tz_min + (nz - iz) * dtz; iz_step = -1; iz_stop = -1; } //Avoid divide by zero error if(dz == 0.0) { tz_next = GlobalVars.K_HUGE_VALUE; iz_step = -1; iz_stop = -1; } //Traverse grid while(true) { RenderableObject objectPointer = cells[ix + (nx * iy) + (nx * ny * iz)]; //Is the next cell an increment in the x direction? if(tx_next < ty_next && tx_next < tz_next) { //Hit an object in this cell, cull cells behind this object if ((objectPointer != null) && objectPointer.Hit(ray, ref tMin, ref sr) && tMin < tx_next) { //mat = object_ptr.getMaterial(); return true; } //Walk the ray to the next cell tx_next += dtx; ix += ix_step; //Havn't hit anything in the volume at all? if(ix == ix_stop) { return false; } } //Next cell is either an increment in y or z direction else { //Next cell is in the y direction if(ty_next < tz_next) { //Hit an object in this cell? Cull cells behind object if (objectPointer != null && objectPointer.Hit(ray, ref tMin, ref sr) && tMin < ty_next) { //mat = object_ptr.getMaterial(); return true; } //Walk the ray to the next cell ty_next += dty; iy += iy_step; //Havn't hit anything in the volume? if(iy == iy_stop) { return false; } } //Next cell is in the z direction else { //Hit an object in this cell? Cull cells behind object if (objectPointer != null && objectPointer.Hit(ray, ref tMin, ref sr) && tMin < tz_next) { //mat = object_ptr.getMaterial(); return true; } //Walk the ray to the next cell tz_next += dtz; iz += iz_step; //Havn't hit anything in the volume? if(iz == iz_stop) { return false; } } } } }