/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004-2016 \/)\/ * * 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 #include namespace vcg { template class GenNormal { public: typedef Point3 Point3x; static void Random(int vn, std::vector > &NN) { NN.clear(); while(NN.size() &NN) { NN.resize(n); for(int i=0;i > &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)); Fibonacci(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 cosAngle = cos(AngleRad); for(vi=NNT.begin();vi!=NNT.end();++vi) { if(dir.dot(*vi) >= cosAngle) NN.push_back(*vi); } } // This is an Implementation of the Dave Rusin’s Disco Ball algorithm // You can spread the points as follows: // Put N+1 points on the meridian from north to south poles, equally spaced. // If you swing this meridian around the sphere, you'll sweep out the entire // surface; in the process, each of the points will sweep out a circle. You // can show that the ith point will sweep out a circle of radius sin(pi i/N). // If you space points equally far apart on this circle, keeping the // displacement roughly the same as on that original meridian, you'll be // able to fit about 2N sin(pi i/N) points here. This process will put points // pretty evenly spaced on the sphere; the number of such points is about // 2+ 2N*Sum(i=1 to N-1) sin(pi i/N). // The closed form of this summation // 2.0 - ( (2.0*N * sin (M_PI/N))/(cos(M_PI/N) - 1.0)); static void DiscoBall(int vn, std::vector > &NN) { // Guess the right N ScalarType N=0; for(N=1;N= vn) break; } ScalarType VerticalAngle = M_PI / N; NN.push_back(Point3(0,0,1.0)); for (int i =1; i(X,Y,Z)); } } NN.push_back(Point3(0,0,-1.0)); } static void RecursiveOctahedron(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(); } } /* Trova la normale piu vicina a quella data. Assume che tutte normale in ingresso sia normalizzata; */ static int BestMatchingNormal(const Point3x &n, std::vector &nv) { int ret=-1; ScalarType bestang=-1; ScalarType cosang; typename std::vector::iterator ni; for(ni=nv.begin();ni!=nv.end();++ni) { cosang=(*ni).dot(n); if(cosang>bestang) { bestang=cosang; ret=ni-nv.begin(); } } assert(ret>=0 && ret v; int level; int sz; int sz2; Point3x &Val(int i, int j) { assert(i>=-sz2 && i<=sz2); assert(j>=-sz2 && j<=sz2); return v[i+sz2 +(j+sz2)*sz]; } /* * Only the first quadrant is generated and replicated onto the other ones. * * o lev == 1 * | \ sz2 = 2^lev = 2 * o - o sz = 5 (eg. all the points lie in a 5x5 squre) * | \ | \ * o - o - o * * | * V * * o * | \ lev == 1 * o - o sz2 = 4 * | \ | \ sz = 9 (eg. all the points lie in a 9x9 squre) * o - o - o * | \ | \ | \ * o - o - o - o * | \ | \ | \ | \ * o - o - o - o - o * * */ void Init(int lev) { sz2=pow(2.0f,lev); sz=sz2*2+1; v.resize(sz*sz,Point3x(0,0,0)); if(lev==0) { Val( 0,0)=Point3x( 0, 0, 1); Val( 1,0)=Point3x( 1, 0, 0); Val( 0,1)=Point3x( 0, 1, 0); } else { OctaLevel tmp; tmp.Init(lev-1); int i,j; for(i=0;i<=sz2;++i) for(j=0;j<=(sz2-i);++j) { if((i%2)==0 && (j%2)==0) Val(i,j)=tmp.Val(i/2,j/2); if((i%2)!=0 && (j%2)==0) Val(i,j)=(tmp.Val((i-1)/2,j/2)+tmp.Val((i+1)/2,j/2))/2.0; if((i%2)==0 && (j%2)!=0) Val(i,j)=(tmp.Val(i/2,(j-1)/2)+tmp.Val(i/2,(j+1)/2))/2.0; if((i%2)!=0 && (j%2)!=0) Val(i,j)=(tmp.Val((i-1)/2,(j+1)/2)+tmp.Val((i+1)/2,(j-1)/2))/2.0; Val( sz2-j, sz2-i)[0] = Val(i,j)[0]; Val( sz2-j, sz2-i)[1] = Val(i,j)[1]; Val( sz2-j, sz2-i)[2] = -Val(i,j)[2]; Val(-sz2+j, sz2-i)[0] =-Val(i,j)[0]; Val(-sz2+j, sz2-i)[1] = Val(i,j)[1]; Val(-sz2+j, sz2-i)[2] = -Val(i,j)[2]; Val( sz2-j,-sz2+i)[0] = Val(i,j)[0]; Val( sz2-j,-sz2+i)[1] =-Val(i,j)[1]; Val( sz2-j,-sz2+i)[2] = -Val(i,j)[2]; Val(-sz2+j,-sz2+i)[0] =-Val(i,j)[0]; Val(-sz2+j,-sz2+i)[1] =-Val(i,j)[1]; Val(-sz2+j,-sz2+i)[2] = -Val(i,j)[2]; Val(-i,-j)[0] = -Val(i,j)[0]; Val(-i,-j)[1] = -Val(i,j)[1]; Val(-i,-j)[2] = Val(i,j)[2]; Val( i,-j)[0] = Val(i,j)[0]; Val( i,-j)[1] = -Val(i,j)[1]; Val( i,-j)[2] = Val(i,j)[2]; Val(-i, j)[0] = -Val(i,j)[0]; Val(-i, j)[1] = Val(i,j)[1]; Val(-i, j)[2] = Val(i,j)[2]; } typename std::vector >::iterator vi; for(vi=v.begin(); vi!=v.end();++vi) (*vi).Normalize(); } } }; }; } #endif