Пример #1
0
        //Sphere constructor
        public Cube(Vector3 frontFloor, float h, float w, float d)
        {
            planes = new List<GeometricObject>();

            hitTri = new Triangle();

            frontFloorPoint = frontFloor;
            height = h;
            width = w;
            depth = d;

            frontTopPoint = frontFloorPoint - new Vector3(0, height, 0);

            leftFloorPoint = new Vector3(frontFloorPoint.X - width, frontFloorPoint.Y, frontFloorPoint.Z + depth);
            backFloorPoint = new Vector3(frontFloorPoint.X, frontFloorPoint.Y, frontFloorPoint.Z + depth + depth);
            rightFloorPoint = new Vector3(frontFloorPoint.X + width, frontFloorPoint.Y, frontFloorPoint.Z + depth);

            leftTopPoint = leftFloorPoint - new Vector3(0, height, 0);
            backTopPoint = backFloorPoint - new Vector3(0, height, 0);
            rightTopPoint = rightFloorPoint - new Vector3(0, height, 0);
        }
Пример #2
0
 public virtual Vector3 NormalAtCube(Vector3 i, Vector3 from, Triangle tri)
 {
     throw new Exception("INTERSECTION NOT IMPLEMENTED!!!");
 }
Пример #3
0
        private Vector3 GetPixelColorFromTexture(Vector3 hp, Triangle hitShape){

            if (hitShape.Tag == "t3")
            {
                int i = 0;

            }

            KeyValuePair<Vector3,Vector2>[] posTex = new KeyValuePair<Vector3,Vector2>[3];
            posTex[0] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[0], hitShape.TextureCoords[0]);
            posTex[1] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[1], hitShape.TextureCoords[1]);
            posTex[2] = new KeyValuePair<Vector3,Vector2>(hitShape.Vertices[2], hitShape.TextureCoords[2]);


            Vector3 B1, B2;
            Vector2 C1, C2;
            Vector2 Offset;
            if (posTex[0].Key.Length() < posTex[1].Key.Length() && posTex[0].Key.Length() < posTex[2].Key.Length())
            {

                C1 = posTex[1].Value - posTex[0].Value;
                C2 = posTex[2].Value - posTex[0].Value;

                B1 = posTex[1].Key - posTex[0].Key;
                B2 = posTex[2].Key - posTex[0].Key;


                Offset = posTex[0].Value;

            }
            else if (posTex[1].Key.Length() < posTex[0].Key.Length() && posTex[1].Key.Length() < posTex[2].Key.Length())
            {
                C1 = posTex[0].Value - posTex[1].Value;
                C2 = posTex[2].Value - posTex[1].Value;

                B1 = posTex[0].Key - posTex[1].Key;
                B2 = posTex[2].Key - posTex[1].Key;
                Offset = posTex[1].Value;
            }
            else
            {
                C1 = posTex[1].Value - posTex[2].Value;
                C2 = posTex[0].Value - posTex[2].Value;

                B1 = posTex[1].Key - posTex[2].Key;
                B2 = posTex[0].Key - posTex[2].Key;
                Offset = posTex[2].Value;
            }

            float p1, p2;
            float a, b, c, d;

            if (hitShape.TCC == TextureCoordConst.Z)
            {
                a = B1.X; b = B2.X; c = B1.Y; d = B2.Y;
                p1 = hp.X; p2 = hp.Y;
            }
            else if (hitShape.TCC == TextureCoordConst.X)
            {
                a = B1.Z; b = B2.Z; c = B1.Y; d = B2.Y;
                p1 = hp.Z; p2 = hp.Y;
            }
            else if (hitShape.TCC == TextureCoordConst.Y)
            {
                a = B1.X; b = B2.X; c = B1.Z; d = B2.Z;
                p1 = hp.X; p2 = hp.Z;
            }
            else
            {
                throw new Exception("No Texture Coord Const set");
            }


            float det = 1 / (a * d - b * c);

            float alpha = d * p1 - b * p2;
            float beta = -c * p1 + a * p2;

            alpha *= det;
            beta *= det;

            Vector2 UV = alpha * C1 + beta * C2;

            UV += Offset;

            if (UV.X > 1) UV.X = 1;
            if (UV.Y > 1) UV.Y = 1;

            float xReal = UV.Y * hitShape.TextureToUse.TexSize.Y - 1;
            float yReal = UV.X * hitShape.TextureToUse.TexSize.X - 1;

            int x0 = (int)xReal, y0 = (int)yReal;

            float dx = xReal - x0, dy = yReal - y0, omdx = 1 - dx, omdy = 1 - dy;
            if (x0 < 1) x0 = 1;
            if (y0 < 1) y0 = 1;

            if (x0 == hitShape.TextureToUse.TexSize.Y - 1 || y0 == hitShape.TextureToUse.TexSize.X - 1 || x0 == 0 || y0 == 0) return hitShape.TextureToUse.TexturePixels[x0, y0];

            Vector3 color = omdx * omdy * hitShape.TextureToUse.TexturePixels[x0, y0] + omdx * dy * hitShape.TextureToUse.TexturePixels[x0, y0 - 1] + dx * omdy * hitShape.TextureToUse.TexturePixels[x0 - 1, y0] + dx * dy * hitShape.TextureToUse.TexturePixels[x0 - 1, y0 - 1];

            return color;


        }
Пример #4
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);
        }
Пример #5
0
 public override Vector3 NormalAtCube(Vector3 i, Vector3 from, Triangle tri)
 {
     if (tri.Normal.X != float.MaxValue) return tri.Normal;
     else return Vector3.Cross(tri.Vertices[0] - tri.Vertices[1], tri.Vertices[2] - tri.Vertices[1]);
 }
Пример #6
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) ;
        }