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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifndef __VCG_MESH_VISIBILITY
00056 #define __VCG_MESH_VISIBILITY
00057
00058 #include <stdlib.h>
00059
00060 #include <bitset>
00061 #include <vcg/math/matrix44.h>
00062 #include <wrap/gl/math.h>
00063 #include "simplepic.h"
00064 #include <vcg/math/gen_normal.h>
00065
00066 namespace vcg {
00067
00068 template <class MESH_TYPE, int MAXVIS=2048> class VisShader
00069 {
00070 public :
00071 enum {VisMax=MAXVIS};
00072 VisShader(MESH_TYPE &me):m(me)
00073 {
00074 CullFlag= false;
00075 IsClosedFlag = false;
00076 ZTWIST=1e-3;
00077 SplitNum=1;
00078
00079 CameraViewing=false;
00080 }
00081
00082 typedef Point3<typename MESH_TYPE::ScalarType> Point3x;
00083
00084 typedef typename MESH_TYPE::CoordType CoordType;
00085 typedef typename MESH_TYPE::ScalarType ScalarType;
00086 typedef typename MESH_TYPE::VertexType VertexType;
00087 typedef typename MESH_TYPE::VertexPointer VertexPointer;
00088 typedef typename MESH_TYPE::VertexIterator VertexIterator;
00089 typedef typename MESH_TYPE::FaceIterator FaceIterator;
00090 typedef typename MESH_TYPE::FaceType FaceType;
00091 typedef Matrix44<ScalarType> Matrix44x;
00092 typedef Box3<ScalarType> Box3x;
00093
00094
00095 MESH_TYPE &m;
00096
00097 std::vector<MESH_TYPE *> OMV;
00098
00099
00100
00101
00102 std::vector<float> VV;
00103 std::vector< Point3x > VN;
00104
00105
00106 bool IsClosedFlag;
00107 float ZTWIST;
00108 bool CullFlag;
00109 int SplitNum;
00110 protected:
00111 bool CameraViewing;
00112
00113 public:
00114
00115
00116
00117 virtual void MapVisibility(float Gamma=1, float LowPass=0, float HighPass=1,float Scale=1.0)=0;
00118
00119
00120 virtual int GLAccumPixel( std::vector<int> &PixSeen)=0;
00121
00122 virtual bool ReadVisibility(const char * ){assert( 0); return false;}
00123 virtual bool WriteVisibility(const char * ){assert( 0); return false;}
00124
00125
00126
00127
00128 void Clear() {
00129 fill(VV.begin(),VV.end(),0); }
00130
00131 void InitGL()
00132 {
00133 glPushAttrib(GL_COLOR_BUFFER_BIT );
00134 ::glClearColor (1.0, 1.0, 1.0, 0.0);
00135 glMatrixMode (GL_PROJECTION);
00136 glPushMatrix();
00137 glMatrixMode (GL_MODELVIEW);
00138 glPushMatrix();
00139 }
00140
00141 void RestoreGL()
00142 {
00143 glMatrixMode (GL_PROJECTION);
00144 glPopMatrix();
00145 glMatrixMode (GL_MODELVIEW);
00146 glPopMatrix();
00147 glPopAttrib();
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void AddPixelCount(std::vector<float> &_VV, const std::vector<int> &PixSeen)
00161 {
00162 assert(_VV.size()==PixSeen.size());
00163 for(unsigned int i=0;i<PixSeen.size();++i)
00164 if(PixSeen[i]>0) _VV[i]+= 1;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 void Compute( CallBack *cb)
00185 {
00186
00187 InitGL();
00188 int t00=clock();
00189 VV.resize(m.vert.size());
00190 std::vector<int> PixSeen(VV.size(),0);
00191 int TotRay=0,HitRay=0;
00192 for(unsigned int i=0;i<VN.size();++i)
00193 {
00194 int t0=clock();
00195 fill(PixSeen.begin(),PixSeen.end(),0);
00196 int added=SplittedRendering(VN[i], PixSeen,cb);
00197 AddPixelCount(VV,PixSeen);
00198 int t1=clock();
00199 HitRay+=added;
00200 TotRay+=VV.size();
00201 printf("%3i/%i : %i msec -- TotRays %i, HitRays %i, ray/sec %3.1fk \n ",i,VN.size(),t1-t0,TotRay,HitRay,float(TotRay)/(clock()-t00));
00202 }
00203
00204 printf("Tot Time %i msec TotRays %i, HitRays %i, ray/sec %3.1fk \n ",clock()-t00,TotRay,HitRay,float(TotRay)/(clock()-t00));
00205 RestoreGL();
00206 }
00207
00208 void ComputeHalf(int nn, Point3x &dir, CallBack *cb)
00209 {
00210 std::string buf;
00211
00212 VN.clear();
00213 std::vector<Point3x> nvt;
00214 assert(0 && "This is only my guess (to compile). (Ponchio)");
00215 assert(0 && "Was: GenNormal(nn*2, nvt);");
00216 GenNormal<ScalarType>::Uniform(nn*2,nvt);
00217 for(int i=0;i<nvt.size();++i)
00218 if(dir*nvt[i]>0) VN.push_back(nvt[i]);
00219
00220 printf("Asked %i normal, got %i normals\n",nn,VN.size());
00221 Compute(cb);
00222 }
00223
00224 void ComputeUniformCone(int nn, std::vector<Point3x> &vv, ScalarType AngleRad, Point3x &ConeDir, CallBack *cb)
00225 {
00226 VN.clear();
00227 GenNormal<ScalarType>::UniformCone(nn,VN,AngleRad,ConeDir);
00228 typename std::vector<Point3x>::iterator vi;
00229 for(vi=VN.begin();vi!=VN.end();++vi)
00230 vv.push_back(*vi);
00231
00232 char buf[256];
00233 sprintf(buf,"Asked %i normal, got %i normals\n",nn,VN.size());
00234 cb(buf);
00235 Compute(cb);
00236 }
00237 void ComputeUniform(int nn, std::vector<Point3x> &vv, CallBack *cb)
00238 {
00239 VN.clear();
00240 GenNormal<ScalarType>::Uniform(nn,VN);
00241 typename std::vector<Point3x>::iterator vi;
00242 for(vi=VN.begin();vi!=VN.end();++vi)
00243 vv.push_back(*vi);
00244
00245 char buf[256];
00246 sprintf(buf,"Asked %i normal, got %i normals\n",nn,VN.size());
00247 cb(buf);
00248 Compute(cb);
00249 }
00250
00251 void ComputeSingle(Point3x &dir, std::vector<Point3x> &vv,CallBack *cb)
00252 {
00253 VN.clear();
00254 VN.push_back(dir);
00255 vv.push_back(dir);
00256 printf("Computing one direction (%f %f %f)\n",dir[0],dir[1],dir[2]);
00257 Compute(cb);
00258 }
00259
00260
00261
00262 int SplittedRendering(Point3x &ViewDir, std::vector<int> &PixSeen, CallBack *cb=DummyCallBack)
00263 {
00264 int tt=0;
00265 int i,j;
00266 for(i=0;i<SplitNum;++i)
00267 for(j=0;j<SplitNum;++j){
00268 SetupOrthoViewMatrix(ViewDir, i,j,SplitNum);
00269 tt+=GLAccumPixel(PixSeen);
00270 }
00271 return tt;
00272 }
00273
00274
00275 void GenMatrix(Matrix44d &a, Point3d Axis, double angle)
00276 {
00277 const double eps=1e-3;
00278 Point3d RotAx = Axis ^ Point3d(0,0,1);
00279 double RotAngle = Angle(Axis,Point3d(0,0,1));
00280
00281 if(math::Abs(RotAx.Norm())<eps) {
00282 RotAx=Axis ^ Point3d(0,1,0);
00283 double RotAngle = Angle(Axis,Point3d(0,1,0));
00284 }
00285
00286
00287 RotAx.Normalize();
00288 a.SetRotate(RotAngle,RotAx);
00289
00290
00291
00292 }
00293
00294
00295
00296
00297 void SetupOrthoViewMatrix(Point3x &ViewDir, int subx, int suby,int LocSplit)
00298 {
00299 glMatrixMode (GL_PROJECTION);
00300 glLoadIdentity ();
00301 float dlt=2.0f/LocSplit;
00302
00303 glOrtho(-1+subx*dlt, -1+(subx+1)*dlt, -1+suby*dlt, -1+(suby+1)*dlt,-2,2);
00304 glMatrixMode (GL_MODELVIEW);
00305 glLoadIdentity ();
00306 Matrix44d rot;
00307 Point3d qq; qq.Import(ViewDir);
00308 GenMatrix(rot,qq,0);
00309 glMultMatrix(rot);
00310 double d=2.0/m.bbox.Diag();
00311 glScalef(d,d,d);
00312 glTranslate(-m.bbox.Center());
00313 }
00314
00315 void ComputeSingleDirection(Point3x BaseDir, std::vector<int> &PixSeen, CallBack *cb=DummyCallBack)
00316 {
00317 int t0=clock();
00318 std::string buf;
00319
00320 int added=SplittedRendering(BaseDir, PixSeen,cb);
00321 int t1=clock();
00322 printf("ComputeSingleDir %i msec\n",t1-t0);
00323 }
00324
00325 void ComputeAverageVisibilityDirection()
00326 {
00327 int i,j;
00328 VD.resize(VM.size());
00329 for(j=0;j<VM.size();++j)
00330 {
00331 Point3x &nn=VD[j];
00332 nn=Point3x(0,0,0);
00333 bitset<VisMax> &msk=VM[j];
00334 for(i=0;i<VN.size();++i)
00335 if(msk[i]) nn+=VN[i];
00336 }
00337 for(j=0;j<VM.size();++j)
00338 VD[j].Normalize();
00339
00340 }
00341
00342
00343
00344
00345
00346
00347 void DirectionalLightingEnvironment(std::vector<float> &LE, Point3x dir, ScalarType DegAngle1, ScalarType DegAngle2)
00348 {
00349 LE.clear();
00350 LE.resize(VN.size(),0);
00351 int i;
00352 for(i=0;i<VN.size();++i)
00353 {
00354 ScalarType a=ToDeg(Angle(dir,VN[i]));
00355 if(a<DegAngle1) { LE[i]=1; continue; }
00356 if(a>DegAngle2) { LE[i]=0; continue; }
00357 LE[i] = 1.0-(a-DegAngle1)/(DegAngle2-DegAngle1);
00358
00359 }
00360
00361 ScalarType sum=0;
00362 for(i=0;i<VN.size();++i)
00363 sum+=LE[i];
00364 for(i=0;i<VN.size();++i)
00365 LE[i]/=sum;
00366 }
00367
00368
00369 };
00370
00371
00372
00373
00374 template <class MESH_TYPE> class VertexVisShader : public VisShader<MESH_TYPE>
00375 {
00376 public :
00377
00378
00379 VertexVisShader(MESH_TYPE &me):VisShader<MESH_TYPE>(me)
00380 {
00381
00382 if(! m.HasPerVertexColor()) assert(0);
00383 }
00384
00385 void Init() { VV.resize(m.vert.size()); }
00386 void Compute(int nn);
00387
00388 void DrawFill (MESH_TYPE &mm)
00389 {
00390 static GLuint dl=0;
00391 if(mm.face.empty())
00392 { AMesh::VertexIterator vi;
00393 glBegin(GL_POINTS);
00394 for(vi=mm.vert.begin();vi!=mm.vert.end();++vi)
00395 {
00396 if(ColorFlag) glColor((*vi).C());
00397 glVertex((*vi).P());
00398 }
00399 glEnd();
00400 }
00401 else
00402 {
00403 glBegin(GL_TRIANGLES);
00404 FaceIterator fi;
00405 for(fi=mm.face.begin();fi!=mm.face.end();++fi)
00406 {
00407 glVertex((*fi).V(0)->P());
00408 glVertex((*fi).V(1)->P());
00409 glVertex((*fi).V(2)->P());
00410 }
00411 glEnd();
00412 }
00413 }
00414
00415
00416
00417
00418
00419
00420 int GLAccumPixel( std::vector<int> &PixSeen)
00421 {
00422 SimplePic<float> snapZ;
00423 SimplePic<Color4b> snapC;
00424
00425 glClearColor(Color4b::Black);
00426 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00427 glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT );
00428 glDisable(GL_LIGHTING);
00429 glDepthRange(0.0f,1.0f);
00430 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00431 glDepthMask(GL_TRUE);
00432 glDrawBuffer(GL_BACK);
00433 glReadBuffer(GL_BACK);
00434
00436 glDepthRange(2.0*ZTWIST,1.0f);
00437 if(IsClosedFlag) glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
00438 glEnable(GL_CULL_FACE);
00439 glCullFace(GL_BACK);
00440 glColor(Color4b::Red);
00441 DrawFill(m);
00442
00443 if(!IsClosedFlag) {
00444 glCullFace(GL_FRONT);
00445 glColor(Color4b::Black);
00446 DrawFill(m);
00447 snapC.OpenGLSnap();
00448 }
00449
00450 int cnt=0;
00451 snapZ.OpenGLSnap(GL_DEPTH_COMPONENT);
00452
00453 glDepthRange(0,1.0f-2.0*ZTWIST);
00454 double MM[16];
00455 glGetDoublev(GL_MODELVIEW_MATRIX,MM);
00456 double MP[16];
00457 glGetDoublev(GL_PROJECTION_MATRIX,MP);
00458 int VP[4];
00459 glGetIntegerv(GL_VIEWPORT,VP);
00460 double tx,ty,tz;
00461
00462 for(unsigned int i=0;i<m.vert.size();++i)
00463 {
00464 gluProject(m.vert[i].P()[0],m.vert[i].P()[1],m.vert[i].P()[2],
00465 MM,MP,VP,
00466 &tx,&ty,&tz);
00467 int col=1;
00468
00469 if(tx>=0 && tx<snapZ.sx && ty>=0 && ty<snapZ.sy)
00470 {
00471 int txi=floor(tx),tyi=floor(ty);
00472 float sd=snapZ.Pix(tx,ty);
00473 if(!IsClosedFlag) {
00474 col = max( max(snapC.Pix(txi+0,tyi+0)[0],snapC.Pix(txi+1,tyi+0)[0]),
00475 max(snapC.Pix(txi+0,tyi+1)[0],snapC.Pix(txi+1,tyi+1)[0]));
00476
00477
00478 }
00479 if(col!=0 && tz<sd) {
00480 PixSeen[i]++;
00481 cnt++;
00482 }
00483 }
00484 }
00485 glPopAttrib();
00486
00487 return cnt;
00488 }
00489
00490 void SmoothVisibility(bool Enhance=false)
00491 {
00492 FaceIterator fi;
00493 std::vector<float> VV2;
00494 std::vector<int> VC(VV.size(),1);
00495 VV2=VV;
00496 for(fi=m.face.begin();fi!=m.face.end();++fi)
00497 for(int i=0;i<3;++i)
00498 {
00499 VV2[(*fi).V(i)-&*m.vert.begin()] += VV[(*fi).V1(i)-&*m.vert.begin()];
00500 ++VC[(*fi).V(i)-&*m.vert.begin()];
00501 }
00502
00503 if(!Enhance)
00504 for(unsigned int i=0;i<VV2.size();++i)
00505 VV[i]=VV2[i]/VC[i];
00506 else
00507 for(unsigned int i=0;i<VV2.size();++i)
00508 VV[i]=VV[i]+ (VV[i]-VV2[i]/VC[i])*.5;
00509 }
00510
00511
00512 void MapFalseColor()
00513 {
00514 float minv=*min_element(VV.begin(),VV.end());
00515 float maxv=*max_element(VV.begin(),VV.end());
00516 printf("Visibility Range %f %f\n", minv,maxv);
00517 MapFalseColor(minv, maxv);
00518 }
00519
00520 void MapFalseColor(float minv, float maxv)
00521 {
00522 VertexIterator vi;
00523 for(vi=m.vert.begin();vi!=m.vert.end();++vi){
00524 float gval=(VV[vi-m.vert.begin()]-minv)/(maxv-minv);
00525 math::Clamp(gval,0.0f,1.0f);
00526 (*vi).C().ColorRamp(1.0,0.0,gval);
00527 }
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537 void MapVisibility(float Gamma=1, float LowPass=0, float HighPass=1, float Scale= 1.0)
00538 {
00539 float minv=*min_element(VV.begin(),VV.end());
00540 float maxv=*max_element(VV.begin(),VV.end());
00541 printf("Visibility Range %f %f\n", minv,maxv);
00542
00543 VertexIterator vi;
00544 for(vi=m.vert.begin();vi!=m.vert.end();++vi){
00545 float gval=(VV[vi-m.vert.begin()]-minv)/(maxv-minv);
00546 if(gval<LowPass) gval=LowPass;
00547 if(gval>HighPass) gval=HighPass;
00548 (*vi).C().SetGrayShade(Scale*pow((gval-LowPass)/(HighPass-LowPass),Gamma));
00549 }
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 };
00569
00570
00571
00572 }
00573 #endif // __VCG_MESH_VISIBILITY