예제 #1
0
        /// standard object services ---------------------------------------------------
        public Scene(StreamReader infile, Vector eyePosition)
        {
            // read and condition default sky and ground values
            skyEmission = new Vector(infile);
            groundReflection = new Vector(infile);

            skyEmission = skyEmission.Clamp(Vector.ZERO, skyEmission);
            groundReflection = skyEmission * groundReflection.Clamp(Vector.ZERO, Vector.ONE);
            triangles = new List<Triangle>();
            emitters = new List<Triangle>();

            // read objects
            while (infile.EndOfStream == false)
                {
                Triangle t = new Triangle(infile);
                if (t.Area != 0)
                    triangles.Add(t);
                }

            // find emitting triangles
            foreach (Triangle t in triangles)
                {
                if (!t.Emitivity.IsZero() && (t.Area > 0.0f))
                    {
                    emitters.Add(t);
                    if (emitters.Count >= (1 << MAX_EMITTERS_P))
                        break;
                    }
                }

            // make index
            octtree = new Spatial(eyePosition, triangles);
        }
예제 #2
0
		/// standard object services ---------------------------------------------------
		public Camera(StreamReader infile)
			{
			// read and condition view definition

			ViewPosition = new Vector(infile);
			viewDirection = new Vector(infile);
			viewAngle = infile.ReadFloat();

			viewDirection = viewDirection.Unitize();
			if (viewDirection.IsZero())
				viewDirection = new Vector(0.0f, 0.0f, 1.0f);

			if (viewAngle < 10) viewAngle = 10;
			if (viewAngle > 160) viewAngle = 160;
			viewAngle *= (float)(Math.PI / 180);

			// make other directions of frame
			up = new Vector(0.0f, 1.0f, 0.0f);
			right = up.Cross(viewDirection).Unitize();

			if (!right.IsZero())
				up = viewDirection.Cross(right).Unitize();
			else
				{
				up = new Vector(0.0f, 0.0f, viewDirection[1] < 0.0f ? 1.0f : -1.0f);
				right = up.Cross(viewDirection).Unitize();
				}
			} // Camera
예제 #3
0
 public Vector GetDefaultEmission(Vector backDirection)
 {
     // sky for downward ray, ground for upward ray
     if (backDirection[1] < 0)
         return skyEmission;
     return groundReflection;
 }
예제 #4
0
        Triangle[] triangles = null; // isBranch = false

        #endregion Fields

        #region Constructors

        public Spatial(Vector eyePosition, List<Triangle> items)
        {
            // set overall bound
            // accommodate eye position
            // (makes tracing algorithm simpler)
            for (int i = 6; i-- > 0; bound[i] = eyePosition[i % 3]) ;

            // accommodate all items
            foreach (Triangle item in items)
            {
                float[] itemBound = item.GetBound();

                // accommodate item
                for (int j = 0; j < 6; ++j)
                {
                    if ((bound[j] > itemBound[j]) ^ (j > 2))
                        bound[j] = itemBound[j];
                }
            }

            // make cubical
            float maxSize = 0.0f;
            for (int i = 0; i < 3; ++i)
                maxSize = Math.Max(maxSize, bound[3 + i] - bound[i]);
            for (int i = 0; i < 3; ++i)
                bound[3 + i] = Math.Max(bound[3 + i], bound[i] + maxSize);

            // make cell tree
            Construct(items, 0);
        }
예제 #5
0
        /// <summary>
        /// Create image based on size from stream
        /// </summary>
        /// <param name="infile"></param>
        public Image(int w , int h)
        {
            // read width and height
            Width = w;
            Height = h;

            // clamp width and height
            Width = Width < 1 ? 1 : (Width > 10000 ? 10000 : Width);
            Height = Height < 1 ? 1 : (Height > 10000 ? 10000 : Height);

            pixels = new Vector[Width, Height];
            for (int i = 0; i < Width; ++i)
                for (int j = 0; j < Height; ++j)
                    pixels[i, j] = new Vector();
        }
예제 #6
0
        /// <summary>
        /// Create image based on size from stream
        /// </summary>
        /// <param name="infile"></param>
        public Image(StreamReader infile)
        {
            // read width and height
            Width = (int)infile.ReadFloat();
            Height = (int)infile.ReadFloat();

            // clamp width and height
            Width = Width < 1 ? 1 : (Width > 10000 ? 10000 : Width);
            Height = Height < 1 ? 1 : (Height > 10000 ? 10000 : Height);

            pixels = new Vector[Width, Height];
            for (int i = 0; i < Width; ++i)
                for (int j = 0; j < Height; ++j)
                    pixels[i, j] = new Vector();
        }
예제 #7
0
        Vector SampleEmitters(Vector rayDirection, SurfacePoint surfacePoint, Sampler random)
        {
            Vector radiance;

            // single emitter sample, ideal diffuse BRDF:
            // reflected = (emitivity * solidangle) * (emitterscount) *
            // (cos(emitdirection) / pi * reflectivity)
            // -- SurfacePoint does the first and last parts (in separate methods)

            // get position on an emitter
            Vector emitterPosition;
            Triangle emitter;
            scene.GetEmitter(random, out emitterPosition, out emitter);

            // check an emitter was found
            if (null != emitter)
            {
                // make direction to emit point
                Vector emitDirection = (emitterPosition - surfacePoint.Position).Unitize();

                // send shadow ray
                Triangle hitObject;
                Vector hitPosition;
                scene.GetIntersection(surfacePoint.Position, emitDirection, surfacePoint.Item, out hitObject, out hitPosition);
                StatsCounter.RayTraced();

                // if unshadowed, get inward emission value
                Vector emissionIn = null;
                if ((null == hitObject) || (emitter == hitObject))
                    emissionIn = new SurfacePoint(emitter, emitterPosition).GetEmission(surfacePoint.Position, -emitDirection, true);
                else
                    emissionIn = new Vector();

                // get amount reflected by surface
                radiance = surfacePoint.GetReflection(emitDirection, emissionIn * scene.GetEmittersCount(), -rayDirection);
            }
            else
                radiance = new Vector();

            return radiance;
        }
예제 #8
0
        public Vector GetRadiance(Vector rayOrigin, Vector rayDirection, Sampler random, Triangle lastHit)
        {
            // intersect ray with scene
            Triangle pHitObject;
            Vector hitPosition;
            scene.GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition);

            Vector radiance;
            if (null != pHitObject)
            {
                // make surface point of intersection
                SurfacePoint surfacePoint = new SurfacePoint(pHitObject, hitPosition);

                // local emission only for first-hit
                if (lastHit != null)
                    radiance = Vector.ZERO;
                else
                    radiance = surfacePoint.GetEmission(rayOrigin, -rayDirection, false);

                // add emitter sample
                radiance = radiance + SampleEmitters(rayDirection, surfacePoint, random);

                // add recursive reflection
                //
                // single hemisphere sample, ideal diffuse BRDF:
                // reflected = (inradiance * pi) * (cos(in) / pi * color) * reflectance
                // -- reflectance magnitude is 'scaled' by the russian roulette, cos is
                // importance sampled (both done by SurfacePoint), and the pi and 1/pi
                // cancel out
                Vector nextDirection;
                Vector color;
                // check surface bounces ray, recurse
                if (surfacePoint.GetNextDirection(random, -rayDirection, out nextDirection, out color))
                    radiance = radiance + (color * GetRadiance(surfacePoint.Position, nextDirection, random, surfacePoint.Item));
            }
            else // no hit: default/background scene emission
                radiance = scene.GetDefaultEmission(-rayDirection);

            return radiance;
        }
예제 #9
0
        /// <summary>
        /// Construct a new triangle from a stream
        /// </summary>
        /// <param name="infile"></param>
        public Triangle(StreamReader infile)
        {
            // read three geometry points
            verts[0] = new Vector(infile);
            verts[1] = new Vector(infile);
            verts[2] = new Vector(infile);

            // read and condition quality
            Reflectivity = new Vector(infile).Clamp(Vector.ZERO, Vector.ONE);

            Emitivity = new Vector(infile).Clamp(Vector.ZERO, Vector.MAX);

            MaterialId = infile.ReadInt();

            // some item caching
            edge1 = verts[1] - verts[0];
            edge2 = verts[2] - verts[0];

            // make area, Tangent, normal, deltas
            MakeTangent();
            MakeNormal();
            MakeArea();
        }
예제 #10
0
 public Vector Clamp(Vector min, Vector max)
 {
     float xn = Math.Min(Math.Max(x, min.x), max.x);
     float yn = Math.Min(Math.Max(y, min.y), max.y);
     float zn = Math.Min(Math.Max(z, min.z), max.z);
     return new Vector(xn, yn, zn);
 }
예제 #11
0
        float CalculateToneMapping(Vector[,] pixels, float divider)
        {
            // calculate log mean luminance
            float logMeanLuminance = 1e-4f;

            float sumOfLogs = 0.0f;
            foreach (Vector p in pixels)
                {
                float Y = p.Dot(RGB_LUMINANCE) * divider;
                sumOfLogs += (float)Math.Log10(Y > 1e-4f ? Y : 1e-4f);
                }

            logMeanLuminance = (float)Math.Pow(10.0f, sumOfLogs / pixels.Length);

            // (what do these mean again? (must check the tech paper...))
            float a = 1.219f + (float)Math.Pow(DISPLAY_LUMINANCE_MAX * 0.25f, 0.4f);
            float b = 1.219f + (float)Math.Pow(logMeanLuminance, 0.4f);

            return (float)Math.Pow(a / b, 2.5f) / DISPLAY_LUMINANCE_MAX;
        }
예제 #12
0
 public void AddToPixel(int x, int y, Vector radiance)
 {
     #if PARALLEL
     lock (locker)
     #endif
     pixels[x, Height - 1 - y] += radiance;
 }
예제 #13
0
 void MakeTangent()
 {
     if (Tangent == null)
         Tangent = (verts[1] - verts[0]).Unitize();
 }
예제 #14
0
        /*
         * @implementation
         * Adapted from:
         * <cite>'Fast, Minimum Storage Ray-Triangle Intersection'
         * Moller, Trumbore;
         * Journal Of Graphics Tools, v2n1p21, 1997.
         * http://www.acm.org/jgt/papers/MollerTrumbore97/</cite>
         */
        public bool GetIntersection(Vector rayOrigin, Vector rayDirection, ref float hitDistance)
        {
            // begin calculating determinant - also used to calculate U parameter
            Vector pvec = rayDirection.Cross(edge2);

            // if determinant is near zero, ray lies in plane of triangle
            float det = edge1.Dot(pvec);

            const float EPSILON = 0.000001f;
            if ((det > -EPSILON) && (det < EPSILON))
                return false;

            float inv_det = 1.0f / det;

            // calculate distance from vertex 0 to ray origin
            Vector tvec = rayOrigin - verts[0];

            // calculate U parameter and test bounds
            float u = tvec.Dot(pvec) * inv_det;
            if ((u < 0.0f) || (u > 1.0f))
                return false;

            // prepare to test V parameter
            Vector qvec = tvec.Cross(edge1);

            // calculate V parameter and test bounds
            float v = rayDirection.Dot(qvec) * inv_det;
            if ((v < 0.0f) || (u + v > 1.0f))
                return false;

            // calculate t, ray intersects triangle
            hitDistance = edge2.Dot(qvec) * inv_det;

            // only allow intersections in the forward ray direction
            return hitDistance >= 0.0f;
        }
예제 #15
0
 /// <summary>
 /// Copy constructor
 /// </summary>
 public Vector(Vector a)
 {
     x = a.x;
     y = a.y;
     z = a.z;
 }
예제 #16
0
 public float Dot(Vector v)
 {
     return (x * v.x) + (y * v.y) + (z * v.z);
 }
예제 #17
0
        public void GetEmitter(Sampler random, out Vector position, out Triangle triangle)
        {
            if (emitters.Count != 0)
                {
                // select emitter
                // not using lower bits, by treating the random as fixed-point i.f bits
                int index = ((((int)(int.MaxValue*random.GetNextSample()) & ((1 << MAX_EMITTERS_P) - 1)) * emitters.Count) >> MAX_EMITTERS_P);

                // get position on triangle
                position = emitters[index].GetSamplePoint(random);
                triangle = emitters[index];
                }
            else
                {
                position = Vector.ZERO;
                triangle = null;
                }
        }
예제 #18
0
        public void GetIntersection(
            Vector rayOrigin, Vector rayDirection, Triangle lastHit,
            out Triangle pHitObject, out Vector hitPosition, Vector pStart)
        {
            hitPosition = null;
            pHitObject = null;
            // is branch: step through subcells and recurse
            if (isBranch)
            {
                if (pStart == null)
                    pStart = rayOrigin;

                // find which subcell holds ray origin (ray origin is inside cell)
                int subCell = 0;
                for (int i = 3; i-- > 0; )
                {
                    // compare dimension with center
                    if (pStart[i] >= ((bound[i] + bound[i + 3]) * 0.5f))
                        subCell |= 1 << i;
                }

                // step through intersected subcells
                Vector cellPosition = new Vector(pStart);
                for (; ; )
                {
                    if (null != spatial[subCell])
                    {
                        // intersect subcell
                        spatial[subCell].GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition, cellPosition);
                        // exit if item hit
                        if (null != pHitObject)
                            break;
                    }

                    // find next subcell ray moves to
                    // (by finding which face of the corner ahead is crossed first)
                    int axis = 2;
                    float[] step = new float[3]; // todo - move this allocation?
                    for (int i = 3; i-- > 0; axis = step[i] < step[axis] ? i : axis)
                    {
                        bool high = ((subCell >> i) & 1) != 0;
                        float face = (rayDirection[i] < 0.0f) ^ high ? bound[i + ((high ? 1 : 0) * 3)] : (bound[i] + bound[i + 3]) * 0.5f;
                        // distance to face
                        // (div by zero produces infinity, which is later discarded)
                        step[i] = (face - rayOrigin[i]) / rayDirection[i];
                    }

                    // leaving branch if: subcell is low and direction is negative,
                    // or subcell is high and direction is positive
                    if ((((subCell >> axis) & 1) != 0) ^ (rayDirection[axis] < 0.0f))
                        break;

                    // move to (outer face of) next subcell
                    cellPosition = rayOrigin + (rayDirection * step[axis]);
                    subCell = subCell ^ (1 << axis);
                }
            }
            else
            { // is leaf: exhaustively intersect contained items
                float nearestDistance = float.MaxValue;

                // step through items
                foreach (Triangle item in triangles)
                {
                    // avoid false intersection with surface just come from
                    if (item != lastHit)
                    {
                        // intersect ray with item, and inspect if nearest so far
                        float distance = float.MaxValue;
                        if (item.GetIntersection(rayOrigin, rayDirection, ref distance) && (distance < nearestDistance))
                        {
                            // check intersection is inside cell bound (with tolerance)
                            Vector hit = rayOrigin + (rayDirection * distance);
                            float t = Triangle.TOLERANCE;
                            if ((bound[0] - hit[0] <= t) && (hit[0] - bound[3] <= t) &&
                                (bound[1] - hit[1] <= t) && (hit[1] - bound[4] <= t) &&
                                (bound[2] - hit[2] <= t) && (hit[2] - bound[5] <= t))
                            {
                                pHitObject = item;
                                nearestDistance = distance;
                                hitPosition = hit;
                            }
                        }
                    }
                }
            }
        }
예제 #19
0
        public static Vector Unitize(Vector v)
        {
            float length = (float)Math.Sqrt((v.x * v.x) + (v.y * v.y) + (v.z * v.z));
            if (length == 0)
                return Vector.ZERO;
            float inv = 1.0f / length;

            return new Vector(v.x * inv, v.y * inv, v.z * inv);
        }
예제 #20
0
 public static float Dot(Vector u, Vector v)
 {
     return (u.x * v.x) + (u.y * v.y) + (u.z * v.z);
 }
예제 #21
0
 public static Vector Cross(Vector u, Vector v)
 {
     return new Vector((u.y * v.z) - (u.z * v.y),
                      (u.z * v.x) - (u.x * v.z),
                      (u.x * v.y) - (u.y * v.x));
 }
예제 #22
0
 public Vector Cross(Vector v)
 {
     return new Vector((y * v.z) - (z * v.y),
                      (z * v.x) - (x * v.z),
                      (x * v.y) - (y * v.x));
 }
예제 #23
0
        public void GetIntersection(
		   Vector rayOrigin, Vector rayDirection, Triangle lastHit,
		   out Triangle pHitObject, out Vector hitPosition)
        {
            octtree.GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition, null);
        }