00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __VCG_GEN_NORMAL
00030 #define __VCG_GEN_NORMAL
00031
00032 #include <algorithm>
00033
00034 namespace vcg {
00035
00036 template <class ScalarType>
00037 class GenNormal
00038 {
00039 public:
00040 typedef Point3<ScalarType> Point3x;
00041
00042 static void Random(int vn, std::vector<Point3<ScalarType > > &NN)
00043 {
00044 NN.clear();
00045 while(NN.size()<vn)
00046 {
00047 Point3x pp(((float)rand())/RAND_MAX,
00048 ((float)rand())/RAND_MAX,
00049 ((float)rand())/RAND_MAX);
00050 pp=pp*2.0-Point3x(1,1,1);
00051 if(pp.SquaredNorm()<1)
00052 {
00053 Normalize(pp);
00054 NN.push_back(pp);
00055 }
00056 }
00057 }
00058 static void UniformCone(int vn, std::vector<Point3<ScalarType > > &NN, ScalarType AngleRad, Point3x dir=Point3x(0,1,0))
00059 {
00060 std::vector<Point3<ScalarType > > NNT;
00061 NN.clear();
00062
00063 ScalarType Height= 1.0 - cos(AngleRad);
00064
00065 ScalarType CapArea = 2.0*M_PI*Height;
00066 ScalarType Ratio = CapArea / (4.0*M_PI );
00067
00068 printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio));
00069 Uniform(vn/Ratio,NNT);
00070 printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn);
00071 typename std::vector<Point3<ScalarType> >::iterator vi;
00072
00073 ScalarType DotProd = cos(AngleRad);
00074 for(vi=NNT.begin();vi!=NNT.end();++vi)
00075 {
00076 if(dir.dot(*vi) >= DotProd) NN.push_back(*vi);
00077 }
00078 }
00079
00080
00081 static void Uniform(int vn, std::vector<Point3<ScalarType > > &NN)
00082 {
00083 OctaLevel pp;
00084
00085 int ll=10;
00086 while(pow(4.0f,ll)+2>vn) ll--;
00087
00088 pp.Init(ll);
00089 sort(pp.v.begin(),pp.v.end());
00090 int newsize = unique(pp.v.begin(),pp.v.end())-pp.v.begin();
00091 pp.v.resize(newsize);
00092
00093 NN=pp.v;
00094 Perturb(NN);
00095 }
00096
00097 static void Perturb(std::vector<Point3<ScalarType > > &NN)
00098 {
00099 float width=0.2f/sqrt(float(NN.size()));
00100
00101 typename std::vector<Point3<ScalarType> >::iterator vi;
00102 for(vi=NN.begin(); vi!=NN.end();++vi)
00103 {
00104 Point3x pp(((float)rand())/RAND_MAX,
00105 ((float)rand())/RAND_MAX,
00106 ((float)rand())/RAND_MAX);
00107 pp=pp*2.0-Point3x(1,1,1);
00108 pp*=width;
00109 (*vi)+=pp;
00110 (*vi).Normalize();
00111 }
00112
00113 }
00114
00115
00116
00117
00118
00119 static int BestMatchingNormal(const Point3x &n, std::vector<Point3x> &nv)
00120 {
00121 int ret=-1;
00122 ScalarType bestang=-1;
00123 ScalarType cosang;
00124 typename std::vector<Point3x>::iterator ni;
00125 for(ni=nv.begin();ni!=nv.end();++ni)
00126 {
00127 cosang=(*ni).dot(n);
00128 if(cosang>bestang) {
00129 bestang=cosang;
00130 ret=ni-nv.begin();
00131 }
00132 }
00133 assert(ret>=0 && ret <int(nv.size()));
00134 return ret;
00135 }
00136
00137
00138 private :
00139 class OctaLevel
00140 {
00141 public:
00142 std::vector<Point3x> v;
00143 int level;
00144 int sz;
00145
00146 Point3x &Val(int i, int j) {
00147 assert(i>=0 && i<sz);
00148 assert(j>=0 && j<sz);
00149 return v[i+j*sz];
00150 }
00151
00152 void Init(int lev)
00153 {
00154 sz=pow(2.0f,lev+1)+1;
00155 v.resize(sz*sz);
00156 if(lev==0)
00157 {
00158 Val(0,0)=Point3x( 0, 0,-1); Val(0,1)=Point3x( 0, 1, 0); Val(0,2)=Point3x( 0, 0,-1);
00159
00160 Val(1,0)=Point3x(-1, 0, 0); Val(1,1)=Point3x( 0, 0, 1); Val(1,2)=Point3x( 1, 0, 0);
00161
00162 Val(2,0)=Point3x( 0, 0,-1); Val(2,1)=Point3x( 0,-1, 0); Val(2,2)=Point3x( 0, 0,-1);
00163 }
00164 else
00165 {
00166 OctaLevel tmp;
00167 tmp.Init(lev-1);
00168 int i,j;
00169 for(i=0;i<sz;++i)
00170 for(j=0;j<sz;++j)
00171 {
00172 if((i%2)==0 && (j%2)==0)
00173 Val(i,j)=tmp.Val(i/2,j/2);
00174 if((i%2)!=0 && (j%2)==0)
00175 Val(i,j)=(tmp.Val(i/2+0,j/2)+tmp.Val(i/2+1,j/2))/2.0;
00176 if((i%2)==0 && (j%2)!=0)
00177 Val(i,j)=(tmp.Val(i/2,j/2+0)+tmp.Val(i/2,j/2+1))/2.0;
00178 if((i%2)!=0 && (j%2)!=0)
00179 Val(i,j)=(tmp.Val(i/2+0,j/2+0)+tmp.Val(i/2+0,j/2+1)+tmp.Val(i/2+1,j/2+0)+tmp.Val(i/2+1,j/2+1))/4.0;
00180 }
00181 typename std::vector<Point3<ScalarType> >::iterator vi;
00182 for(vi=v.begin(); vi!=v.end();++vi)
00183 (*vi).Normalize();
00184
00185 }
00186 }
00187 };
00188 };
00189 }
00190 #endif