Example #1
0
        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;
                }
            }
        }
Example #2
0
        /// <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.
        }
Example #3
0
        /// <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();
                }
            }
        }
Example #4
0
        /// <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();
        }
Example #5
0
        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;
        }
Example #6
0
 public virtual bool InShadow(ShadeRec sr, Ray ray)
 {
     return false;
 }
Example #7
0
 public override RGBColor TraceRay(Ray ray, int depth)
 {
     return TraceRay(ray);
 }
Example #8
0
        /// <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();
        }
Example #9
0
        /// <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;
        }
Example #10
0
 public override RGBColor TraceRay(Ray ray)
 {
     throw new NotImplementedException();
 }
Example #11
0
 public override RGBColor TraceRay(Ray ray, float tMin, int depth)
 {
     throw new NotImplementedException();
 }
Example #12
0
        //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;
        }
Example #13
0
        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;
     }
 }
Example #17
0
        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;
        }
Example #18
0
        //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;
            }
        }
Example #19
0
        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;
        }
Example #20
0
 public virtual bool Hit(Ray r, ref float tmin, ref ShadeRec sr)
 {
     return false;
 }
Example #21
0
 public virtual bool Hit(Ray r, float tmin)
 {
     return false;
 }
Example #22
0
        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;
        }
Example #23
0
        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();
                }
            }
        }
Example #24
0
        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;
        }
Example #26
0
        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;
            }
        }
Example #27
0
        /// <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);
        }
Example #28
0
        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;
            }
        }
Example #29
0
 public override bool InShadow(ShadeRec sr, Ray ray)
 {
     ShadeRec tempSr = sr.WorldPointer.HitObjects(ray);
     return tempSr.HitAnObject;
 }
Example #30
0
        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;
                        }
                    }
                }
            }
        }