diff --git a/vcg/math/gen_normal.h b/vcg/math/gen_normal.h new file mode 100644 index 00000000..caa08d58 --- /dev/null +++ b/vcg/math/gen_normal.h @@ -0,0 +1,165 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +/**************************************************************************** + History + +$Log: gen_normal.h,v $ +****************************************************************************/ + +#ifndef __VCG_GEN_NORMAL +#define __VCG_GEN_NORMAL + +namespace vcg { + +template +class GenNormal +{ +public: +typedef Point3 Point3x; + +static void Random(int vn, std::vector > &NN) +{ + NN.clear(); + while(NN.size() > &NN, ScalarType AngleRad, Point3x dir=Point3x(0,1,0)) +{ + std::vector > NNT; + NN.clear(); + // per prima cosa si calcola il volume della spherical cap di angolo AngleRad + ScalarType Height= 1.0 - cos(AngleRad); // height is measured from top... + // Surface is the one of the tangent cylinder + ScalarType CapArea = 2.0*M_PI*Height; + ScalarType Ratio = CapArea / (4.0*M_PI ); + + printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio)); + Uniform(vn/Ratio,NNT); + printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn); + typename std::vector >::iterator vi; + + ScalarType DotProd = cos(AngleRad); + for(vi=NNT.begin();vi!=NNT.end();++vi) + { + if(dir*(*vi) >= DotProd) NN.push_back(*vi); + } + } + + +static void Uniform(int vn, std::vector > &NN) +{ + OctaLevel pp; + + int ll=10; + while(pow(4.0f,ll)+2>vn) ll--; + + pp.Init(ll); + sort(pp.v.begin(),pp.v.end()); + int newsize = unique(pp.v.begin(),pp.v.end())-pp.v.begin(); + pp.v.resize(newsize); + + NN=pp.v; + Perturb(NN); + } + +static void Perturb(std::vector > &NN) +{ + float width=0.2f/sqrt(float(NN.size())); + + typename std::vector >::iterator vi; + for(vi=NN.begin(); vi!=NN.end();++vi) + { + Point3x pp(((float)rand())/RAND_MAX, + ((float)rand())/RAND_MAX, + ((float)rand())/RAND_MAX); + pp=pp*2.0-Point3x(1,1,1); + pp*=width; + (*vi)+=pp; + (*vi).Normalize(); + } + +} + +private : +class OctaLevel + { + public: + std::vector v; + int level; + int sz; + + Point3f &Val(int i, int j) { + assert(i>=0 && i=0 && j >::iterator vi; + for(vi=v.begin(); vi!=v.end();++vi) + (*vi).Normalize(); + + } + } + }; +}; +} +#endif