VCRA-SZCZERBACKI-PointBasedRendering/splatting.cpp

00001 
00018 #include "splatting.h"
00019 
00020 #include "analytic.inl"
00021 
00022 extern Mesh    *lwo;
00023 extern Color   *buffer;
00024 extern ABuffer *abuffer;
00025 
00026 extern std::vector<Splat>       splats;
00027 
00028 void loadLwoFile(char *filename) 
00029 {
00030   glutSetCursor(GLUT_CURSOR_WAIT);
00031 
00032   lwo = new Mesh( filename );
00033         lwo->setParametrization();
00034         lwo->subdivide( subdivision );
00035         splats.resize(lwo->getVertexCount());
00036         for(int i=0;i<splats.size();++i)
00037         {
00038                 float maxl = 0.0f,l;
00039                 int valence, left, right;
00040                 bool boundary;
00041                 const std::vector<Mesh::ventry> &vertexlist = lwo->get1Neighbourhood( i, valence, boundary, left, right );
00042                 for(int j=0;j<vertexlist.size();++j)
00043                 {
00044                         l = (lwo->getVertex(vertexlist[j].m_vertex).m_position - lwo->getVertex(i).m_position).length();
00045                         maxl = max2(l,maxl);
00046                 }
00047 
00048                 splats[i].m_position = lwo->getVertex(i).m_position;
00049                 splats[i].m_normal = lwo->getVertex(i).m_normal;
00050                 splats[i].m_size = maxl;
00051     splats[i].m_color.set(1.0f,0.85f,0.65f, 1.0f);
00052         }
00053 
00054   glutSetCursor(GLUT_CURSOR_INHERIT);
00055 }
00056 
00057 void poissonDiscDistribution( Vector2 *points, int count )
00058 {
00059         SS_ASSERT(count > 0);
00060 
00061         float threshold = 1.0f;
00062 
00063         //repeat until we have all subpixels distributed
00064         int j=0;
00065         while(j < count)
00066         {
00067                 //try to place a random sample in a unit circle so that it is not closer
00068                 // to earlier samples than the threshold 
00069                 int tries = 100;
00070                 int k;
00071                 Vector2 p;
00072                 do
00073                 {
00074                         //make a random sample inside unit circle
00075                         p = randInCircle();
00076 
00077                         //test whether the sample is closer to points already placed than the threshold
00078                         for(k=0;k<j;k++)
00079                         {
00080                                 if( (p - points[k]).length() < threshold )
00081                                 {       //too close, break
00082                                         tries--;
00083                                         break;
00084                                 }
00085                         }
00086                 } while(k < j && tries > 0);
00087 
00088                 if( tries == 0 )
00089                 {
00090                         //if did not succeed, lower the threshold and redistribute all points
00091                         threshold *= 0.98f;     //the closer the number is to 1, the slower the convergence
00092                         j = 0;
00093                 }
00094                 else
00095                 {
00096                         //if succeeded, add the sample
00097                         points[j] = p;
00098                         j++;
00099                 }
00100         }
00101 }
00102 
00103 float cumulativeGaussian[gausssamples];
00104 
00105 void initCumulativeGaussian()
00106 {
00107         //init cumulative gaussian
00108         float x = 0.0f;
00109         float xstep = prefiltercutoff / (float)gausssamples;
00110         x += xstep/2.0f;        //calculate x at the center of each slice
00111         cumulativeGaussian[0] = exp(-0.5f*x*x)*xstep;
00112         for(int i=1;i<gausssamples;i++)
00113         {
00114                 x += xstep;
00115                 cumulativeGaussian[i] = cumulativeGaussian[i-1] + exp(-0.5f*x*x)*xstep;
00116         }
00117         //normalize
00118         for(int i=0;i<gausssamples;i++)
00119         {
00120                 cumulativeGaussian[i] /= cumulativeGaussian[gausssamples-1];
00121         }
00122 }
00123 
00124 float inverseCumulativeGaussian( float r )
00125 {
00126         int i;
00127         for(i=0;i<gausssamples-1;i++)
00128         {
00129                 if( r > cumulativeGaussian[i] && r < cumulativeGaussian[i+1] )
00130                         break;
00131         }
00132         return (float)i/(float)gausssamples;
00133 }
00134 
00135 void makeJitter(int subpixels)
00136 {
00137         SS_ASSERT(subpixels > 0);
00138 
00139         if( prefilterJitter ) delete[] prefilterJitter;
00140         if( lensJitter) delete[] lensJitter;
00141 
00142         prefilterJitter = new Vector2[subpixels*jitterPatterns];
00143         lensJitter = new Vector2[subpixels*jitterPatterns];
00144 
00145         svPrint("poisson disk distribution with %d points.",subpixels);
00146         Timer t;
00147         t.sample();
00148         initCumulativeGaussian();
00149         for(int p=0;p<jitterPatterns;p++)
00150         {
00151                 poissonDiscDistribution(&prefilterJitter[p*subpixels],subpixels);
00152                 for(int j=0;j<subpixels;j++)
00153                 {
00154                         Vector2 jit = prefilterJitter[p*subpixels+j];
00155                         float r = jit.length();
00156                         if( r > 0.0f ) jit *= 1.0f/r;
00157                         jit *= inverseCumulativeGaussian(r) * prefiltersize;
00158                         prefilterJitter[p*subpixels+j] = jit;
00159                 }
00160 
00161                 poissonDiscDistribution(&lensJitter[p*subpixels],subpixels);
00162                 for(int j=0;j<subpixels;j++)
00163                 {
00164                         lensJitter[p*subpixels+j] *= lensRadius;
00165                 }
00166         }
00167         t.sample();
00168         svPrint(" took %f seconds\n",t.getDelta());
00169 }

Generated on Thu Feb 15 09:09:20 2007 for Surface Splating by  doxygen 1.5.1-p1