Exemple #1
0
        private void balance()
        {
            if (storedPhotons == 0)
            {
                return;
            }
            photons    = photonList.ToArray();
            photonList = null;

//			photons = Photon.BalancePhotons(ref photons);

            Photon[] temp = new Photon[storedPhotons + 1];
            balanceSegment(temp, 1, 1, storedPhotons);
            photons = temp;

            halfStoredPhotons = storedPhotons / 2;
            log2n             = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0));
        }
Exemple #2
0
        public static Photon[] BalancePhotons(ref Photon[] unbalanced)
        {
            SortedList<Int64, Photon> balanced = new SortedList<Int64, Photon>();

            BalancePhotons(balanced, 1, 1, unbalanced.Length-1, 1, ref unbalanced);

            int index=0;

            foreach(KeyValuePair<Int64, Photon> photon in balanced) {

                unbalanced[index++] = photon.Value;

            }

            balanced = null;

            return unbalanced;
        }
Exemple #3
0
        public void getSamples(ShadingState state)
        {
            if (storedPhotons == 0)
            {
                return;
            }
            NearestPhotons np = new NearestPhotons(state.getPoint(), gatherNum, gatherRadius * gatherRadius);

            locatePhotons(np);
            if (np.found < 8)
            {
                return;
            }
            Point3  ppos     = new Point3();
            Vector3 pdir     = new Vector3();
            Vector3 pvec     = new Vector3();
            float   invArea  = 1.0f / ((float)Math.PI * np.dist2[0]);
            float   maxNDist = np.dist2[0] * 0.05f;
            float   f2r2     = 1.0f / (filterValue * filterValue * np.dist2[0]);
            float   fInv     = 1.0f / (1.0f - 2.0f / (3.0f * filterValue));

            for (int i = 1; i <= np.found; i++)
            {
                Photon phot = np.index[i];
                Vector3.decode(phot.dir, pdir);
                float cos = -Vector3.dot(pdir, state.getNormal());
                if (cos > 0.001)
                {
                    ppos.set(phot.x, phot.y, phot.z);
                    Point3.sub(ppos, state.getPoint(), pvec);
                    float pcos = Vector3.dot(pvec, state.getNormal());
                    if ((pcos < maxNDist) && (pcos > -maxNDist))
                    {
                        LightSample sample = new LightSample();
                        sample.setShadowRay(new Ray(state.getPoint(), pdir.negate()));
                        sample.setRadiance(new Color().setRGBE(np.index[i].power).mul(invArea / cos), Color.BLACK);
                        sample.getDiffuseRadiance().mul((1.0f - (float)Math.Sqrt(np.dist2[i] * f2r2)) * fInv);
                        state.addSample(sample);
                    }
                }
            }
        }
 public void checkAddNearest(Photon p)
 {
     float fdist2 = p.getDist2(px, py, pz);
     if (fdist2 < dist2[0])
     {
         if (found < max)
         {
             found++;
             dist2[found] = fdist2;
             index[found] = p;
         }
         else
         {
             int j;
             int parent;
             if (!gotHeap)
             {
                 float dst2;
                 Photon phot;
                 int halfFound = found >> 1;
                 for (int k = halfFound; k >= 1; k--)
                 {
                     parent = k;
                     phot = index[k];
                     dst2 = dist2[k];
                     while (parent <= halfFound)
                     {
                         j = parent + parent;
                         if ((j < found) && (dist2[j] < dist2[j + 1]))
                             j++;
                         if (dst2 >= dist2[j])
                             break;
                         dist2[parent] = dist2[j];
                         index[parent] = index[j];
                         parent = j;
                     }
                     dist2[parent] = dst2;
                     index[parent] = phot;
                 }
                 gotHeap = true;
             }
             parent = 1;
             j = 2;
             while (j <= found)
             {
                 if ((j < found) && (dist2[j] < dist2[j + 1]))
                     j++;
                 if (fdist2 > dist2[j])
                     break;
                 dist2[parent] = dist2[j];
                 index[parent] = index[j];
                 parent = j;
                 j += j;
             }
             dist2[parent] = fdist2;
             index[parent] = p;
             dist2[0] = dist2[1];
         }
     }
 }
 private void balanceSegment(Photon[] temp, int index, int start, int end)
 {
     int median = 1;
     while ((4 * median) <= (end - start + 1))
         median += median;
     if ((3 * median) <= (end - start + 1))
     {
         median += median;
         median += (start - 1);
     }
     else
         median = end - median + 1;
     int axis = Photon.SPLIT_Z;
     Vector3 extents = bounds.getExtents();
     if ((extents.x > extents.y) && (extents.x > extents.z))
         axis = Photon.SPLIT_X;
     else if (extents.y > extents.z)
         axis = Photon.SPLIT_Y;
     int left = start;
     int right = end;
     while (right > left)
     {
         double v = photons[right].getCoord(axis);
         int i = left - 1;
         int j = right;
         while (true)
         {
             while (photons[++i].getCoord(axis) < v)
             {
             }
             while ((photons[--j].getCoord(axis) > v) && (j > left))
             {
             }
             if (i >= j)
                 break;
             swap(i, j);
         }
         swap(i, right);
         if (i >= median)
             right = i - 1;
         if (i <= median)
             left = i + 1;
     }
     temp[index] = photons[median];
     temp[index].setSplitAxis(axis);
     if (median > start)
     {
         if (start < (median - 1))
         {
             float tmp;
             switch (axis)
             {
                 case Photon.SPLIT_X:
                     tmp = bounds.getMaximum().x;
                     bounds.getMaximum().x = temp[index].x;
                     balanceSegment(temp, 2 * index, start, median - 1);
                     bounds.getMaximum().x = tmp;
                     break;
                 case Photon.SPLIT_Y:
                     tmp = bounds.getMaximum().y;
                     bounds.getMaximum().y = temp[index].y;
                     balanceSegment(temp, 2 * index, start, median - 1);
                     bounds.getMaximum().y = tmp;
                     break;
                 default:
                     tmp = bounds.getMaximum().z;
                     bounds.getMaximum().z = temp[index].z;
                     balanceSegment(temp, 2 * index, start, median - 1);
                     bounds.getMaximum().z = tmp;
                     break;
             }
         }
         else
             temp[2 * index] = photons[start];
     }
     if (median < end)
     {
         if ((median + 1) < end)
         {
             float tmp;
             switch (axis)
             {
                 case Photon.SPLIT_X:
                     tmp = bounds.getMinimum().x;
                     bounds.getMinimum().x = temp[index].x;
                     balanceSegment(temp, (2 * index) + 1, median + 1, end);
                     bounds.getMinimum().x = tmp;
                     break;
                 case Photon.SPLIT_Y:
                     tmp = bounds.getMinimum().y;
                     bounds.getMinimum().y = temp[index].y;
                     balanceSegment(temp, (2 * index) + 1, median + 1, end);
                     bounds.getMinimum().y = tmp;
                     break;
                 default:
                     tmp = bounds.getMinimum().z;
                     bounds.getMinimum().z = temp[index].z;
                     balanceSegment(temp, (2 * index) + 1, median + 1, end);
                     bounds.getMinimum().z = tmp;
                     break;
             }
         }
         else
             temp[(2 * index) + 1] = photons[end];
     }
 }
 private void balance()
 {
     if (storedPhotons == 0)
         return;
     photons = photonList.ToArray();
     photonList = null;
     Photon[] temp = new Photon[storedPhotons + 1];
     balanceSegment(temp, 1, 1, storedPhotons);
     photons = temp;
     halfStoredPhotons = storedPhotons / 2;
     log2n = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0));
 }
 public void store(ShadingState state, Vector3 dir, Color power, Color diffuse)
 {
     if (((state.getDiffuseDepth() == 0) && (state.getReflectionDepth() > 0 || state.getRefractionDepth() > 0)))
     {
         // this is a caustic photon
         Photon p = new Photon(state.getPoint(), dir, power);
         lock (lockObj)
         {
             storedPhotons++;
             photonList.Add(p);
             bounds.include(new Point3(p.x, p.y, p.z));
             maxPower = Math.Max(maxPower, power.getMax());
         }
     }
 }
Exemple #8
0
        private static void BalancePhotons(SortedList<Int64, Photon> balanced, int index, int start, int end, int level, ref Photon[] unbalanced)
        {
            //			Console.WriteLine("index {0},  start {1},  end {2},  level {3}",index,  start,  end,  level);

            switch (level % 3) {
                case Photon.SPLIT_X:
                    Array.Sort(unbalanced, start, end - start + 1, new XAxisCompare());
                    break;
                case Photon.SPLIT_Y:
                    Array.Sort(unbalanced, start, end - start + 1, new YAxisCompare());
                    break;
                case Photon.SPLIT_Z:
                    Array.Sort(unbalanced, start, end - start + 1, new ZAxisCompare());
                    break;
                default:
                    break;
            }

            int median = start + ((end - start) / 2);

            balanced[index] = unbalanced[median];

            if (median > start)
            {
                if (start < (median - 1))
                {
                    BalancePhotons(balanced, index * 2, start, median-1, level + 1, ref unbalanced);
                }
                else
                {
                    balanced[index * 2] = unbalanced[start];
                }
            }

            if (median < end)
            {
                if ((median + 1) < end)
                {
                    BalancePhotons(balanced, index * 2 + 1, median+1, end, level + 1, ref unbalanced);
                }
                else
                {
                    balanced[(index * 2) + 1 ] = unbalanced[end];
                }
            }
        }
Exemple #9
0
 public void store(ShadingState state, Vector3 dir, Color power, Color diffuse)
 {
     Photon p = new Photon(state.getPoint(), state.getNormal(), dir, power, diffuse);
     lock (lockObj)
     {
         storedPhotons++;
         photonList.Add(p);
         bounds.include(new Point3(p.x, p.y, p.z));
         maxPower = Math.Max(maxPower, power.getMax());
     }
 }
Exemple #10
0
        public void precomputeRadiance()
        {
            if (storedPhotons == 0)
                return;
            // precompute the radiance for all photons that are neither
            // leaves nor parents of leaves in the tree.
            int quadStoredPhotons = halfStoredPhotons / 2;
            Point3 p = new Point3();
            Vector3 n = new Vector3();
            Point3 ppos = new Point3();
            Vector3 pdir = new Vector3();
            Vector3 pvec = new Vector3();
            Color irr = new Color();
            Color pow = new Color();
            float maxDist2 = gatherRadius * gatherRadius;
            NearestPhotons np = new NearestPhotons(p, numGather, maxDist2);
            Photon[] temp = new Photon[quadStoredPhotons + 1];
            UI.taskStart("Precomputing radiance", 1, quadStoredPhotons);
            for (int i = 1; i <= quadStoredPhotons; i++)
            {
                UI.taskUpdate(i);
                Photon curr = photons[i];
                p.set(curr.x, curr.y, curr.z);
                Vector3.decode(curr.normal, n);
                irr.set(Color.BLACK);
                np.reset(p, maxDist2);
                locatePhotons(np);
                if (np.found < 8)
                {
                    curr.data = 0;
                    temp[i] = curr;
                    continue;
                }
                float invArea = 1.0f / ((float)Math.PI * np.dist2[0]);
                float maxNDist = np.dist2[0] * 0.05f;
                for (int j = 1; j <= np.found; j++)
                {
                    Photon phot = np.index[j];
                    Vector3.decode(phot.dir, pdir);
                    float cos = -Vector3.dot(pdir, n);
                    if (cos > 0.01f)
                    {
                        ppos.set(phot.x, phot.y, phot.z);
                        Point3.sub(ppos, p, pvec);
                        float pcos = Vector3.dot(pvec, n);
                        if ((pcos < maxNDist) && (pcos > -maxNDist))
                            irr.add(pow.setRGBE(phot.power));
                    }
                }
                irr.mul(invArea);
                // compute radiance
                irr.mul(new Color(curr.data)).mul(1.0f / (float)Math.PI);
                curr.data = irr.toRGBE();
                temp[i] = curr;
            }
            UI.taskStop();

            // resize photon map to only include irradiance photons
            numGather /= 4;
            maxRadius = 1.4f * (float)Math.Sqrt(maxPower * numGather);
            if (gatherRadius > maxRadius)
                gatherRadius = maxRadius;
            storedPhotons = quadStoredPhotons;
            halfStoredPhotons = storedPhotons / 2;
            log2n = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0));
            photons = temp;
            hasRadiance = true;
        }
Exemple #11
0
            public void checkAddNearest(Photon p)
            {
                float fdist2 = p.getDist2(px, py, pz);

                if (fdist2 < dist2[0])
                {
                    if (found < max)
                    {
                        found++;
                        dist2[found] = fdist2;
                        index[found] = p;
                    }
                    else
                    {
                        int j;
                        int parent;
                        if (!gotHeap)
                        {
                            float  dst2;
                            Photon phot;
                            int    halfFound = found >> 1;
                            for (int k = halfFound; k >= 1; k--)
                            {
                                parent = k;
                                phot   = index[k];
                                dst2   = dist2[k];
                                while (parent <= halfFound)
                                {
                                    j = parent + parent;
                                    if ((j < found) && (dist2[j] < dist2[j + 1]))
                                    {
                                        j++;
                                    }
                                    if (dst2 >= dist2[j])
                                    {
                                        break;
                                    }
                                    dist2[parent] = dist2[j];
                                    index[parent] = index[j];
                                    parent        = j;
                                }
                                dist2[parent] = dst2;
                                index[parent] = phot;
                            }
                            gotHeap = true;
                        }
                        parent = 1;
                        j      = 2;
                        while (j <= found)
                        {
                            if ((j < found) && (dist2[j] < dist2[j + 1]))
                            {
                                j++;
                            }
                            if (fdist2 > dist2[j])
                            {
                                break;
                            }
                            dist2[parent] = dist2[j];
                            index[parent] = index[j];
                            parent        = j;
                            j            += j;
                        }
                        dist2[parent] = fdist2;
                        index[parent] = p;
                        dist2[0]      = dist2[1];
                    }
                }
            }
Exemple #12
0
        public Color getRadiance(Point3 p, Vector3 n)
        {
            if (!hasRadiance || (storedPhotons == 0) || p == null)
            {
                return(Color.BLACK);
            }
            float   px    = p.x;
            float   py    = p.y;
            float   pz    = p.z;
            int     i     = 1;
            int     level = 0;
            int     cameFrom;
            float   dist2;
            float   maxDist2 = gatherRadius * gatherRadius;
            Photon  nearest  = null;
            Photon  curr;
            Vector3 photN = new Vector3();

            float[] dist1d2 = new float[log2n];
            int[]   chosen  = new int[log2n];
            while (true)
            {
                while (i < halfStoredPhotons)
                {
                    float dist1d = photons[i].getDist1(px, py, pz);
                    dist1d2[level] = dist1d * dist1d;
                    i += i;
                    if (dist1d > 0)
                    {
                        i++;
                    }
                    chosen[level++] = i;
                }
                curr  = photons[i];
                dist2 = curr.getDist2(px, py, pz);
                if (dist2 < maxDist2)
                {
                    Vector3.decode(curr.normal, photN);
                    float currentDotN = Vector3.dot(photN, n);
                    if (currentDotN > 0.9f)
                    {
                        nearest  = curr;
                        maxDist2 = dist2;
                    }
                }
                do
                {
                    cameFrom = i;
                    i      >>= 1;
                    level--;
                    if (i == 0)
                    {
                        return((nearest == null) ? Color.BLACK : new Color().setRGBE(nearest.data));
                    }
                } while ((dist1d2[level] >= maxDist2) || (cameFrom != chosen[level]));
                curr  = photons[i];
                dist2 = curr.getDist2(px, py, pz);
                if (dist2 < maxDist2)
                {
                    Vector3.decode(curr.normal, photN);
                    float currentDotN = Vector3.dot(photN, n);
                    if (currentDotN > 0.9f)
                    {
                        nearest  = curr;
                        maxDist2 = dist2;
                    }
                }
                i = chosen[level++] ^ 1;
            }
        }
Exemple #13
0
        public void precomputeRadiance()
        {
            if (storedPhotons == 0)
            {
                return;
            }
            // precompute the radiance for all photons that are neither
            // leaves nor parents of leaves in the tree.
            int            quadStoredPhotons = halfStoredPhotons / 2;
            Point3         p        = new Point3();
            Vector3        n        = new Vector3();
            Point3         ppos     = new Point3();
            Vector3        pdir     = new Vector3();
            Vector3        pvec     = new Vector3();
            Color          irr      = new Color();
            Color          pow      = new Color();
            float          maxDist2 = gatherRadius * gatherRadius;
            NearestPhotons np       = new NearestPhotons(p, numGather, maxDist2);

            Photon[] temp = new Photon[quadStoredPhotons + 1];
            UI.taskStart("Precomputing radiance", 1, quadStoredPhotons);
            for (int i = 1; i <= quadStoredPhotons; i++)
            {
                UI.taskUpdate(i);
                Photon curr = photons[i];
                p.set(curr.x, curr.y, curr.z);
                Vector3.decode(curr.normal, n);
                irr.set(Color.BLACK);
                np.reset(p, maxDist2);
                locatePhotons(np);
                if (np.found < 8)
                {
                    curr.data = 0;
                    temp[i]   = curr;
                    continue;
                }
                float invArea  = 1.0f / ((float)Math.PI * np.dist2[0]);
                float maxNDist = np.dist2[0] * 0.05f;
                for (int j = 1; j <= np.found; j++)
                {
                    Photon phot = np.index[j];
                    Vector3.decode(phot.dir, pdir);
                    float cos = -Vector3.dot(pdir, n);
                    if (cos > 0.01f)
                    {
                        ppos.set(phot.x, phot.y, phot.z);
                        Point3.sub(ppos, p, pvec);
                        float pcos = Vector3.dot(pvec, n);
                        if ((pcos < maxNDist) && (pcos > -maxNDist))
                        {
                            irr.add(pow.setRGBE(phot.power));
                        }
                    }
                }
                irr.mul(invArea);
                // compute radiance
                irr.mul(new Color(curr.data)).mul(1.0f / (float)Math.PI);
                curr.data = irr.toRGBE();
                temp[i]   = curr;
            }
            UI.taskStop();

            // resize photon map to only include irradiance photons
            numGather /= 4;
            maxRadius  = 1.4f * (float)Math.Sqrt(maxPower * numGather);
            if (gatherRadius > maxRadius)
            {
                gatherRadius = maxRadius;
            }
            storedPhotons     = quadStoredPhotons;
            halfStoredPhotons = storedPhotons / 2;
            log2n             = (int)Math.Ceiling(Math.Log(storedPhotons) / Math.Log(2.0));
            photons           = temp;
            hasRadiance       = true;
        }