diff --git a/apps/shadevis/shadevis.cpp b/apps/shadevis/shadevis.cpp new file mode 100644 index 00000000..a377946e --- /dev/null +++ b/apps/shadevis/shadevis.cpp @@ -0,0 +1,363 @@ +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "visshader.h" +using namespace vcg; +using namespace std; + + + + +// Vertex, Face, Mesh and Grid definitions. +class MyEdge; +class AFace; +class AVertex : public VertexVCVN< float ,MyEdge,AFace > {}; +class AFace : public FaceFCFN< AVertex,MyEdge,AFace > {}; +class AMesh : public tri::TriMesh< vector, vector > {}; + +///////// Global //////// + +int SampleNum=32; +int WindowRes=800; + +bool SwapFlag=false; + +float lopass=0,hipass=1,gamma=1; +bool LightFlag=true; +bool ColorFlag=true; + +Trackball Q; + +int ScreenH,ScreenW; +float ViewAngle=45; + +class TimeOracle +{ +public: + time_t start; + time_t cur; + + char buf[128]; + + char const *TimeToEndStr(double perc) + { + time(&cur); + double diff=difftime(cur,start); + diff= diff/perc - diff; + + int hh=diff/3600; + int mm=(diff-hh*3600)/60; + int ss=diff-hh*3600-mm*60; + sprintf(buf,"%02i:%02i:%02i",hh,mm,ss); + return buf; + } + + void Start(){time(&start);}; +}; + +bool cb(const char *buf) +{ + printf(buf); + return true; +} + +// prototypes +void SaveTexturedGround(); + +void Draw(AMesh &mm) +{ + AMesh::FaceIterator fi; + glBegin(GL_TRIANGLES); + for(fi=mm.face.begin();fi!=mm.face.end();++fi) + { + + glNormal((*fi).V(0)->N()); glColor((*fi).V(0)->C()); glVertex((*fi).V(0)->P()); + glNormal((*fi).V(1)->N()); glColor((*fi).V(1)->C()); glVertex((*fi).V(1)->P()); + glNormal((*fi).V(2)->N()); glColor((*fi).V(2)->C()); glVertex((*fi).V(2)->P()); + } + glEnd(); +} + +AMesh m; +VertexVisShader Vis(m); + +string OutNameMsh; + + +/* Called when the window is first opened and whenever + * the window is reconfigured (moved or resized). + */ +void ViewReshape(GLsizei w, GLsizei h) +{ + ScreenW=w; ScreenH=h; + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective(ViewAngle,(float)w/(float)h,.1,10000); + glViewport (0, 0, (GLsizei) w, (GLsizei) h); +} + +void ViewDisplay (void) +{ + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluPerspective(ViewAngle,1,.1,10); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); + glTranslatef(0,0,-4); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + Q.GetView(); + Q.Apply(); + Q.Draw(); + float d = 2.0/m.bbox.Diag(); + glScalef(d, d, d); + glTranslate(-m.bbox.Center()); + if(LightFlag) glEnable(GL_LIGHTING); + else glDisable(GL_LIGHTING); + if(ColorFlag) glEnable(GL_COLOR_MATERIAL); + else glDisable(GL_COLOR_MATERIAL); + Draw(m); + glutSwapBuffers(); +} + +void ViewSpecialKey(int , int , int ) +{ + glutPostRedisplay(); +} +void Toggle(bool &flag) {flag = !flag;} +/*********************************************************************/ +/*********************************************************************/ +/*********************************************************************/ +void ViewKey(unsigned char key, int , int ) +{ + Point3f dir; + switch (key) { + case 27: exit(0); break; + case 'l' : + lopass=lopass+.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'L' : + lopass=lopass-.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'h' : + hipass=hipass-.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'H' : + hipass=hipass+.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'g' : + gamma=gamma-.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'G' : + gamma=gamma+.05; printf("Lo %f, Hi %f Gamma %f\n",lopass,hipass,gamma); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'c' : + Vis.ComputeUniform(SampleNum,cb); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case ' ' : { + Point3f dir = Q.camera.ViewPoint(); + printf("ViewPoint %f %f %f\n",dir[0],dir[1],dir[2]); + dir.Normalize(); + dir=Inverse(Q.track.Matrix())*dir; + printf("ViewPoint %f %f %f\n",dir[0],dir[1],dir[2]); + dir.Normalize(); + Vis.ComputeSingle(dir,cb); + Vis.MapVisibility(gamma,lopass,hipass); } + break; + case 's' : + Vis.SmoothVisibility(); + Vis.MapVisibility(gamma,lopass,hipass); + break; + case 'S' : + { + vcg::tri::io::PlyInfo p; + p.mask|=vcg::ply::PLYMask::PM_VERTCOLOR /* | vcg::ply::PLYMask::PM_VERTQUALITY*/ ; + tri::io::ExporterPLY::Save(m,OutNameMsh.c_str(),false,p); + } + break; + case 'a' : LightFlag = !LightFlag; printf("Toggled Light\n"); break; + case 'A' : ColorFlag = !ColorFlag; printf("Toggled Color\n"); break; + } + glutPostRedisplay(); ; +} +void ViewMenu(int val) +{ + ViewKey(val, 0, 0); +} +/*********************************************************************/ +// TrackBall Functions +/*********************************************************************/ + +int PressedButton; // What is the button actually pressed? +int KeyMod; +int GW,GH; // Grandezza della finestra +int B[3]={0,0,0}; // Variabile globale che tiene lo stato dei tre bottoni; + + +void ViewMouse(int button, int state, int x, int y) +{ + static int glut_buttons=0; + + int m_mask = 0; + KeyMod=glutGetModifiers(); + if(GLUT_ACTIVE_SHIFT & KeyMod) m_mask |= Trackball::KEY_SHIFT; + if(GLUT_ACTIVE_ALT & KeyMod) m_mask |= Trackball::KEY_ALT; + if(GLUT_ACTIVE_CTRL & KeyMod) m_mask |= Trackball::KEY_CTRL; + + if(state == GLUT_DOWN) { + glut_buttons |= (1<::Open(m,argv[i]); + if(ret) {printf("Error unable to open mesh %s\n",argv[i]);exit(-1);} + tri::UpdateNormals::PerVertexNormalized(m); + tri::UpdateBounding::Box(m); + + printf("Mesh bbox (%f %f %f)-(%f %f %f)\n\n",m.bbox.min[0],m.bbox.min[1],m.bbox.min[2],m.bbox.max[0],m.bbox.max[1],m.bbox.max[2]); + OutNameMsh=(string(argv[i]).substr(0,strlen(argv[i])-4)); + OutNameMsh+="_vis.ply"; + + printf("Mesh Output filename %s\n",OutNameMsh.c_str()); + + printf("Mesh %iv %if bbox Diag %g\n",m.vn,m.fn,m.bbox.Diag()); + + glutInit(&argc, argv); + + glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); + glutInitWindowSize(WindowRes, WindowRes); + glutInitWindowPosition (10,10); + glutCreateWindow ("shadevis - Visual Computing Lab - vcg.isti.cnr.it "); + glutDisplayFunc(ViewDisplay); + glutReshapeFunc(ViewReshape); + glutKeyboardFunc(ViewKey); + glutSpecialFunc(ViewSpecialKey); + glutMouseFunc(ViewMouse); + glutMotionFunc(ViewMouseMotion); + + ViewInit(); + glewInit(); + glutMainLoop(); + + return(0); +} \ No newline at end of file diff --git a/apps/shadevis/simplepic.h b/apps/shadevis/simplepic.h new file mode 100644 index 00000000..ed70d306 --- /dev/null +++ b/apps/shadevis/simplepic.h @@ -0,0 +1,85 @@ +/*#*************************************************************************** + * Visibility.h o o * + * o o * + * Visual Computing Group _ O _ * + * IEI Institute, CNUCE Institute, CNR Pisa \/)\/ * + * /\/| * + * Copyright(C) 1999 by Paolo Cignoni, Paolo Pingi, Claudio Rocchini | * + * All rights reserved. \ * + * * + * Permission to use, copy, modify, distribute and sell this software and * + * its documentation for any purpose is hereby granted without fee, provided * + * that the above copyright notice appear in all copies and that both that * + * copyright notice and this permission notice appear in supporting * + * documentation. the author makes no representations about the suitability * + * of this software for any purpose. It is provided "as is" without express * + * or implied warranty. * + * * + *****************************************************************************/ +/*#************************************************************************** + History + + 2003 Aug 26 First Working version + +****************************************************************************/ +#ifndef __VCG_SIMPLE_PIC +#define __VCG_SIMPLE_PIC +#include + +namespace vcg { + template + class SimplePic + {public: + std::vector img; + int sx,sy; + void Create(int tx,int ty) + { + sx=tx;sy=ty; + img.resize(sx*sy); + } + PixType &Pix(int x, int y) {return img[sx*y+x];} + + void OpenGLSnap(GLenum format=0) + { + int vp[4]; + glGetIntegerv( GL_VIEWPORT,vp ); // Lettura viewport + glPixelStorei( GL_PACK_ROW_LENGTH, 0); + glPixelStorei( GL_PACK_ALIGNMENT, 1); + int tx = vp[2]; + int ty = vp[3]; + + Create(tx,ty); + + GLenum mtype = 0; + + if(format==0) { + format = GL_RGBA; + mtype = GL_UNSIGNED_BYTE; + } + if(format==GL_DEPTH_COMPONENT) { + format = GL_DEPTH_COMPONENT; + mtype = GL_FLOAT; + } + glReadPixels(vp[0],vp[1],vp[2],vp[3],format,mtype,(GLvoid *)&img[0]); + } + bool SavePPM( const char * filename ) + { + FILE * fp = fopen(filename,"wb"); + if(fp==0) return false; + + + fprintf(fp,"P6\n%d %d\n255\n",sx,sy); + + for(int i=0;i +#include +#include "simplepic.h" +namespace vcg { + +template +void GenNormal(int vn, std::vector > &NN) +{ + typedef Point3 Point3x; + NN.clear(); + while(NN.size() class VisShader +{ + public : + enum {VisMax=MAXVIS}; + VisShader(MESH_TYPE &me):m(me) + { + CullFlag= false; + IsClosed = false; + ZTWIST=1e-3; + SplitNum=1; + + CameraViewing=false; + } + + typedef Point3 Point3x; + + typedef typename MESH_TYPE::CoordType CoordType; + typedef typename MESH_TYPE::ScalarType ScalarType; + typedef typename MESH_TYPE::VertexType VertexType; + typedef typename MESH_TYPE::VertexPointer VertexPointer; + typedef typename MESH_TYPE::VertexIterator VertexIterator; + typedef typename MESH_TYPE::FaceIterator FaceIterator; + typedef typename MESH_TYPE::FaceType FaceType; + typedef Matrix44 Matrix44x; + typedef Box3 Box3x; + +// The Basic Data the mesh and its wrapper; + MESH_TYPE &m; + + std::vector OMV; // Occluder Mesh Vector; + +// la visibilita' e' in float, per ogni entita' +// 1 significa che e' totalmente visibile per una data direzione. + + std::vector VV; + std::vector< Point3x > VN; // Vettore delle normali che ho usato per calcolare la mask e i float in W; + + // User defined parameters and flags + bool IsClosed; + float ZTWIST; + bool CullFlag; // Enable the frustum culling. Useful when the splitting value is larger than 2 + int SplitNum; + protected: + bool CameraViewing; + //Camera Cam; + public: + +/********************************************************/ +// Generic functions with Specialized code for every subclass + virtual void MapVisibility(float Gamma=1, float LowPass=0, float HighPass=1,bool FalseColor=false)=0; + //virtual void ApplyLightingEnvironment(std::vector &W, float Gamma); + + virtual int GLAccumPixel( std::vector &PixSeen)=0; + + virtual bool ReadVisibility(const char * /*filename*/){assert( 0); return false;} + virtual bool WriteVisibility(const char * /*filename*/){assert( 0); return false;} + +/********************************************************/ +// Generic functions with same code for every subclass + + void Clear() { fill(VV.begin(),VV.end(),0); } + + void InitGL() + { + glPushAttrib(GL_COLOR_BUFFER_BIT ); + ::glClearColor (1.0, 1.0, 1.0, 0.0); + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + } + + void RestoreGL() + { + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + glMatrixMode (GL_MODELVIEW); + glPopMatrix(); + glPopAttrib(); + } + + +/* + Funzione principale di conversione in visibilita' + Dati i due vettori PixSeen e PixNotSeen che indicano per ogni entita' (vertice o faccia) + quanti sono, rispettivamente, i pixel visibili e occlusi, + questa funzione calcola un valore float per ogni entita' che indica quanto e' visibile lungo una data direzione camera + == 1 significa completamente visibile + == 0 significa completamente occluso. + +*/ + void AddPixelCount(std::vector &_VV, const std::vector &PixSeen) + { + assert(_VV.size()==PixSeen.size()); + for(int i=0;i0) _VV[i]+= 1; + } + + + //void SetVisibilityMask(std::vector< std::bitset > &_VM, const std::vector &PixSeen, const int dir) + // { + // assert(_VM.size()==PixSeen.size()); + // for(int i=0;i0) _VM[i][dir]=true; + // } + +/******************************* +Funzioni ad alto livello che computano le Visibility Mask per varie distribuzioni di direzioni + + +*******************************/ + +// Funzione Generica chiamata da tutte le seguenti +void Compute( CallBack *cb) +{ + //cb(buf.format("Start to compute %i dir\n",VN.size())); + InitGL(); + VV.resize(m.vert.size()); + vector PixSeen(VV.size(),0); + + for(int i=0;i nvt; + GenNormal(nn*Frac,nvt); + ScalarType CosConeAngle=Cos(ConeAngleRad); + for(int i=0;i=CosConeAngle) VN.push_back(nvt[i]); + + printf("Asked %i normal, got %i normals\n",nn,VN.size()); + Compute(cb); +} + +void ComputeHalf(int nn, Point3x &dir, CallBack *cb) +{ + string buf; + + VN.clear(); + vector nvt; + GenNormal(nn*2,nvt); + for(int i=0;i0) VN.push_back(nvt[i]); + + printf("Asked %i normal, got %i normals\n",nn,VN.size()); + Compute(cb); +} + +void ComputeUniform(int nn, CallBack *cb) +{ + VN.clear(); + GenNormal(nn,VN); + char buf[256]; + sprintf(buf,"Asked %i normal, got %i normals\n",nn,VN.size()); + cb(buf); + Compute(cb); +} + +void ComputeSingle(Point3x &dir, CallBack *cb) +{ + VN.clear(); + VN.push_back(dir); + printf("Computing one direction (%f %f %f)\n",dir[0],dir[1],dir[2]); + Compute(cb); +} + +/**********************************************************/ + +int SplittedRendering(Point3x &ViewDir, std::vector &PixSeen, CallBack *cb=DummyCallBack) +{ + int tt=0; + int i,j; + for(i=0;i &PixSeen, CallBack *cb=DummyCallBack) +{ + int t0=clock(); + string buf; + + int added=SplittedRendering(BaseDir, PixSeen,cb); + int t1=clock(); + printf("ComputeSingleDir %i msec\n",t1-t0); +} + +void ComputeAverageVisibilityDirection() +{ + int i,j; + VD.resize(VM.size()); + for(j=0;j &msk=VM[j]; + for(i=0;i &LE, Point3x dir, ScalarType DegAngle1, ScalarType DegAngle2) +{ + LE.clear(); + LE.resize(VN.size(),0); + int i; + for(i=0;iDegAngle2) { LE[i]=0; continue; } + LE[i] = 1.0-(a-DegAngle1)/(DegAngle2-DegAngle1); + + } + // last step normalize the weights; + ScalarType sum=0; + for(i=0;i class VertexVisShader : public VisShader +{ + public : + + // Function Members + VertexVisShader(MESH_TYPE &me):VisShader(me) + { + // la mesh DEVE avere colore per vertice + if(! m.HasPerVertexColor()) assert(0); + } + + void Init() { VV.resize(m.vert.size()); AssignColorId(); } +// Vis::VisMode Id() {return Vis::VMPerVert;}; + void Compute(int nn); + + void AddPixelCount(std::vector &_VV, std::vector &PixSeen, std::vector &PixNotSeen ) + { + for(int i=0;iP()); + glVertex((*fi).V(1)->P()); + glVertex((*fi).V(2)->P()); + } + glEnd(); +} + +/***************************************************************************/ + +//VertexVisibility +// Funzione Principale restituisce per ogni entita' quanti px si vedono o no. +int GLAccumPixel( std::vector &PixSeen) +{ + SimplePic snapZ; + SimplePic snapC; + + glClearColor(Color4b::White); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT ); + glDisable(GL_LIGHTING); + glDepthRange(0.0f,1.0f); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + glDepthMask(GL_TRUE); + glDrawBuffer(GL_BACK); + glReadBuffer(GL_BACK); + + /////** Si disegnano le front face **///// + glDepthRange(2.0*ZTWIST,1.0f); +// glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glColor(Color4b::Red); + DrawFill(m); + snapC.OpenGLSnap(); + + // if(!IsClosed) // sono necessarie due passate in piu! + //{ + // /////** Si disegnano le back face shiftate in avanti di 2 epsilon **///// + // glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + // glColor(Color4b::Black); + // glCullFace(GL_FRONT); + // glDepthRange(0.0f,1.0f-2.0*ZTWIST); + // DrawFill(m); + // //glw.DrawFill(); + //} + //if(OMV.size()>0) + //{ + // /////** Si disegnano le back face shiftate in avanti di 2 epsilon **///// + // glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + // glColor(Color4b::Black); + // glDisable(GL_CULL_FACE); + // glDepthRange(0.0f,1.0f-2.0*ZTWIST); + // for(unsigned int i=0;iDrawFill(); + //} + int cnt=0; + snapZ.OpenGLSnap(GL_DEPTH_COMPONENT); + snapC.OpenGLSnap(); + double MM[16]; + glGetDoublev(GL_MODELVIEW_MATRIX,MM); + double MP[16]; + glGetDoublev(GL_PROJECTION_MATRIX,MP); + int VP[4]; + glGetIntegerv(GL_VIEWPORT,VP); + double tx,ty,tz; + for(int i=0;i=0 && tx=0 && ty VV2; + vector VC(VV.size(),1); + VV2=VV; + for(fi=m.face.begin();fi!=m.face.end();++fi) + for(int i=0;i<3;++i) + { + VV2[(*fi).V(i)-&*m.vert.begin()] += VV[(*fi).V1(i)-&*m.vert.begin()]; + ++VC[(*fi).V(i)-&*m.vert.begin()]; + } + + for(unsigned int i=0;iHighPass) gval=HighPass; + (*vi).C().SetGrayShade(pow((gval-LowPass)/(HighPass-LowPass),Gamma)); + } +} + +//void ApplyLightingEnvironment(std::vector &W, float Gamma=1) +// { +// assert(W.size()==VN.size()); +// MESH_TYPE::VertexIterator vi; +// +// for(vi=m.vert.begin();vi!=m.vert.end();++vi) +// { +// float gray=0; +// bitset &msk=VM[vi-m.vert.begin()]; +// for(int i=0;i