Beispiel #1
0
        public override double intersection(Ray ray)
        {
            Vector3 p0 = Vertices[0];
            Vector3 p1 = Vertices[2];
            Vector3 p2 = Vertices[1];

            Vector3 e1 = p1 - p0;
            Vector3 e2 = p2 - p0;

            Vector3 e1e2 = Vector3.Cross(e1, e2);
            Vector3 p = Vector3.Cross(ray.Direction, e2);

            e1e2.Normalize();

            float a = Vector3.Dot(e1e2, p);

            if (a < 0.000001) return 0.0;

            float f = 1.0f / a;

            Vector3 s = ray.Start - p0;

            float u = f * Vector3.Dot(s, p);

            if (u < 0.0 || u > 1.0) return 0.0;

            Vector3 q = Vector3.Cross(s, e1);
            float v = f * Vector3.Dot(ray.Direction, q);
            if (v < 0.0 || u + v > 1.0) return 0.0;

            float t = f * Vector3.Dot(e2, q);

            return t;
        }
Beispiel #2
0
        public override double intersection(Ray ray)
        {
            // sRay is the position of the eye/camera, dRay is the direction of the ray.
            // the new start and end of the ray for these calculations.
            Vector3 sRay = new Vector3();
            Vector3 dRay = ray.Direction;
            dRay.Normalize();

            //coefficients of quadratic equation, and discriminant
            double a, b, c, d, t;

            // transform ray to put sphere centre at origin to make calculations cleaner.
            sRay = ray.Start - position;

            a = Vector3.Dot(dRay, dRay);
            b = 2*Vector3.Dot(dRay, sRay);
            c = Vector3.Dot(sRay, sRay) - radius * radius;

            //Find discriminant
            d = b * b - 4 * a * c;

            // if discriminant < 0, then the ray did not intersect the object.
            if (d < 0.0)
            {
                return 0.0;
            }
            else
            {
                d = Math.Sqrt(d);

                // If there are one or two real values then chose the smallest,
                // non-negative value, as the intersection point.
                t = (-b - d) / (2.0 * a);

                if (t < INTERSECTION_TOLERANCE) t = (-b + d) / (2.0 * a);

                if (t < INTERSECTION_TOLERANCE) return 0.0;
                else return t;
            }
        }
        private Vector3 calcLightRay(Ray ray)
        {
            GeometricObject hitShape = null;
            double closestShape = float.MaxValue;

            foreach (GeometricObject shape in Shapes)
            {
                double t;
                if (shape is Cube)
                {
                    Tuple<double, Triangle> temp = shape.intersectionCube(ray);
                    t = temp.Item1;
                }
                else
                {
                    t = shape.intersection(ray);
                }

                if (t > 0.0 && t < closestShape)
                {
                    hitShape = shape;
                    closestShape = t;
                }
            }
            if (hitShape != null)
            {
                return FindPointOnRay(ray, closestShape);
            }
            else
                return new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
        }
        public void spawnVPL(Light light,float width,float height)
        {
            Random r = new Random();

            List<Vector3> virtualLightPositions = new List<Vector3>();
            for (int i = 0; i < NumVirtualLights/3; i++)
            {
                virtualLightPositions.Add(new Vector3(r.Next(0, (int)width), r.Next(0, (int)height/3), 0));
            }

            for (int i = 0; i < NumVirtualLights/3; i++)
            {
                virtualLightPositions.Add(new Vector3(r.Next(0, (int)width), r.Next((int)height/3, 2*(int)height/3), 0));
            }

            for (int i = 0; i < NumVirtualLights/3; i++)
            {
                virtualLightPositions.Add(new Vector3(r.Next(0, (int)width), r.Next(2 * (int)height / 3, (int)height), 0));
            }

            foreach (Vector3 VPLPos in virtualLightPositions)
            {
                Vector3 dir = (new Vector3(VPLPos.X, VPLPos.Y, 0)) - Eye;
                dir.Normalize();
                Ray ray = new Ray(Eye, dir);
                Vector3 newLightPos = calcLightRay(ray);
                SurfaceType hitSurface;

                if (newLightPos.X == float.MaxValue)
                {
                    continue;
                }
                else
                {
                    hitSurface = findSurfaceType(ray);
                }

                Vector3 dir2 = light.position - newLightPos;
                dir2.Normalize();

                Ray ray2 = new Ray(newLightPos, dir2);

                if (isVisible(light, VPLPos, ray2) <= 0)
                {
                    continue;
                }

                if (newLightPos.X != float.MaxValue && newLightPos.Y != float.MaxValue && newLightPos.Z != float.MaxValue)
                {
                    if (drawSpheres)
                    {
                        GeometricObject testSphere = new Sphere(ImageSize.Y / 32.0f, newLightPos, new Vector4(0, 0, 0, 255), new SurfaceType(textureType.standard,new Vector3(200, 100, 100), new Vector3(100, 40, 78), new Vector3(50, 50, 50), new Vector3(255, 255, 255), 0));
                        Shapes.Add(testSphere);
                    }
                    else
                    {
                        VirtualLights.Add(new Light()
                        {
                            position = newLightPos,
                            color = light.color,
                            intensity = (float)(1.0f / (float)NumVirtualLights)
                        });
                    }
                }
            }
        }
        private SurfaceType findSurfaceType(Ray ray)
        {
            GeometricObject hitShape = null;
            double closestShape = float.MaxValue;

            foreach (GeometricObject shape in Shapes)
            {
                double t;
                if (shape is Cube)
                {
                    Tuple<double, Triangle> temp = shape.intersectionCube(ray);
                    t = temp.Item1;
                }
                else
                {
                    t = shape.intersection(ray);
                }

                if (t > 0.0 && t < closestShape)
                {
                    hitShape = shape;
                    closestShape = t;
                }
            }
            if (hitShape != null)
            {
                return hitShape.surface;
            }
            else
                return null;
        }
Beispiel #6
0
        public override double intersection(Ray r)
        {
            float t = float.MaxValue;//(r.Direction.X * r.Direction.X + r.Direction.Y * r.Direction.Y + r.Direction.Z * r.Direction.Z);
            List<poly> polynomMap = new List<poly>();

            float rSquare, rInvSquare;
            rSquare = size * size;
            rInvSquare = invSizeSquare;
            float maxEstimatedPotential = 0.0f;

            float A = 0.0f;
            float B = 0.0f;
            float C = 0.0f;

            for (int i= 0; i< centerList.Count; i++)
            {
                Vector3 currentPoint = centerList[i];

                Vector3 vDist = currentPoint - r.Start;
                float aa = 1.0f;
                float bb = - 2.0f * (r.Direction.X*vDist.X + r.Direction.Y*vDist.Y + r.Direction.Z*vDist.Z);
                float cc = (vDist.X*vDist.X + vDist.Y*vDist.Y + vDist.Z*vDist.Z);

                float BSquareOverFourMinusC = 0.25f * bb * bb - cc;
                float MinusBOverTwo = -0.5f * bb;
                float ATimeInvSquare = aa * rInvSquare;
                float BTimeInvSquare = bb * rInvSquare;
                float CTimeInvSquare = cc * rInvSquare;

                for (int j=0; j < zoneNumber - 1; j++)
                {
                    float fDelta = BSquareOverFourMinusC + zoneTab[j].fCoef * rSquare;
                    if (fDelta < 0.0f)
                    {
                        break;
                    }
                    float sqrtDelta = (float)Math.Sqrt(fDelta);
                    float t0 = MinusBOverTwo - sqrtDelta;
                    float t1 = MinusBOverTwo + sqrtDelta;

                    poly poly0 = new poly(zoneTab[j].fGamma * ATimeInvSquare ,
                                  zoneTab[j].fGamma * BTimeInvSquare ,
                                  zoneTab[j].fGamma * CTimeInvSquare + zoneTab[j].fBeta,
                                  t0,
                                  zoneTab[j].fDeltaFInvSquare);
                    poly poly1 = new poly(- poly0.a, - poly0.b, - poly0.c,
                                  t1,
                                  -poly0.fDeltaFInvSquare);

                    maxEstimatedPotential += zoneTab[j].fDeltaFInvSquare;

                    polynomMap.Add(poly0);
                    polynomMap.Add(poly1);
                };
            }

            if (polynomMap.Count < 2 || maxEstimatedPotential < 1.0f)
            {
                return 0;
            }

            polynomMap.Sort((x, y) => x.isLess(y));

            maxEstimatedPotential = 0.0f;
            bool bResult = false;
            int it, itNext;

            for(it = 0, itNext = it+1; itNext < polynomMap.Count; it = itNext, itNext++)
            {
                A += polynomMap[it].a;
                B += polynomMap[it].b;
                C += polynomMap[it].c;
                maxEstimatedPotential += polynomMap[it].fDeltaFInvSquare;
                if (maxEstimatedPotential < 1.0f)
                {
                    continue;
                }
                float fZoneStart =  polynomMap[it].fDistance;
                float fZoneEnd = polynomMap[itNext].fDistance;

                if (t > fZoneStart &&  0.01f < fZoneEnd )
                {
                    float fDelta = B * B - 4.0f * A * (C - 1.0f) ;
                    if (fDelta < 0.0f)
                    {
                        continue;
                    }
                    if(A == 0) A = float.MinValue;
                    float fInvA = (0.5f / A);
                    float fSqrtDelta = (float)Math.Sqrt(fDelta);

                    float t0 = fInvA * (- B - fSqrtDelta);
                    float t1 = fInvA * (- B + fSqrtDelta);
                    if ((t0 > 0.01f ) && (t0 >= fZoneStart ) && (t0 < fZoneEnd) && (t0 <= t ))
                    {
                        t = t0;
                        bResult = true;
                    }

                    if ((t1 > 0.01f ) && (t1 >= fZoneStart ) && (t1 < fZoneEnd) && (t1 <= t ))
                    {
                        t = t1;
                        bResult = true;
                    }

                    if (bResult)
                    {
                        return t;
                    }
                }
            }
            return 0;
        }
 public virtual Tuple<double, Triangle> intersectionCube(Ray ray)
 {
     throw new Exception("INTERSECTIONCUBE NOT IMPLEMENTED!!!");
 }
 public virtual double intersection(Ray ray)
 {
     throw new Exception("INTERSECTION NOT IMPLEMENTED!!!");
 }
        // Find the point along the ray vector where the hit occurs.
        private Vector3 FindPointOnRay(Ray ray, double t)
        {

            Vector3 intersect;

            intersect.X = (float)(ray.Start.X + t * ray.Direction.X);
            intersect.Y = (float)(ray.Start.Y + t * ray.Direction.Y);
            intersect.Z = (float)(ray.Start.Z + t * ray.Direction.Z);

            return intersect;

        }
Beispiel #10
0
        private GeometricObject FindClosestShape(Ray r, Light l, GeometricObject theShape)
        {
            double dist = float.MaxValue;
            GeometricObject closest = null;

            foreach (GeometricObject shape in Shapes)
            {

                double t;
                if (shape is Cube)
                {
                    Tuple<double, Triangle> temp = shape.intersectionCube(r);
                    t = temp.Item1;
                }
                else
                {
                    t = shape.intersection(r);
                }
                if (theShape != shape && t < dist && t > 0.0f && shape.surface.RefractionIndex < 1)

                {
                    closest = shape;
                    dist = t;
                }
            }

            foreach (Light light in Lights)
            {
                if (light != l) continue;
                double t = light.intersection(r);
                if (light.intersection(r) < dist)
                {
                    closest = light;
                    dist = t;
                }

            }

            return closest;

        }
Beispiel #11
0
        private float isVisible(Light L, Vector3 hitPoint, Ray ray, GeometricObject theShape = null)
        {

            float retVal = 0.0f;
            float offset = 5;


            float numSegments = 1;
            float numAlongSegment = 1;

            Vector3 dir;
            Ray r;

            for (float i = 0; i <= 2 * Math.PI; i += 2.0f * (float)Math.PI / (numSegments))
            {

                for (float j = 1; j <= numAlongSegment; j++)
                {

                    dir = L.position + new Vector3((float)Math.Cos(i) * L.radius / j + offset * (Math.Cos(i) < 0 ? 1 : -1), (float)Math.Sin(i) * L.radius / j + offset * (Math.Sin(i) < 0 ? 1 : -1), 0);
                    dir = dir - ray.Start;
                    dir.Normalize();

                    r = new Ray(ray.Start, dir);

                    if (FindClosestShape(r, L, theShape) == L)
                        retVal += 1.0f / (numSegments * numAlongSegment);

                }
            }

            return Clamp(retVal, 0, 1);
            

        }
Beispiel #12
0
        /// <summary>
        /// Traces rays and calculates their color. Recursive method
        /// </summary>
        /// <param name="ray"></param>
        /// <param name="depth"></param>
        /// <param name="coef"></param>
        /// <param name="specOn">if at any point an object is not specular, all successive recursive calls will ignore specular</param>
        /// <returns></returns>
        private Vector3 AddRay(Ray ray, int depth, float coef, ref float prevDist, float lastRIndex = 1)
        {
            Vector3 curColor = new Vector3(0, 0, 0);
            GeometricObject hitShape = null;
            double hitShapeDist = float.MaxValue;
            Vector3 vNormal;
            Vector3 hp;
            float LightValue = 0.0f;

            Triangle hitTri = new Triangle();

            foreach (GeometricObject shape in Shapes)
            {
                if (shape == null) continue;

                double t;

                if (shape is Cube)
                {
                    Tuple<double, Triangle> temp = shape.intersectionCube(ray);
                    t = temp.Item1;
                    hitTri = temp.Item2;
                }
                else
                {
                    t = shape.intersection(ray);
                }

                if (t > 0.0 && t < hitShapeDist)
                {
                    hitShape = shape;
                    hitShapeDist = t;
                    prevDist = (float)t;
                }
            }

            if (hitShape == null)
            {
                if (depth == 0) return new Vector3(-1, -1, -1);
                else return new Vector3(0, 0, 0);
            }
            else
            {
                hp = FindPointOnRay(ray, hitShapeDist);

                if (hitShape is Cube)
                {
                    vNormal = hitShape.NormalAtCube(hp, Eye, hitTri);
                }
                else
                {

                    vNormal = hitShape.NormalAt(hp, Eye);
                }


                if (hitShape.surface.type == textureType.bump)
                {

                    const double bumpLevel = 0.2;
                    double noiseX = perlinTexture.noise(0.1 * (double)hp.X, 0.1 * (double)hp.Y, 0.1 * (double)hp.Z);
                    double noiseY = perlinTexture.noise(0.1 * (double)hp.Y, 0.1 * (double)hp.Z, 0.1 * (double)hp.X);
                    double noiseZ = perlinTexture.noise(0.1 * (double)hp.Z, 0.1 * (double)hp.X, 0.1 * (double)hp.Y);

                    vNormal.X = (float)((1.0 - bumpLevel) * vNormal.X + bumpLevel * noiseX);
                    vNormal.Y = (float)((1.0 - bumpLevel) * vNormal.Y + bumpLevel * noiseY);
                    vNormal.Z = (float)((1.0 - bumpLevel) * vNormal.Z + bumpLevel * noiseZ);

                    double temp = Vector3.Dot(vNormal, vNormal);
                    if (temp != 0.0)
                    {
                        temp = 1.0 / Math.Sqrt(temp);
                        vNormal = (float)temp * vNormal;
                    }
                }

                vNormal.Normalize();

            
                foreach (Light light in Lights)
                {
                    Vector3 dir = light.position - hp;
                    dir.Normalize();
                    Ray lightRay = new Ray(hp, dir);

                    if ((LightValue = isVisible(light, hp, lightRay)) > 0)
                    {

                        Vector3 color = new Vector3();

                        if (hitShape is Triangle)
                        {
                            if (((Triangle)hitShape).HasTexture)
                            {
                                color = GetPixelColorFromTexture(hp, hitShape as Triangle);
                            }
                            else
                            {
                                color = hitShape.surface.color;
                            }
                        }
                        else
                        {
                            color = hitShape.surface.color;
                        }


                        //TODO to add ambient just do Llight[ambient] * hitShape[ambiemt]
                        float lambert = Vector3.Dot(lightRay.Direction, vNormal) ;
                        curColor += light.intensity * lambert * ((light.color)) * (color) * coef;

                        Vector3 blinn = lightRay.Direction - ray.Direction;
                        blinn.Normalize();

                        float blinnValue = (float)Math.Pow(Math.Max(0, Vector3.Dot(vNormal, blinn)), hitShape.surface.SpecExponent);

                        curColor += hitShape.surface.specular * light.intensity * light.color * blinnValue * coef;

                        curColor *= LightValue;
                    }
                }

            }
            if (depth >= NumBounces) return Clamp(curColor);
            else
            {

                //calculate reflections
                Vector3 dir = ray.Direction - (2.0f * Vector3.Dot(ray.Direction, vNormal)) * vNormal;
                dir.Normalize();
                float UGH = 0;
                curColor += AddRay(new Ray(hp, dir), depth + 1, coef * ((float)hitShape.surface.reflectiveness / 100.0f), ref UGH);

                //calculate refraction (nigguh)
                float refr = hitShape.surface.RefractionIndex;
                if (refr > 0)
                {
                    float n = lastRIndex/refr;

                    float cos = Vector3.Dot(ray.Direction, vNormal);
                    float sin = (float)Math.Pow(n, 2) * (1 - (float)Math.Pow(cos,2));
                    if (Math.Pow(sin,2) <= 1)
                    {
                        Vector3 transmissiveDir = n * ray.Direction - (n * cos + (float)Math.Sqrt(1 - (float)Math.Pow(sin, 2))) * vNormal;
                        transmissiveDir.Normalize();
                        float dist = 0;
                        Vector3 theColor = AddRay(new Ray(hp, transmissiveDir), depth + 1, coef, ref dist, refr);

                        Vector3 absorbance = hitShape.surface.color * 0.0000015f * -dist;
                        Vector3 trans = new Vector3((float)Math.Exp(absorbance.X), (float)Math.Exp(absorbance.Y), (float)Math.Exp(absorbance.Z));


                        curColor += theColor * trans;

                    }
                }


            }
            return Clamp(curColor);
        }
Beispiel #13
0
        private async Task<byte[]> Trace(int width, int height)
        {

            string s = "0 =                                                                                                    100";

            // 4 bytes required for each pixel
            byte[] result = new byte[width * height * 4];
            int resultIndex = 0;

            float totalNum = width * height;

            Vector3 color = new Vector3(0, 0, 0);


            for (int y = 0; y < height; y++)
            {

                for (int x = 0; x < width; x++)
                {
                    color = new Vector3(0, 0, 0);

                   //if(y>ImageSize.Y / 2.0f  )
                        for (float innerPixelY = 1.0f / numInnerPixels; innerPixelY <= 1; innerPixelY += 1.0f / numInnerPixels)
                        {
                            for (float innerPixelX = 1.0f / numInnerPixels; innerPixelX <= 1; innerPixelX += 1.0f / numInnerPixels)
                            {

                                Vector3 dir = (new Vector3(x + (innerPixelX - (1.0f / numInnerPixels * 2.0f)), y + (innerPixelY - (1.0f / numInnerPixels * 2.0f)), 0)) - Eye;
                                dir.Normalize();
                                Ray ray = new Ray(Eye, dir);
                                float ThisVariableDoesAbsolutelyNothingInThisSpotButYouNeedItForTheRefVariable = 0;
                                color += AddRay(ray, 0, 1.0f, ref ThisVariableDoesAbsolutelyNothingInThisSpotButYouNeedItForTheRefVariable);


                            }
                        }


                    color /= (numInnerPixels * numInnerPixels);

                    color *= 255.0f;

                    if (color.X < 0 || color.Y < 0 || color.Z < 0)
                    {

                        color = new Vector3(0, 0, 0);

                    }

                    result[resultIndex++] = Convert.ToByte(color.Z);    // Green value of pixel
                    result[resultIndex++] = Convert.ToByte(color.Y);    // Blue value of pixel
                    result[resultIndex++] = Convert.ToByte(color.X);    // Red value of pixel
                    result[resultIndex++] = Convert.ToByte(255);        // Alpha value of pixel



                    float n = (((float)y) * height + x) / totalNum * 100;

                    if (n == (int)n)
                    {
                        if (!DontPornIt)
                        {
                            MainPage.d.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(async () =>
                            {
                                // Open a stream to copy the graph to the WriteableBitmap's pixel buffer
                                using (Stream stream = WB.PixelBuffer.AsStream())
                                {
                                    byte[] tempr = result;
                                    await stream.WriteAsync(tempr, 0, tempr.Length);
                                }

                                WB.Invalidate();
                            }));
                        }

                        s = s.Replace("= ", " =");

                        System.Diagnostics.Debug.WriteLine(s);
                    }



                }

            }
            return result;
        }
Beispiel #14
0
        public override Tuple<double, Triangle> intersectionCube(Ray ray)
        {
            float closest = float.PositiveInfinity;

            foreach (Triangle triangle in planes)
            {
                Vector3 p0 = triangle.Vertices[0];
                Vector3 p1 = triangle.Vertices[2];
                Vector3 p2 = triangle.Vertices[1];

                Vector3 e1 = p1 - p0;
                Vector3 e2 = p2 - p0;

                Vector3 p = Vector3.Cross(ray.Direction, e2);

                float a = Vector3.Dot(e1, p);

                if (a < 0.000001) continue;// return 0.0;

                float f = 1.0f / a;

                Vector3 s = ray.Start - p0;

                float u = f * Vector3.Dot(s, p);

                if (u < 0.0 || u > 1.0) continue;// return 0.0;

                Vector3 q = Vector3.Cross(s, e1);
                float v = f * Vector3.Dot(ray.Direction, q);
                if (v < 0.0 || u + v > 1.0) continue;// return 0.0;

                float t = f * Vector3.Dot(e2, q);

                //return t;
                if (t < closest)
                {
                    closest = t;
                    hitTri = triangle;
                }
            }

            if (closest < float.PositiveInfinity)
            {
                return new Tuple<double,Triangle>(closest,hitTri);
            }
            else
                return new Tuple<double, Triangle>(0.0, null) ;
        }