Пример #1
0
        // Returns index of triangle most frequently intersected by random rays along lightfield cell's beam
        // Returns -1 if no triangle is intersected
        private int BeamTriangleComplexIntersect(Coord4D lfCoord, RenderContext context)
        {
            var triCount = new Dictionary <int, short>();

            for (int i = 0; i < 100; i++)
            {
                const double bias      = +0.5;
                Float4D      randCoord = new Float4D(
                    lfCoord.Item1 + random.NextDouble() + bias,
                    lfCoord.Item2 + random.NextDouble() + bias,
                    lfCoord.Item3 + random.NextDouble() + bias,
                    lfCoord.Item4 + random.NextDouble() + bias);

                // switch to tracing the canonical ray associated with this lightfield entry, instead of the original ray (to avoid biasing values in lightfield)
                Vector cellRayStart;
                Vector cellRayDir;
                lightFieldCache.Float4DToRay(randCoord, out cellRayStart, out cellRayDir);

                // TODO: once the light field cache 'fills up', do we cease tracing rays? Prove/measure this!

                // trace a primary ray against all triangles in scene
                // TODO: trace multiple rays to find the triangle with largest cross-section in the beam corresponding to this lightfield cell?
                // This may also avoid incorrectly storing 'missing triangle' value when primary ray misses because there are no triangles along central axis of cell's beam.
                IntersectionInfo intersection = geometry_subdivided.IntersectRay(cellRayStart, cellRayDir, context);
                if (null != intersection)
                {
                    var triIndex = intersection.triIndex;

                    Contract.Assert(triIndex >= 0);
                    if (triCount.ContainsKey(triIndex))
                    {
                        triCount[triIndex]++;
                    }
                    else
                    {
                        triCount[triIndex] = 1;
                    }
                }
            }

            if (triCount.Count == 0)
            {
                return(-1);
            }
            else
            {
                // find tri index that occurs most often
                var maxCount = triCount.Max(x => x.Value);
                return(triCount.First(x => x.Value == maxCount).Key);
            }
        }
Пример #2
0
        /// <summary>
        /// Convert a 4D coordinate within the light field, to a ray travelling from first spherical point to second spherical point.
        /// </summary>
        /// <param name="coord4D">4D coordinate within the light field</param>
        /// <param name="start">The first point on the sphere</param>
        /// <param name="dir">The vector from the first to second points on the sphere</param>
        public void Float4DToRay(Float4D coord4D, out Vector start, out Vector dir)
        {
            Contract.Requires(coord4D != null);
            Contract.Requires(coord4D.Item1 < cacheRes * 2);
            Contract.Requires(coord4D.Item2 < cacheRes);
            Contract.Requires(coord4D.Item3 < cacheRes * 2);
            Contract.Requires(coord4D.Item4 < cacheRes);
            Contract.Ensures(!Contract.ValueAtReturn(out dir).IsZeroVector);

            // generate the canonical ray associated with this lightfield entry
            double maxValueUandS = cacheRes * 2 /*- 1*/;
            double maxValueVandT = cacheRes /*- 1*/;
            var    u             = ((coord4D.Item1 /*+ 0.5*/) / maxValueUandS - 0.5) * Math.PI * 2; // [-π, π]
            var    v             = ((coord4D.Item2 /*+ 0.5*/) / maxValueVandT - 0.5) * Math.PI;     // [-π/2, π/2]
            var    s             = ((coord4D.Item3 /*+ 0.5*/) / maxValueUandS - 0.5) * Math.PI * 2; // [-π, π]
            var    t             = ((coord4D.Item4 /*+ 0.5*/) / maxValueVandT - 0.5) * Math.PI;     // [-π/2, π/2]

            Sphere.LatLong spherePt1 = new Sphere.LatLong(u, v);
            Sphere.LatLong spherePt2 = new Sphere.LatLong(s, t);
            boundingSphere.ConvertLine(spherePt1, spherePt2, out start, out dir);
            dir = dir - start;
        }
Пример #3
0
        // TODO: is this method multi-thread safe?
        // cache ray colors in a 4D light field
        private uint CalcColorForRay(Vector rayStart, Vector rayDir, RenderContext context)
        {
            // TODO: do we need locking to ensure another thread does not overwrite lightfield cache entry(s)?

            if (!Interpolate)
            {
                // no interpolation
                Coord4D lfCoord = null;

                // Convert ray to 4D spherical coordinates
                // TODO: do we need locking to ensure another thread does not overwrite this lightfield cache entry?
                lfCoord = lightFieldCache.RayToCoord4D(ref rayStart, ref rayDir);
                if (lfCoord == null)
                {
                    return(backgroundColor);
                }

                return(CalcColorForCoord(lfCoord, context));
            }
            else
            {
                // quad-linear interpolation

                // Convert ray to 4D spherical coordinates
                Float4D lfFloat4D = lightFieldCache.RayToFloat4D(ref rayStart, ref rayDir);
                if (lfFloat4D == null)
                {
                    return(backgroundColor);
                }

                // this linearly interpolates lightfield colours along all four axes
                Coord4D coord      = new Coord4D((byte)lfFloat4D.Item1, (byte)lfFloat4D.Item2, (byte)lfFloat4D.Item3, (byte)lfFloat4D.Item4);
                double  uFrac      = lfFloat4D.Item1 - coord.Item1;
                double  vFrac      = lfFloat4D.Item2 - coord.Item2;
                double  sFrac      = lfFloat4D.Item3 - coord.Item3;
                double  tFrac      = lfFloat4D.Item4 - coord.Item4;
                Color   finalColor = new Color();
                for (byte u = 0; u <= 1; u++)
                {
                    var uFactor = (u == 1 ? uFrac : 1 - uFrac);
                    for (byte v = 0; v <= 1; v++)
                    {
                        var vFactor = (v == 1 ? vFrac : 1 - vFrac);
                        for (byte s = 0; s <= 1; s++)
                        {
                            var sFactor = (s == 1 ? sFrac : 1 - sFrac);
                            for (byte t = 0; t <= 1; t++)
                            {
                                Coord4D newCoord = new Coord4D(
                                    (byte)((coord.Item1 + u) % uRes),
                                    (byte)((coord.Item2 + v) % vRes),
                                    (byte)((coord.Item3 + s) % sRes),
                                    (byte)((coord.Item4 + t) % tRes));
                                var color = new Color(CalcColorForCoord(newCoord, context));
                                finalColor += color * uFactor * vFactor * sFactor * (t == 1 ? tFrac : 1 - tFrac);
                            }
                        }
                    }
                }
                return(finalColor.ToARGB());
            }
        }