- bug fixing

- integration
- so on...
This commit is contained in:
Guido Ranzuglia granzuglia 2016-06-29 12:58:10 +00:00
parent bd33bba9e1
commit d311c3f2a6
56 changed files with 3502 additions and 3266 deletions

View File

@ -44,33 +44,33 @@ using namespace std;
bool AlignPair::A2Mesh::Import(const char *filename, Matrix44d &Tr)
{
int err = tri::io::Importer<A2Mesh>::Open(*this,filename);
if(err) {
printf("Error in reading %s: '%s'\n",filename,tri::io::Importer<A2Mesh>::ErrorMsg(err));
exit(-1);
if(err) {
printf("Error in reading %s: '%s'\n",filename,tri::io::Importer<A2Mesh>::ErrorMsg(err));
exit(-1);
}
printf("read mesh `%s'\n", filename);
return Init(Tr);
printf("read mesh `%s'\n", filename);
return Init(Tr);
}
bool AlignPair::A2Mesh::InitVert(const Matrix44d &Tr)
{
Matrix44d Idn; Idn.SetIdentity();
if(Tr!=Idn) tri::UpdatePosition<A2Mesh>::Matrix(*this,Tr);
tri::UpdateNormal<A2Mesh>::NormalizePerVertex(*this);
tri::UpdateBounding<A2Mesh>::Box(*this);
return true;
Matrix44d Idn; Idn.SetIdentity();
if(Tr!=Idn) tri::UpdatePosition<A2Mesh>::Matrix(*this,Tr);
tri::UpdateNormal<A2Mesh>::NormalizePerVertex(*this);
tri::UpdateBounding<A2Mesh>::Box(*this);
return true;
}
bool AlignPair::A2Mesh::Init(const Matrix44d &Tr)
{
Matrix44d Idn; Idn.SetIdentity();
tri::Clean<A2Mesh>::RemoveUnreferencedVertex(*this);
if(Tr!=Idn) tri::UpdatePosition<A2Mesh>::Matrix(*this,Tr);
tri::UpdateNormal<A2Mesh>::PerVertexNormalizedPerFaceNormalized(*this);
tri::UpdateFlags<A2Mesh>::FaceBorderFromNone(*this);
tri::UpdateBounding<A2Mesh>::Box(*this);
Matrix44d Idn; Idn.SetIdentity();
tri::Clean<A2Mesh>::RemoveUnreferencedVertex(*this);
if(Tr!=Idn) tri::UpdatePosition<A2Mesh>::Matrix(*this,Tr);
tri::UpdateNormal<A2Mesh>::PerVertexNormalizedPerFaceNormalized(*this);
tri::UpdateFlags<A2Mesh>::FaceBorderFromNone(*this);
tri::UpdateBounding<A2Mesh>::Box(*this);
return true;
return true;
}
@ -88,9 +88,9 @@ void AlignPair::Stat::clear()
bool AlignPair::Stat::Stable(int lastiter)
{
if(I.empty()) return false;
int parag = I.size()-lastiter;
int parag = I.size()-lastiter;
if(parag<0) parag=0;
if(parag<0) parag=0;
if( I.back().pcl50 < I[parag].pcl50 ) return false; // se siamo diminuiti non e' stabile
return true;
@ -100,19 +100,19 @@ bool AlignPair::Stat::Stable(int lastiter)
void AlignPair::Stat::Dump(FILE *fp)
{
if(I.size()==0) {
fprintf(fp,"Empty AlignPair::Stat\n");
return;
}
fprintf(fp,"Final Err %8.5f In %i iterations Total Time %ims\n",LastPcl50(),(int)I.size(),TotTime());
fprintf(fp,"Mindist Med Hi Avg RMS StdDev Time Tested Used Dist Bord Angl \n");
for(unsigned int qi=0;qi<I.size();++qi)
fprintf(fp,"%5.2f (%6.3f:%6.3f) (%6.3f %6.3f %6.3f) %4ims %5i %5i %4i+%4i+%4i\n",
I[qi].MinDistAbs,
I[qi].pcl50, I[qi].pclhi,
I[qi].AVG, I[qi].RMS, I[qi].StdDev ,
IterTime(qi),
I[qi].SampleTested,I[qi].SampleUsed,I[qi].DistanceDiscarded,I[qi].BorderDiscarded,I[qi].AngleDiscarded);
if(I.size()==0) {
fprintf(fp,"Empty AlignPair::Stat\n");
return;
}
fprintf(fp,"Final Err %8.5f In %i iterations Total Time %ims\n",LastPcl50(),(int)I.size(),TotTime());
fprintf(fp,"Mindist Med Hi Avg RMS StdDev Time Tested Used Dist Bord Angl \n");
for(unsigned int qi=0;qi<I.size();++qi)
fprintf(fp,"%5.2f (%6.3f:%6.3f) (%6.3f %6.3f %6.3f) %4ims %5i %5i %4i+%4i+%4i\n",
I[qi].MinDistAbs,
I[qi].pcl50, I[qi].pclhi,
I[qi].AVG, I[qi].RMS, I[qi].StdDev ,
IterTime(qi),
I[qi].SampleTested,I[qi].SampleUsed,I[qi].DistanceDiscarded,I[qi].BorderDiscarded,I[qi].AngleDiscarded);
}
// Scrive una tabella con tutti i valori
@ -120,14 +120,14 @@ void AlignPair::Stat::HTMLDump(FILE *fp)
{
fprintf(fp,"Final Err %8.5f In %i iterations Total Time %ims\n",LastPcl50(),(int)I.size(),TotTime());
fprintf(fp,"<table border>\n");
fprintf(fp,"<tr> <th>Mindist</th><th> 50ile </th><th> Hi </th><th> Avg </th><th> RMS </th><th> StdDev </th><th> Time </th><th> Tested </th><th> Used </th><th> Dist </th><th> Bord </th><th> Angl \n");
fprintf(fp,"<tr> <th>Mindist</th><th> 50ile </th><th> Hi </th><th> Avg </th><th> RMS </th><th> StdDev </th><th> Time </th><th> Tested </th><th> Used </th><th> Dist </th><th> Bord </th><th> Angl \n");
for(unsigned int qi=0;qi<I.size();++qi)
fprintf(fp,"<tr> <td> %8.5f </td><td align=\"right\"> %9.6f </td><td align=\"right\"> %8.5f </td><td align=\"right\"> %5.3f </td><td align=\"right\"> %8.5f </td><td align=\"right\"> %9.6f </td><td align=\"right\"> %4ims </td><td align=\"right\"> %5i </td><td align=\"right\"> %5i </td><td align=\"right\"> %4i </td><td align=\"right\"> %4i </td><td align=\"right\">%4i </td><td align=\"right\"></tr>\n",
I[qi].MinDistAbs,
fprintf(fp,"<tr> <td> %8.5f </td><td align=\"right\"> %9.6f </td><td align=\"right\"> %8.5f </td><td align=\"right\"> %5.3f </td><td align=\"right\"> %8.5f </td><td align=\"right\"> %9.6f </td><td align=\"right\"> %4ims </td><td align=\"right\"> %5i </td><td align=\"right\"> %5i </td><td align=\"right\"> %4i </td><td align=\"right\"> %4i </td><td align=\"right\">%4i </td><td align=\"right\"></tr>\n",
I[qi].MinDistAbs,
I[qi].pcl50, I[qi].pclhi,
I[qi].AVG, I[qi].RMS, I[qi].StdDev ,
IterTime(qi),
I[qi].SampleTested,I[qi].SampleUsed,I[qi].DistanceDiscarded,I[qi].BorderDiscarded,I[qi].AngleDiscarded);
I[qi].AVG, I[qi].RMS, I[qi].StdDev ,
IterTime(qi),
I[qi].SampleTested,I[qi].SampleUsed,I[qi].DistanceDiscarded,I[qi].BorderDiscarded,I[qi].AngleDiscarded);
fprintf(fp,"</table>\n");
}
@ -142,24 +142,24 @@ MinPointNum the minimum number of points that have to be chosen to be usable
*/
bool AlignPair::ChoosePoints( vector<Point3d> &Ps, // vertici corrispondenti su src (rossi)
vector<Point3d> &Ns, // normali corrispondenti su src (rossi)
vector<Point3d> &Pt, // vertici scelti su trg (verdi)
vector<Point3d> &OPt, // vertici scelti su trg (verdi)
double PassHi,
Histogramf &H)
vector<Point3d> &Ns, // normali corrispondenti su src (rossi)
vector<Point3d> &Pt, // vertici scelti su trg (verdi)
vector<Point3d> &OPt, // vertici scelti su trg (verdi)
double PassHi,
Histogramf &H)
{
const int N = ap.MaxPointNum;
double newmaxd = H.Percentile(PassHi);
double newmaxd = H.Percentile(PassHi);
//printf("%5.1f of the pairs has a distance less than %g and greater than %g (0..%g) avg %g\n", Perc*100,newmind,newmaxd,H.maxv,H.Percentile(.5));
int sz = Ps.size();
int fnd=0;
int lastgood=sz-1;
math::SubtractiveRingRNG myrnd;
math::SubtractiveRingRNG myrnd;
while(fnd<N && fnd<lastgood)
{
int index = fnd+myrnd.generate(lastgood-fnd);
double dd=Distance(Ps[index],Pt[index]);
if(dd<=newmaxd)
if(dd<=newmaxd)
{
swap(Ps[index],Ps[fnd]);
swap(Ns[index],Ns[fnd]);
@ -200,10 +200,10 @@ della mesh da muovere trasformata secondo la matrice <In>
Calcola anche il nuovo bounding box di tali vertici trasformati.
*/
bool AlignPair::InitMov(
vector< Point3d > &MovVert,
vector< Point3d > &MovNorm,
Box3d &trgbox,
const Matrix44d &in ) // trasformazione Iniziale (che porta i punti di trg su src)
vector< Point3d > &MovVert,
vector< Point3d > &MovNorm,
Box3d &trgbox,
const Matrix44d &in ) // trasformazione Iniziale (che porta i punti di trg su src)
{
Point3d pp,nn;
@ -224,34 +224,34 @@ bool AlignPair::InitMov(
}
bool AlignPair::InitFixVert(AlignPair::A2Mesh *fm,
AlignPair::Param &pp,
A2GridVert &u,
int PreferredGridSize)
AlignPair::Param &pp,
A2GridVert &u,
int PreferredGridSize)
{
Box3d bb2=fm->bbox;
double MinDist= pp.MinDistAbs*1.1;
//the bbox of the grid should be enflated of the mindist used in the ICP search
bb2.Offset(Point3d(MinDist,MinDist,MinDist));
Box3d bb2=fm->bbox;
double MinDist= pp.MinDistAbs*1.1;
//the bbox of the grid should be enflated of the mindist used in the ICP search
bb2.Offset(Point3d(MinDist,MinDist,MinDist));
u.SetBBox(bb2);
u.SetBBox(bb2);
//Inserisco la src nella griglia
if(PreferredGridSize==0) PreferredGridSize=fm->vert.size()*pp.UGExpansionFactor;
u.Set(fm->vert.begin(), fm->vert.end());//, PreferredGridSize);
printf("UG %i %i %i\n",u.siz[0],u.siz[1],u.siz[2]);
return true;
//Inserisco la src nella griglia
if(PreferredGridSize==0) PreferredGridSize=fm->vert.size()*pp.UGExpansionFactor;
u.Set(fm->vert.begin(), fm->vert.end());//, PreferredGridSize);
printf("UG %i %i %i\n",u.siz[0],u.siz[1],u.siz[2]);
return true;
}
bool AlignPair::InitFix(AlignPair::A2Mesh *fm,
AlignPair::Param &pp,
A2Grid &u,
int PreferredGridSize)
AlignPair::Param &pp,
A2Grid &u,
int PreferredGridSize)
{
tri::InitFaceIMark(*fm);
tri::InitFaceIMark(*fm);
Box3d bb2=fm->bbox;
// double MinDist= fm->bbox.Diag()*pp.MinDistPerc;
// double MinDist= fm->bbox.Diag()*pp.MinDistPerc;
double MinDist= pp.MinDistAbs*1.1;
//gonfio della distanza utente il BBox della seconda mesh
bb2.Offset(Point3d(MinDist,MinDist,MinDist));
@ -265,13 +265,13 @@ bool AlignPair::InitFix(AlignPair::A2Mesh *fm,
return true;
}
/*
The Main ICP alignment Function:
It assumes that:
we have two meshes:
- Fix the mesh that does not move and stays in the spatial indexing structure.
- Mov the mesh we 'move' e.g. the one for which we search the transforamtion.
The Main ICP alignment Function:
It assumes that:
we have two meshes:
- Fix the mesh that does not move and stays in the spatial indexing structure.
- Mov the mesh we 'move' e.g. the one for which we search the transforamtion.
requires normalize normals for vertexes AND faces
requires normalize normals for vertexes AND faces
Allinea due mesh;
Assume che:
la uniform grid sia gia' inizializzata con la mesh fix
@ -280,21 +280,21 @@ la uniform grid sia gia' inizializzata con la mesh fix
*/
bool AlignPair::Align(
A2Grid &u,
A2GridVert &uv,
const Matrix44d &in, // trasformazione Iniziale (che porta i punti di mov su fix)
Matrix44d &out, // trasformazione calcolata
vector<Point3d> &Pfix, // vertici corrispondenti su src (rossi)
vector<Point3d> &Nfix, // normali corrispondenti su src (rossi)
vector<Point3d> &OPmov, // vertici scelti su trg (verdi) prima della trasformazione in ingresso (Original Point Target)
vector<Point3d> &ONmov, // normali scelti su trg (verdi)
Histogramf &H,
AlignPair::Stat &as)
A2Grid &u,
A2GridVert &uv,
const Matrix44d &in, // trasformazione Iniziale (che porta i punti di mov su fix)
Matrix44d &out, // trasformazione calcolata
vector<Point3d> &Pfix, // vertici corrispondenti su src (rossi)
vector<Point3d> &Nfix, // normali corrispondenti su src (rossi)
vector<Point3d> &OPmov, // vertici scelti su trg (verdi) prima della trasformazione in ingresso (Original Point Target)
vector<Point3d> &ONmov, // normali scelti su trg (verdi)
Histogramf &H,
AlignPair::Stat &as)
{
vector<char> beyondCntVec; // vettore per marcare i movvert che sicuramente non si devono usare
// ogni volta che un vertice si trova a distanza oltre max dist viene incrementato il suo contatore;
// i movvert che sono stati scartati piu' di MaxCntDist volte non si guardano piu';
const int maxBeyondCnt=3;
vector<char> beyondCntVec; // vettore per marcare i movvert che sicuramente non si devono usare
// ogni volta che un vertice si trova a distanza oltre max dist viene incrementato il suo contatore;
// i movvert che sono stati scartati piu' di MaxCntDist volte non si guardano piu';
const int maxBeyondCnt=3;
vector< Point3d > movvert;
vector< Point3d > movnorm;
vector<Point3d> Pmov; // vertici scelti dopo la trasf iniziale
@ -316,7 +316,7 @@ bool AlignPair::Align(
beyondCntVec.resize(mov->size(),0);
/**************** BEGIN ICP LOOP ****************/
/**************** BEGIN ICP LOOP ****************/
do
{
Stat::IterInfo ii;
@ -330,134 +330,134 @@ bool AlignPair::Align(
ONmov.clear();
int tts0=clock();
ii.MinDistAbs=StartMinDist;
int LocSampleNum=min(ap.SampleNum,int(movvert.size()));
Box3d fixbox;
if(u.Empty()) fixbox = uv.bbox;
else fixbox = u.bbox;
for(i=0;i<LocSampleNum;++i)
{
if( beyondCntVec[i] < maxBeyondCnt ){
if(! fixbox.IsIn(movvert[i]) )
beyondCntVec[i]=maxBeyondCnt+1;
}
else
{
double error=StartMinDist;
Point3d closestPoint, closestNormal;
double maxd= StartMinDist;
ii.SampleTested++;
if(u.Empty()) // using the point cloud grid
int LocSampleNum=min(ap.SampleNum,int(movvert.size()));
Box3d fixbox;
if(u.Empty()) fixbox = uv.bbox;
else fixbox = u.bbox;
for(i=0;i<LocSampleNum;++i)
{
A2Mesh::VertexPointer vp = tri::GetClosestVertex(*fix,uv,movvert[i], maxd, error);
if(error>=StartMinDist) {
ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
}
if(movnorm[i].dot(vp->N()) < CosAngleThr) {
ii.AngleDiscarded++; continue;
}
closestPoint=vp->P();
closestNormal=vp->N();
}
else // using the standard faces and grid
{
A2Mesh::FacePointer f=vcg::tri::GetClosestFaceBase<vcg::AlignPair::A2Mesh, vcg::AlignPair::A2Grid >(*fix, u, movvert[i], maxd, error, closestPoint);
if(error>=StartMinDist) {
ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
}
if(movnorm[i].dot(f->N()) < CosAngleThr) {
ii.AngleDiscarded++; continue;
}
Point3d ip;
InterpolationParameters<A2Face,double>(*f,f->N(),closestPoint, ip);
const double IP_EPS = 0.00001;
// If ip[i] == 0 it means that we are on the edge opposite to i
if( (fabs(ip[0])<=IP_EPS && f->IsB(1)) || (fabs(ip[1])<=IP_EPS && f->IsB(2)) || (fabs(ip[2])<=IP_EPS && f->IsB(0)) ){
ii.BorderDiscarded++; continue;
}
closestNormal = f->N();
}
// The sample was accepted. Store it.
Pmov.push_back(movvert[i]);
OPmov.push_back((*mov)[i].P());
ONmov.push_back((*mov)[i].N());
Nfix.push_back( closestNormal );
Pfix.push_back( closestPoint );
H.Add(float(error));
ii.SampleUsed++;
}
} // End for each pmov
int tts1=clock();
if( beyondCntVec[i] < maxBeyondCnt ){
if(! fixbox.IsIn(movvert[i]) )
beyondCntVec[i]=maxBeyondCnt+1;
}
else
{
double error=StartMinDist;
Point3d closestPoint, closestNormal;
double maxd= StartMinDist;
ii.SampleTested++;
if(u.Empty()) // using the point cloud grid
{
A2Mesh::VertexPointer vp = tri::GetClosestVertex(*fix,uv,movvert[i], maxd, error);
if(error>=StartMinDist) {
ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
}
if(movnorm[i].dot(vp->N()) < CosAngleThr) {
ii.AngleDiscarded++; continue;
}
closestPoint=vp->P();
closestNormal=vp->N();
}
else // using the standard faces and grid
{
A2Mesh::FacePointer f=vcg::tri::GetClosestFaceBase<vcg::AlignPair::A2Mesh, vcg::AlignPair::A2Grid >(*fix, u, movvert[i], maxd, error, closestPoint);
if(error>=StartMinDist) {
ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
}
if(movnorm[i].dot(f->N()) < CosAngleThr) {
ii.AngleDiscarded++; continue;
}
Point3d ip;
InterpolationParameters<A2Face,double>(*f,f->N(),closestPoint, ip);
const double IP_EPS = 0.00001;
// If ip[i] == 0 it means that we are on the edge opposite to i
if( (fabs(ip[0])<=IP_EPS && f->IsB(1)) || (fabs(ip[1])<=IP_EPS && f->IsB(2)) || (fabs(ip[2])<=IP_EPS && f->IsB(0)) ){
ii.BorderDiscarded++; continue;
}
closestNormal = f->N();
}
// The sample was accepted. Store it.
Pmov.push_back(movvert[i]);
OPmov.push_back((*mov)[i].P());
ONmov.push_back((*mov)[i].N());
Nfix.push_back( closestNormal );
Pfix.push_back( closestPoint );
H.Add(float(error));
ii.SampleUsed++;
}
} // End for each pmov
int tts1=clock();
//printf("Found %d pairs\n",(int)Pfix.size());
if(!ChoosePoints(Pfix,Nfix,Pmov,OPmov,ap.PassHiFilter,H))
if(int(Pfix.size())<ap.MinPointNum)
{
status = TOO_FEW_POINTS;
if(!ChoosePoints(Pfix,Nfix,Pmov,OPmov,ap.PassHiFilter,H))
if(int(Pfix.size())<ap.MinPointNum)
{
status = TOO_FEW_POINTS;
ii.Time=clock();
as.I.push_back(ii);
return false;
}
Matrix44d newout;
switch(ap.MatchMode) {
case AlignPair::Param::MMSimilarity : ComputeRotoTranslationScalingMatchMatrix(newout,Pfix,OPmov); break;
case AlignPair::Param::MMRigid : ComputeRigidMatchMatrix(Pfix,OPmov,newout); break;
default :
status = UNKNOWN_MODE;
ii.Time=clock();
as.I.push_back(ii);
return false;
}
// double sum_before=0;
// double sum_after=0;
// for(unsigned int iii=0;iii<Pfix.size();++iii)
// {
// sum_before+=Distance(Pfix[iii], out*OPmov[iii]);
// sum_after+=Distance(Pfix[iii], newout*OPmov[iii]);
// }
// //printf("Distance %f -> %f\n",sum_before/double(Pfix.size()),sum_after/double(Pfix.size()) ) ;
// le passate successive utilizzano quindi come trasformazione iniziale questa appena trovata.
// Nei prossimi cicli si parte da questa matrice come iniziale.
out=newout;
assert(Pfix.size()==Pmov.size());
int tts2=clock();
ttsearch+=tts1-tts0;
ttleast +=tts2-tts1;
ii.pcl50=H.Percentile(.5);
ii.pclhi=H.Percentile(ap.PassHiFilter);
ii.AVG=H.Avg();
ii.RMS=H.RMS();
ii.StdDev=H.StandardDeviation();
ii.Time=clock();
as.I.push_back(ii);
return false;
}
Matrix44d newout;
switch(ap.MatchMode) {
case AlignPair::Param::MMSimilarity : ComputeRotoTranslationScalingMatchMatrix(newout,Pfix,OPmov); break;
case AlignPair::Param::MMRigid : ComputeRigidMatchMatrix(Pfix,OPmov,newout); break;
default :
status = UNKNOWN_MODE;
ii.Time=clock();
as.I.push_back(ii);
return false;
}
// double sum_before=0;
// double sum_after=0;
// for(unsigned int iii=0;iii<Pfix.size();++iii)
// {
// sum_before+=Distance(Pfix[iii], out*OPmov[iii]);
// sum_after+=Distance(Pfix[iii], newout*OPmov[iii]);
// }
// //printf("Distance %f -> %f\n",sum_before/double(Pfix.size()),sum_after/double(Pfix.size()) ) ;
// le passate successive utilizzano quindi come trasformazione iniziale questa appena trovata.
// Nei prossimi cicli si parte da questa matrice come iniziale.
out=newout;
assert(Pfix.size()==Pmov.size());
int tts2=clock();
ttsearch+=tts1-tts0;
ttleast +=tts2-tts1;
ii.pcl50=H.Percentile(.5);
ii.pclhi=H.Percentile(ap.PassHiFilter);
ii.AVG=H.Avg();
ii.RMS=H.RMS();
ii.StdDev=H.StandardDeviation();
ii.Time=clock();
as.I.push_back(ii);
nc++;
// The distance of the next points to be considered is lowered according to the <ReduceFactor> parameter.
// We use 5 times the <ReduceFactor> percentile of the found points.
if(ap.ReduceFactorPerc<1) StartMinDist=max(ap.MinDistAbs*ap.MinMinDistPerc, min(StartMinDist,5.0*H.Percentile(ap.ReduceFactorPerc)));
nc++;
// The distance of the next points to be considered is lowered according to the <ReduceFactor> parameter.
// We use 5 times the <ReduceFactor> percentile of the found points.
if(ap.ReduceFactorPerc<1) StartMinDist=max(ap.MinDistAbs*ap.MinMinDistPerc, min(StartMinDist,5.0*H.Percentile(ap.ReduceFactorPerc)));
}
while (
nc<=ap.MaxIterNum &&
H.Percentile(.5) > ap.TrgDistAbs &&
(nc<ap.EndStepNum+1 || ! as.Stable(ap.EndStepNum) )
);
/**************** END ICP LOOP ****************/
/**************** END ICP LOOP ****************/
int tt2=clock();
Matrix44d ResCopy=out;
Point3d scv,shv,rtv,trv;
Decompose(ResCopy,scv,shv,rtv,trv);
if((ap.MatchMode==vcg::AlignPair::Param::MMRigid) && (math::Abs(1-scv[0])>ap.MaxScale || math::Abs(1-scv[1])>ap.MaxScale || math::Abs(1-scv[2])>ap.MaxScale) ) {
status = TOO_MUCH_SCALE;
return false;
}
if((ap.MatchMode==vcg::AlignPair::Param::MMRigid) && (math::Abs(1-scv[0])>ap.MaxScale || math::Abs(1-scv[1])>ap.MaxScale || math::Abs(1-scv[2])>ap.MaxScale) ) {
status = TOO_MUCH_SCALE;
return false;
}
if(shv[0]>ap.MaxShear || shv[1]>ap.MaxShear || shv[2]>ap.MaxShear ) {
status = TOO_MUCH_SHEAR;
return false;
}
status = TOO_MUCH_SHEAR;
return false;
}
printf("Grid %i %i %i - fn %i\n",u.siz[0],u.siz[1],u.siz[2],fix->fn);
printf("Init %8.3f Loop %8.3f Search %8.3f least sqrt %8.3f\n",
float(tt1-tt0)/CLOCKS_PER_SEC, float(tt2-tt1)/CLOCKS_PER_SEC,
float(ttsearch)/CLOCKS_PER_SEC,float(ttleast)/CLOCKS_PER_SEC );
printf("Init %8.3f Loop %8.3f Search %8.3f least sqrt %8.3f\n",
float(tt1-tt0)/CLOCKS_PER_SEC, float(tt2-tt1)/CLOCKS_PER_SEC,
float(ttsearch)/CLOCKS_PER_SEC,float(ttleast)/CLOCKS_PER_SEC );
return true;
}
@ -467,17 +467,17 @@ bool AlignPair::Align(
const char *AlignPair::ErrorMsg( ErrorCode code)
{
switch(code){
case SUCCESS: return "Success ";
case NO_COMMON_BBOX : return "No Common BBox ";
case TOO_FEW_POINTS : return "Too few points ";
case LSQ_DIVERGE : return "LSQ not converge";
case TOO_MUCH_SHEAR : return "Too much shear ";
case TOO_MUCH_SCALE : return "Too much scale ";
case UNKNOWN_MODE : return "Unknown mode ";
default : assert(0); return "Catastrophic Error";
}
return 0;
switch(code){
case SUCCESS: return "Success ";
case NO_COMMON_BBOX : return "No Common BBox ";
case TOO_FEW_POINTS : return "Too few points ";
case LSQ_DIVERGE : return "LSQ not converge";
case TOO_MUCH_SHEAR : return "Too much shear ";
case TOO_MUCH_SCALE : return "Too much scale ";
case UNKNOWN_MODE : return "Unknown mode ";
default : assert(0); return "Catastrophic Error";
}
return 0;
}
/*
@ -491,131 +491,131 @@ Da controllare se ancora funge.
// Restituisce il numero di celle di sovrapposizione massimo trovato
int AlignPair::SearchTranslate(A2Grid &u,
const Matrix44d &BaseRot,
const int range,
const int step,
Point3d &BestTransV, // miglior vettore di spostamento
bool Verbose)
const Matrix44d &BaseRot,
const int range,
const int step,
Point3d &BestTransV, // miglior vettore di spostamento
bool Verbose)
{
const int wide1=(range*2+1);
const int wide2=wide1*wide1;
vector< Point3d > movvert;
vector< Point3d > movnorm;
Box3d movbox;
const int wide1=(range*2+1);
const int wide2=wide1*wide1;
vector< Point3d > movvert;
vector< Point3d > movnorm;
Box3d movbox;
int t0=clock();
InitMov(movvert,movnorm,movbox,BaseRot);
Point3i ip;
int i,ii,jj,kk;
vector<int> test((range*2+1)*(range*2+1)*(range*2+1),0);
//int bx,by,bz,ex,ey,ez;
int t0=clock();
InitMov(movvert,movnorm,movbox,BaseRot);
Point3i ip;
int i,ii,jj,kk;
vector<int> test((range*2+1)*(range*2+1)*(range*2+1),0);
//int bx,by,bz,ex,ey,ez;
Point3i b,e;
int testposii,testposjj;
for(i=0;i<movvert.size();++i)
{
if(u.bbox.IsIn(movvert[i])){
u.PToIP(movvert[i],ip);
b=ip+Point3i(-range,-range,-range);
e=ip+Point3i( range, range, range);
while(b[0]<0) b[0]+=step;
while(e[0]>=u.siz[0]) e[0]-=step;
while(b[1]<0) b[1]+=step;
while(e[1]>=u.siz[1]) e[1]-=step;
while(b[2]<0) b[2]+=step;
while(e[2]>=u.siz[2]) e[2]-=step;
Point3i b,e;
int testposii,testposjj;
for(i=0;i<movvert.size();++i)
{
if(u.bbox.IsIn(movvert[i])){
u.PToIP(movvert[i],ip);
b=ip+Point3i(-range,-range,-range);
e=ip+Point3i( range, range, range);
while(b[0]<0) b[0]+=step;
while(e[0]>=u.siz[0]) e[0]-=step;
while(b[1]<0) b[1]+=step;
while(e[1]>=u.siz[1]) e[1]-=step;
while(b[2]<0) b[2]+=step;
while(e[2]>=u.siz[2]) e[2]-=step;
for(ii=b[0];ii<=e[0];ii+=step)
{
testposii=(ii-ip[0]+range)*wide2;
for(jj=b[1];jj<=e[1];jj+=step)
{
testposjj=testposii+(jj-ip[1]+range)*wide1-ip[2]+range;
for(kk=b[2];kk<=e[2];kk+=step)
{
UGrid< A2Mesh::face_container >::UG ** g = u.Grid(ii,jj,kk);
//if((*(g+1))- (*g) >0)
if((*(g+1))!=(*g) )
++test[testposjj+kk];
assert(ii >=0 && ii < u.siz[0]);
assert(jj >=0 && jj < u.siz[1]);
assert(kk >=0 && kk < u.siz[2]);
}
}
}
}
}
int maxfnd=0;
Point3i BestI;
for(ii=-range;ii<=range;ii+=step)
for(jj=-range;jj<=range;jj+=step)
for(kk=-range;kk<=range;kk+=step)
{const int pos =(range+ii)*wide2+(range+jj)*wide1+range+kk;
if(test[pos]>maxfnd)
{
BestI=Point3i(ii,jj,kk);
BestTransV=Point3d(ii*u.voxel[0], jj*u.voxel[1], kk*u.voxel[2]);
maxfnd=test[pos];
}
//printf("Found %i su %i in %i\n",test[testcnt],movvert.size(),t1-t0);
}
for(ii=b[0];ii<=e[0];ii+=step)
{
testposii=(ii-ip[0]+range)*wide2;
for(jj=b[1];jj<=e[1];jj+=step)
{
testposjj=testposii+(jj-ip[1]+range)*wide1-ip[2]+range;
for(kk=b[2];kk<=e[2];kk+=step)
{
UGrid< A2Mesh::face_container >::UG ** g = u.Grid(ii,jj,kk);
//if((*(g+1))- (*g) >0)
if((*(g+1))!=(*g) )
++test[testposjj+kk];
assert(ii >=0 && ii < u.siz[0]);
assert(jj >=0 && jj < u.siz[1]);
assert(kk >=0 && kk < u.siz[2]);
}
}
}
}
}
int maxfnd=0;
Point3i BestI;
for(ii=-range;ii<=range;ii+=step)
for(jj=-range;jj<=range;jj+=step)
for(kk=-range;kk<=range;kk+=step)
{const int pos =(range+ii)*wide2+(range+jj)*wide1+range+kk;
if(test[pos]>maxfnd)
{
BestI=Point3i(ii,jj,kk);
BestTransV=Point3d(ii*u.voxel[0], jj*u.voxel[1], kk*u.voxel[2]);
maxfnd=test[pos];
}
//printf("Found %i su %i in %i\n",test[testcnt],movvert.size(),t1-t0);
}
int t1=clock();
if(Verbose) printf("BestTransl (%4i in %3ims) is %8.4f %8.4f %8.4f (%3i %3i %3i)\n",maxfnd,t1-t0,BestTransV[0],BestTransV[1],BestTransV[2],BestI[0],BestI[1],BestI[2]);
return maxfnd;
int t1=clock();
if(Verbose) printf("BestTransl (%4i in %3ims) is %8.4f %8.4f %8.4f (%3i %3i %3i)\n",maxfnd,t1-t0,BestTransV[0],BestTransV[1],BestTransV[2],BestI[0],BestI[1],BestI[2]);
return maxfnd;
}
#if 0
int AlignPair::SearchTranslate(UGrid< A2Mesh::face_container > &u,
vector< Point3d > &movvert,
vector< Point3d > &movnorm,
Box3d &movbox,
const Matrix44d &BaseRot,
const int range,
const int step,
Point3d &BestTransV, // miglior vettore di spostamento
bool Verbose)
vector< Point3d > &movvert,
vector< Point3d > &movnorm,
Box3d &movbox,
const Matrix44d &BaseRot,
const int range,
const int step,
Point3d &BestTransV, // miglior vettore di spostamento
bool Verbose)
{
const int wide1=(range*2+1);
const int wide2=wide1*wide1;
const int wide1=(range*2+1);
const int wide2=wide1*wide1;
int t0=clock();
InitMov(movvert,movnorm,movbox,BaseRot);
Point3i ip;
int i,ii,jj,kk;
vector<int> test((range*2+1)*(range*2+1)*(range*2+1),0);
for(i=0;i<movvert.size();++i)
{
if(u.bbox.IsIn(movvert[i])){
u.PToIP(movvert[i],ip);
for(ii=-range;ii<=range;ii+=step) if(ip[0]+ii>=0 && ip[0]+ii<u.siz[0])
for(jj=-range;jj<=range;jj+=step) if(ip[1]+jj>=0 && ip[1]+jj<u.siz[1])
for(kk=-range;kk<=range;kk+=step) if(ip[2]+kk>=0 && ip[2]+kk<u.siz[2])
{
UGrid< A2Mesh::face_container >::UG ** g = u.Grid(ip[0]+ii,ip[1]+jj,ip[2]+kk);
if((*(g+1))- (*g) >0)
++test[(range+ii)*wide2+(range+jj)*wide1+range+kk];
}
}
}
int maxfnd=0;
Point3i BestI;
for(ii=-range;ii<=range;ii+=step)
for(jj=-range;jj<=range;jj+=step)
for(kk=-range;kk<=range;kk+=step)
{const int pos =(range+ii)*wide2+(range+jj)*wide1+range+kk;
assert(test2[pos]==test[pos]);
if(test[pos]>maxfnd)
{
BestI=Point3i(ii,jj,kk);
BestTransV=Point3d(ii*u.voxel[0], jj*u.voxel[1], kk*u.voxel[2]);
maxfnd=test[pos];
}
//printf("Found %i su %i in %i\n",test[testcnt],movvert.size(),t1-t0);
}
int t0=clock();
InitMov(movvert,movnorm,movbox,BaseRot);
Point3i ip;
int i,ii,jj,kk;
vector<int> test((range*2+1)*(range*2+1)*(range*2+1),0);
for(i=0;i<movvert.size();++i)
{
if(u.bbox.IsIn(movvert[i])){
u.PToIP(movvert[i],ip);
for(ii=-range;ii<=range;ii+=step) if(ip[0]+ii>=0 && ip[0]+ii<u.siz[0])
for(jj=-range;jj<=range;jj+=step) if(ip[1]+jj>=0 && ip[1]+jj<u.siz[1])
for(kk=-range;kk<=range;kk+=step) if(ip[2]+kk>=0 && ip[2]+kk<u.siz[2])
{
UGrid< A2Mesh::face_container >::UG ** g = u.Grid(ip[0]+ii,ip[1]+jj,ip[2]+kk);
if((*(g+1))- (*g) >0)
++test[(range+ii)*wide2+(range+jj)*wide1+range+kk];
}
}
}
int maxfnd=0;
Point3i BestI;
for(ii=-range;ii<=range;ii+=step)
for(jj=-range;jj<=range;jj+=step)
for(kk=-range;kk<=range;kk+=step)
{const int pos =(range+ii)*wide2+(range+jj)*wide1+range+kk;
assert(test2[pos]==test[pos]);
if(test[pos]>maxfnd)
{
BestI=Point3i(ii,jj,kk);
BestTransV=Point3d(ii*u.voxel[0], jj*u.voxel[1], kk*u.voxel[2]);
maxfnd=test[pos];
}
//printf("Found %i su %i in %i\n",test[testcnt],movvert.size(),t1-t0);
}
int t1=clock();
if(Verbose) printf("BestTransl (%4i in %3ims) is %8.4f %8.4f %8.4f (%3i %3i %3i)\n",maxfnd,t1-t0,BestTransV[0],BestTransV[1],BestTransV[2],BestI[0],BestI[1],BestI[2]);
return maxfnd;
int t1=clock();
if(Verbose) printf("BestTransl (%4i in %3ims) is %8.4f %8.4f %8.4f (%3i %3i %3i)\n",maxfnd,t1-t0,BestTransV[0],BestTransV[1],BestTransV[2],BestI[0],BestI[1],BestI[2]);
return maxfnd;
}
*/
@ -627,9 +627,9 @@ bool AlignPair::SampleMovVert(vector<A2Vertex> &vert, int SampleNum, AlignPair::
{
switch(SampleMode)
{
case AlignPair::Param::SMRandom : return SampleMovVertRandom(vert,SampleNum);
case AlignPair::Param::SMNormalEqualized : return SampleMovVertNormalEqualized(vert,SampleNum);
default: assert(0);
case AlignPair::Param::SMRandom : return SampleMovVertRandom(vert,SampleNum);
case AlignPair::Param::SMNormalEqualized : return SampleMovVertNormalEqualized(vert,SampleNum);
default: assert(0);
}
return false;
}
@ -647,12 +647,12 @@ static int LocRnd(int n){
// Scelta a caso semplice
bool AlignPair::SampleMovVertRandom(vector<A2Vertex> &vert, int SampleNum)
{
if(int(vert.size())<=SampleNum) return true;
if(int(vert.size())<=SampleNum) return true;
int i;
for(i=0;i<SampleNum;++i)
{
int pos=LocRnd(vert.size());
assert(pos>=0 && pos < int(vert.size()));
assert(pos>=0 && pos < int(vert.size()));
swap(vert[i],vert[pos]);
}
vert.resize(SampleNum);
@ -673,49 +673,49 @@ e poi un punto all'interno del bucket
bool AlignPair::SampleMovVertNormalEqualized(vector<A2Vertex> &vert, int SampleNum)
{
// assert(0);
// assert(0);
// int t0=clock();
// int t0=clock();
static vector<Point3d> NV;
if(NV.size()==0)
{
GenNormal<double>::Uniform(30,NV);
printf("Generated %i normals\n",int(NV.size()));
}
{
GenNormal<double>::Fibonacci(30,NV);
printf("Generated %i normals\n",int(NV.size()));
}
// Bucket vector dove, per ogni normale metto gli indici
// dei vertici ad essa corrispondenti
vector<vector <int> > BKT(NV.size());
for(size_t i=0;i<vert.size();++i)
for(size_t i=0;i<vert.size();++i)
{
int ind=GenNormal<double>::BestMatchingNormal(vert[i].N(),NV);
int ind=GenNormal<double>::BestMatchingNormal(vert[i].N(),NV);
BKT[ind].push_back(i);
}
//int t1=clock();
//int t1=clock();
// vettore di contatori per sapere quanti punti ho gia' preso per ogni bucket
vector <int> BKTpos(BKT.size(),0);
if(SampleNum >= int(vert.size())) SampleNum= vert.size()-1;
if(SampleNum >= int(vert.size())) SampleNum= vert.size()-1;
for(int i=0;i<SampleNum;)
for(int i=0;i<SampleNum;)
{
int ind=LocRnd(BKT.size()); // Scelgo un Bucket
int &CURpos = BKTpos[ind];
vector<int> &CUR = BKT[ind];
if(CURpos<int(CUR.size()))
{
int ind=LocRnd(BKT.size()); // Scelgo un Bucket
int &CURpos = BKTpos[ind];
vector<int> &CUR = BKT[ind];
if(CURpos<int(CUR.size()))
{
swap(CUR[CURpos], CUR[ CURpos + LocRnd(BKT[ind].size()-CURpos)]);
swap(vert[i],vert[CUR[CURpos]]);
++BKTpos[ind];
swap(CUR[CURpos], CUR[ CURpos + LocRnd(BKT[ind].size()-CURpos)]);
swap(vert[i],vert[CUR[CURpos]]);
++BKTpos[ind];
++i;
}
}
}
vert.resize(SampleNum);
// int t2=clock();
// printf("Matching %6i\n",t1-t0);
// printf("Collecting %6i\n",t2-t1);
// printf("Total %6i\n",t2-t0);
// int t2=clock();
// printf("Matching %6i\n",t1-t0);
// printf("Collecting %6i\n",t2-t1);
// printf("Total %6i\n",t2-t0);
return true;
}

View File

@ -313,7 +313,7 @@ public:
void GenRotMatrix()
{
vector<Point3x> NV;
GenNormal<ScalarType>::Uniform(sqrt(float(pp.MatrixNum)),NV);
GenNormal<ScalarType>::Fibonacci(sqrt(float(pp.MatrixNum)),NV);
ScalarType AngleStep;
int AngleNum;

View File

@ -39,30 +39,32 @@
class GeometryAgingPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum {FP_ERODE};
public:
enum {FP_ERODE};
GeometryAgingPlugin();
virtual ~GeometryAgingPlugin();
GeometryAgingPlugin();
virtual ~GeometryAgingPlugin();
virtual QString filterInfo(FilterIDType filter) const;
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual QString filterName(FilterIDType filter) const;
virtual int getRequirements(QAction *) {return (MeshModel::MM_FACEMARK | MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV);}
virtual int getRequirements(QAction *) {return (MeshModel::MM_FACEMARK | MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV);}
virtual void initParameterSet(QAction *action, MeshModel &m, RichParameterSet &params);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet &params, vcg::CallBackPos *cb);
virtual FilterClass getClass(QAction *);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet &params, vcg::CallBackPos *cb);
virtual FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
protected:
void refineMesh(CMeshO &m, vcg::QualityEdgePred &ep, bool selection, vcg::CallBackPos *cb);
double generateNoiseValue(int Octaves, const CVertexO::CoordType &p);
bool faceIntersections(CMeshO &m, vcg::face::Pos<CMeshO::FaceType> p, vcg::GridStaticPtr<CFaceO, CMeshO::ScalarType> &gM);
void smoothPeaks(CMeshO &m, bool selected, bool updateErosionAttr);
void computeMeanCurvature(CMeshO &m);
protected:
void refineMesh(CMeshO &m, vcg::QualityEdgePred &ep, bool selection, vcg::CallBackPos *cb);
double generateNoiseValue(int Octaves, const CVertexO::CoordType &p);
bool faceIntersections(CMeshO &m, vcg::face::Pos<CMeshO::FaceType> p, vcg::GridStaticPtr<CFaceO, CMeshO::ScalarType> &gM);
void smoothPeaks(CMeshO &m, bool selected, bool updateErosionAttr);
void computeMeanCurvature(CMeshO &m);
};

View File

@ -44,8 +44,8 @@ static GLuint vs, fs, shdrID;
AmbientOcclusionPlugin::AmbientOcclusionPlugin()
{
typeList
<< FP_VERT_AMBIENT_OCCLUSION
<< FP_FACE_AMBIENT_OCCLUSION;
<< FP_VERT_AMBIENT_OCCLUSION
<< FP_FACE_AMBIENT_OCCLUSION;
foreach(FilterIDType tt , types())
actionList << new QAction(filterName(tt), this);
@ -71,7 +71,7 @@ QString AmbientOcclusionPlugin::filterName(FilterIDType filterId) const
{
case FP_VERT_AMBIENT_OCCLUSION : return QString("Ambient Occlusion - Per Vertex");
case FP_FACE_AMBIENT_OCCLUSION : return QString("Ambient Occlusion - Per Face");
default : assert(0);
default : assert(0);
}
return QString("");
@ -83,7 +83,7 @@ QString AmbientOcclusionPlugin::filterInfo(FilterIDType filterId) const
{
case FP_VERT_AMBIENT_OCCLUSION :
case FP_FACE_AMBIENT_OCCLUSION : return QString("Compute ambient occlusions values; it takes a number or well distributed view direction and for point of the surface it computes how many time it is visible from these directions. This number is saved into quality and automatically mapped into a gray shade. The average direction is saved into an attribute named 'BentNormal'");
default : assert(0);
default : assert(0);
}
return QString("");
@ -99,21 +99,21 @@ void AmbientOcclusionPlugin::initParameterSet(QAction *action, MeshModel &m, Ric
{
switch(ID(action))
{
case FP_FACE_AMBIENT_OCCLUSION:
case FP_VERT_AMBIENT_OCCLUSION:
parlst.addParam(new RichFloat("dirBias",0,"Directional Bias [0..1]","The balance between a uniform and a directionally biased set of lighting direction<br>:"
" - 0 means light came only uniformly from any direction<br>"
" - 1 means that all the light cames from the specified cone of directions <br>"
" - other values mix the two set of lighting directions "));
parlst.addParam(new RichInt ("reqViews",AMBOCC_DEFAULT_NUM_VIEWS,"Requested views", "Number of different views uniformly placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichPoint3f("coneDir",Point3f(0,1,0),"Lighting Direction", "Number of different views placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichFloat("coneAngle",30,"Cone amplitude", "Number of different views uniformly placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichBool("useGPU",AMBOCC_USEGPU_BY_DEFAULT,"Use GPU acceleration","In order to use GPU-Mode, your hardware must support FBOs, FP32 Textures and Shaders. Normally increases the performance by a factor of 4x-5x"));
parlst.addParam(new RichBool("useVBO",AMBOCC_USEVBO_BY_DEFAULT,"Use VBO if supported","By using VBO, Meshlab loads all the vertex structure in the VRam, greatly increasing rendering speed (for both CPU and GPU mode). Disable it if problem occurs"));
parlst.addParam(new RichInt ("depthTexSize",AMBOCC_DEFAULT_TEXTURE_SIZE,"Depth texture size(should be 2^n)", "Defines the depth texture size used to compute occlusion from each point of view. Higher values means better accuracy usually with low impact on performance"));
break;
default: break; // do not add any parameter for the other filters
}
case FP_FACE_AMBIENT_OCCLUSION:
case FP_VERT_AMBIENT_OCCLUSION:
parlst.addParam(new RichFloat("dirBias",0,"Directional Bias [0..1]","The balance between a uniform and a directionally biased set of lighting direction<br>:"
" - 0 means light came only uniformly from any direction<br>"
" - 1 means that all the light cames from the specified cone of directions <br>"
" - other values mix the two set of lighting directions "));
parlst.addParam(new RichInt ("reqViews",AMBOCC_DEFAULT_NUM_VIEWS,"Requested views", "Number of different views uniformly placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichPoint3f("coneDir",Point3f(0,1,0),"Lighting Direction", "Number of different views placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichFloat("coneAngle",30,"Cone amplitude", "Number of different views uniformly placed around the mesh. More views means better accuracy at the cost of increased calculation time"));
parlst.addParam(new RichBool("useGPU",AMBOCC_USEGPU_BY_DEFAULT,"Use GPU acceleration","In order to use GPU-Mode, your hardware must support FBOs, FP32 Textures and Shaders. Normally increases the performance by a factor of 4x-5x"));
//parlst.addParam(new RichBool("useVBO",AMBOCC_USEVBO_BY_DEFAULT,"Use VBO if supported","By using VBO, Meshlab loads all the vertex structure in the VRam, greatly increasing rendering speed (for both CPU and GPU mode). Disable it if problem occurs"));
parlst.addParam(new RichInt ("depthTexSize",AMBOCC_DEFAULT_TEXTURE_SIZE,"Depth texture size(should be 2^n)", "Defines the depth texture size used to compute occlusion from each point of view. Higher values means better accuracy usually with low impact on performance"));
break;
default: break; // do not add any parameter for the other filters
}
}
bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
@ -122,7 +122,6 @@ bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, Rich
else perFace = false;
useGPU = par.getBool("useGPU");
useVBO = par.getBool("useVBO");
depthTexSize = par.getInt("depthTexSize");
depthTexArea = depthTexSize*depthTexSize;
numViews = par.getInt("reqViews");
@ -132,7 +131,7 @@ bool AmbientOcclusionPlugin::applyFilter(QAction *filter, MeshDocument &md, Rich
float coneAngle = par.getFloat("coneAngle");
if(perFace)
m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
m.updateDataMask(MeshModel::MM_FACEQUALITY | MeshModel::MM_FACECOLOR);
else
m.updateDataMask(MeshModel::MM_VERTQUALITY | MeshModel::MM_VERTCOLOR);
@ -205,11 +204,13 @@ bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
glClearColor(0.0, 0.0, 0.0, 0.0);
if (useVBO)
{
m.glw.SetHint(vcg::GLW::HNUseVBO);
m.glw.Update();
}
//if (useVBO)
//{
// //m.glw.SetHint(vcg::GLW::HNUseVBO);
// //m.glw.Update();
//}
tri::UpdateQuality<CMeshO>::VertexConstant(m.cm,0);
@ -243,7 +244,14 @@ bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
glClear(GL_DEPTH_BUFFER_BIT);
glColorMask(0, 0, 0, 0);
m.glw.DrawFill<GLW::NMNone, GLW::CMNone, GLW::TMNone>();
MLRenderingData dt;
MLRenderingData::RendAtts atts;
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
dt.set(MLRenderingData::PR_SOLID,atts);
glContext->setRenderingData(m.id(),dt);
glContext->drawMeshModel(m.id());
glColorMask(1, 1, 1, 1);
glDisable(GL_POLYGON_OFFSET_FILL);
@ -259,7 +267,14 @@ bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
glClear(GL_DEPTH_BUFFER_BIT);
// FIRST PASS - fill depth buffer
glColorMask(0, 0, 0, 0);
m.glw.DrawFill<GLW::NMNone, GLW::CMNone, GLW::TMNone>();
MLRenderingData dt;
MLRenderingData::RendAtts atts;
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
dt.set(MLRenderingData::PR_SOLID,atts);
glContext->setRenderingData(m.id(),dt);
glContext->drawMeshModel(m.id());
glColorMask(1, 1, 1, 1);
glDisable(GL_POLYGON_OFFSET_FILL);
@ -279,20 +294,20 @@ bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
}
if(perFace)
{
tri::UpdateColor<CMeshO>::PerFaceQualityGray(m.cm);
CMeshO::FaceIterator fi;
for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi)
(*fi).Q()=(*fi).Q()/numViews;
} else {
tri::UpdateColor<CMeshO>::PerVertexQualityGray(m.cm,0.0f,0.0f);
CMeshO::VertexIterator vi;
for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi)
{
tri::UpdateColor<CMeshO>::PerFaceQualityGray(m.cm);
CMeshO::FaceIterator fi;
for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi)
(*fi).Q()=(*fi).Q()/numViews;
} else {
tri::UpdateColor<CMeshO>::PerVertexQualityGray(m.cm,0.0f,0.0f);
CMeshO::VertexIterator vi;
for(vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi)
{
(*vi).Q()=(*vi).Q()/numViews;
BN[vi].Normalize();
}
(*vi).Q()=(*vi).Q()/numViews;
BN[vi].Normalize();
}
}
Log(0,"Successfully calculated A.O. after %3.2f sec, %3.2f of which is due to initialization", ((float)tAll.elapsed()/1000.0f), ((float)tInitElapsed/1000.0f) );
@ -322,8 +337,9 @@ bool AmbientOcclusionPlugin::processGL(MeshModel &m, vector<Point3f> &posVect)
glDeleteTextures(1, &depthBufferTex);
if (useVBO)
m.glw.ClearHint(vcg::GLW::HNUseVBO);
glContext->meshAttributesUpdated(m.id(),true,MLRenderingData::RendAtts());
/*if (useVBO)
m.glw.ClearHint(vcg::GLW::HNUseVBO);*/
return true;
}
@ -432,9 +448,9 @@ void AmbientOcclusionPlugin::initGL(vcg::CallBackPos *cb, unsigned int numVertic
cb(30, "Initializing: Shaders and Textures");
if (maxTexPages == 4)
set_shaders(":/AmbientOcclusion/shaders/ambient_occlusion4",vs,fs,shdrID);
set_shaders(":/AmbientOcclusion/shaders/ambient_occlusion4",vs,fs,shdrID);
else
set_shaders(":/AmbientOcclusion/shaders/ambient_occlusion8",vs,fs,shdrID); //geforce 8+
set_shaders(":/AmbientOcclusion/shaders/ambient_occlusion8",vs,fs,shdrID); //geforce 8+
maxTexSize = smartTexSize;
@ -642,7 +658,7 @@ void AmbientOcclusionPlugin::setCamera(Point3f camDir, Box3m &meshBBox)
{
cameraDir.Import(camDir);
GLfloat d = (meshBBox.Diag()/2.0) * 1.1,
k = 0.1f;
k = 0.1f;
Point3f eye = Point3f::Construct(meshBBox.Center()) + camDir * (d+k);
glViewport(0.0, 0.0, depthTexSize, depthTexSize);
@ -654,8 +670,8 @@ void AmbientOcclusionPlugin::setCamera(Point3f camDir, Box3m &meshBBox)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.X(), eye.Y(), eye.Z(),
meshBBox.Center().X(), meshBBox.Center().Y(), meshBBox.Center().Z(),
0.0, 1.0, 0.0);
meshBBox.Center().X(), meshBBox.Center().Y(), meshBBox.Center().Z(),
0.0, 1.0, 0.0);
}
@ -716,10 +732,10 @@ void AmbientOcclusionPlugin::generateOcclusionHW()
// Screen-aligned Quad
glBegin(GL_QUADS);
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glEnd();
glUseProgram(0);
@ -740,22 +756,22 @@ void AmbientOcclusionPlugin::generateOcclusionSW(MeshModel &m)
glReadPixels(0, 0, depthTexSize, depthTexSize, GL_DEPTH_COMPONENT, GL_FLOAT, dFloat);
cameraDir.Normalize();
CMeshO::PerVertexAttributeHandle<Point3f> BN = tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "BentNormal");
CMeshO::PerVertexAttributeHandle<Point3f> BN = tri::Allocator<CMeshO>::GetPerVertexAttribute<Point3f>(m.cm, "BentNormal");
for (int i=0; i<m.cm.vn; ++i)
{
Point3<CMeshO::ScalarType> &vp = m.cm.vert[i].P();
gluProject(vp.X(), vp.Y(), vp.Z(),
(const GLdouble *) mvMatrix_f, (const GLdouble *) prMatrix_f, (const GLint *) viewpSize,
&resCoords[0], &resCoords[1], &resCoords[2] );
(const GLdouble *) mvMatrix_f, (const GLdouble *) prMatrix_f, (const GLint *) viewpSize,
&resCoords[0], &resCoords[1], &resCoords[2] );
int x = floor(resCoords[0]);
int y = floor(resCoords[1]);
if (resCoords[2] <= (GLdouble)dFloat[depthTexSize*y+x])
{
m.cm.vert[i].Q() += max(Point3f::Construct(m.cm.vert[i].cN()).dot(cameraDir), 0.0f);
BN[ m.cm.vert[i] ] += cameraDir;
m.cm.vert[i].Q() += max(Point3f::Construct(m.cm.vert[i].cN()).dot(cameraDir), 0.0f);
BN[ m.cm.vert[i] ] += cameraDir;
}
}
@ -780,8 +796,8 @@ void AmbientOcclusionPlugin::generateFaceOcclusionSW(MeshModel &m, vector<Point3
{
Point3f &vp = faceCenterVec[i];
gluProject(vp.X(), vp.Y(), vp.Z(),
(const GLdouble *) mvMatrix_f, (const GLdouble *) prMatrix_f, (const GLint *) viewpSize,
&resCoords[0], &resCoords[1], &resCoords[2] );
(const GLdouble *) mvMatrix_f, (const GLdouble *) prMatrix_f, (const GLint *) viewpSize,
&resCoords[0], &resCoords[1], &resCoords[2] );
int x = floor(resCoords[0]);
int y = floor(resCoords[1]);
@ -792,7 +808,7 @@ void AmbientOcclusionPlugin::generateFaceOcclusionSW(MeshModel &m, vector<Point3
}
}
delete [] dFloat;
delete [] dFloat;
}
void AmbientOcclusionPlugin::applyOcclusionHW(MeshModel &m)
@ -833,7 +849,7 @@ void AmbientOcclusionPlugin::set_shaders(char *shaderName, GLuint &v, GLuint &f,
fileName = fileName.left(fileName.size()-1);
fileName.append(".vert");
file.setFileName(fileName);
file.setFileName(fileName);
if (file.open(QIODevice::ReadOnly))
{
QTextStream ts(&file);
@ -850,7 +866,7 @@ void AmbientOcclusionPlugin::set_shaders(char *shaderName, GLuint &v, GLuint &f,
fileName = fileName.left(fileName.size()-5);
fileName.append(nMRT);
fileName.append(".frag");
file.setFileName(fileName);
file.setFileName(fileName);
if (file.open(QIODevice::ReadOnly))
{
QTextStream ts(&file);
@ -871,6 +887,7 @@ void AmbientOcclusionPlugin::set_shaders(char *shaderName, GLuint &v, GLuint &f,
glLinkProgram(pr);
}
void AmbientOcclusionPlugin::dumpFloatTexture(QString filename, float *texdata, int elems)
{
unsigned char *cdata = new unsigned char[elems];

View File

@ -35,83 +35,76 @@ class AmbientOcclusionPlugin : public QObject, public MeshFilterInterface
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
// Attributes
// Attributes
protected:
std::vector<vcg::Point3f> viewDirVec;
vcg::Point3f cameraDir;
GLuint fboDepth,
fboResult,
depthBufferTex,
vertexCoordTex,
vertexNormalsTex,
*resultBufferTex;
fboResult,
depthBufferTex,
vertexCoordTex,
vertexNormalsTex,
*resultBufferTex;
GLenum *resultBufferMRT,
colorFormat,
dataTypeFP;
colorFormat,
dataTypeFP;
unsigned int numViews,
depthTexArea,
numTexPages;
depthTexArea,
numTexPages;
bool useGPU,
useVBO,
errInit;
errInit;
bool perFace;
public:
unsigned int depthTexSize,
maxTexSize;
maxTexSize;
// Methods
// Methods
public:
enum { FP_VERT_AMBIENT_OCCLUSION,
FP_FACE_AMBIENT_OCCLUSION } ;
FP_FACE_AMBIENT_OCCLUSION } ;
AmbientOcclusionPlugin();
~AmbientOcclusionPlugin();
virtual QString filterName (FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filterId) const;
QString filterName(FilterIDType filter) const;
QString filterInfo(FilterIDType filterId) const;
virtual int getRequirements (QAction *action);
FILTER_ARITY filterArity(QAction*) const
{
return SINGLE_MESH;
}
virtual FilterClass getClass(QAction *filter)
int getRequirements (QAction *action);
FilterClass getClass(QAction *filter)
{
if(ID(filter)==FP_FACE_AMBIENT_OCCLUSION) return MeshFilterInterface::FaceColoring;
else return MeshFilterInterface::VertexColoring;
};
virtual void initParameterSet(QAction *,
MeshModel &/*m*/,
RichParameterSet & /*parent*/);
virtual bool applyFilter (QAction *filter,
MeshDocument &md,
RichParameterSet & /*parent*/,
vcg::CallBackPos * cb) ;
void initTextures (void);
void initGL (vcg::CallBackPos *cb,
unsigned int numVertices);
bool processGL (MeshModel &m, std::vector<vcg::Point3f> &posVect);
bool checkFramebuffer();
void initParameterSet(QAction *,MeshModel &/*m*/,RichParameterSet & /*parent*/);
bool applyFilter(QAction *filter,MeshDocument &md,RichParameterSet & /*parent*/,vcg::CallBackPos * cb) ;
void initTextures(void);
void initGL(vcg::CallBackPos *cb,unsigned int numVertices);
bool processGL(MeshModel &m, std::vector<vcg::Point3f> &posVect);
bool checkFramebuffer();
void vertexCoordsToTexture (MeshModel &m);
void vertexCoordsToTexture(MeshModel &m);
void setCamera (vcg::Point3f camDir,
Box3m &meshBBox);
void setCamera(vcg::Point3f camDir,Box3m &meshBBox);
void generateOcclusionHW ();
void generateOcclusionSW (MeshModel &m);
void generateFaceOcclusionSW(MeshModel &m, std::vector<vcg::Point3f> & faceCenterVec);
void generateOcclusionHW();
void generateOcclusionSW(MeshModel &m);
void generateFaceOcclusionSW(MeshModel &m, std::vector<vcg::Point3f> & faceCenterVec);
void applyOcclusionHW (MeshModel &m);
void applyOcclusionSW (MeshModel &m,
GLfloat *aoValues);
void applyOcclusionHW(MeshModel &m);
void applyOcclusionSW(MeshModel &m,GLfloat *aoValues);
void set_shaders (char *shaderName,
GLuint &vs,
GLuint &fs,
GLuint &pr);
void set_shaders(char *shaderName,GLuint &vs,GLuint &fs,GLuint &pr);
void dumpFloatTexture(QString filename, float *texdata, int elems);
private:

View File

@ -110,7 +110,7 @@ bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParamet
MeshModel *movMesh= par.getMesh("movMesh");
MeshModel *sampleMesh= 0;
bool showSample = par.getBool("showSample");
if(showSample) sampleMesh = md.addOrGetMesh("sample","sample",false, RenderMode(vcg::GLW::DMPoints));
if(showSample) sampleMesh = md.addOrGetMesh("sample","sample",false);
tri::UpdateNormal<CMeshO>::NormalizePerVertex(fixMesh->cm);
tri::UpdateNormal<CMeshO>::NormalizePerVertex(movMesh->cm);
tri::Clean<CMeshO>::RemoveUnreferencedVertex(fixMesh->cm);
@ -180,7 +180,7 @@ bool FilterAutoalign::applyFilter(QAction *filter, MeshDocument &md, RichParamet
sort(ResultVec.begin(),ResultVec.end());
movMesh->cm.Tr.Import(ResultVec.back().m);
tri::Build(sample->cm,GG.movVertBase);
tri::BuildMeshFromCoordVector(sample->cm,GG.movVertBase);
sample->cm.Tr.Import(ResultVec.back().m);
qDebug("Result %i",ResultVec.back().score);

View File

@ -45,6 +45,7 @@ class FilterAutoalign : public QObject, public MeshFilterInterface
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &m, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction *) const {return FIXED;}
};
#endif

View File

@ -44,6 +44,7 @@ public:
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction *) const {return VARIABLE;}
};
#endif

View File

@ -34,24 +34,24 @@ using namespace vcg;
FilterCameraPlugin::FilterCameraPlugin()
{
typeList <<
FP_SET_MESH_CAMERA <<
FP_SET_RASTER_CAMERA <<
FP_QUALITY_FROM_CAMERA <<
FP_CAMERA_ROTATE<<
FP_CAMERA_SCALE<<
FP_CAMERA_TRANSLATE<<
FP_CAMERA_TRANSFORM <<
FP_CAMERA_EDIT <<
FP_ORIENT_NORMALS_WITH_CAMERAS;
FP_SET_MESH_CAMERA <<
FP_SET_RASTER_CAMERA <<
FP_QUALITY_FROM_CAMERA <<
FP_CAMERA_ROTATE<<
FP_CAMERA_SCALE<<
FP_CAMERA_TRANSLATE<<
FP_CAMERA_TRANSFORM <<
FP_CAMERA_EDIT <<
FP_ORIENT_NORMALS_WITH_CAMERAS;
foreach(FilterIDType tt , types())
actionList << new QAction(filterName(tt), this);
foreach(FilterIDType tt , types())
actionList << new QAction(filterName(tt), this);
}
// ST() return the very short string describing each filtering action
QString FilterCameraPlugin::filterName(FilterIDType filterId) const
{
switch(filterId) {
switch(filterId) {
case FP_SET_MESH_CAMERA : return QString("Set Mesh Camera");
case FP_SET_RASTER_CAMERA : return QString("Set Raster Camera");
case FP_QUALITY_FROM_CAMERA : return QString("Vertex Quality from Camera");
@ -62,399 +62,399 @@ QString FilterCameraPlugin::filterName(FilterIDType filterId) const
case FP_CAMERA_EDIT : return QString("Edit Raster Camera");
case FP_ORIENT_NORMALS_WITH_CAMERAS:return QString("Reorient vertex normals using cameras");
default : assert(0);
}
}
}
// Info() return the longer string describing each filtering action
QString FilterCameraPlugin::filterInfo(FilterIDType filterId) const
{
switch(filterId) {
switch(filterId) {
case FP_SET_MESH_CAMERA : return QString("This filter allow to set a shot for the current mesh");
case FP_SET_RASTER_CAMERA : return QString("This filter allow to set a shot for the current mesh");
case FP_QUALITY_FROM_CAMERA : return QString("Compute vertex quality using the camera definition, according to viewing angle or distance");
case FP_CAMERA_ROTATE : return QString("Rotate the camera, or all the cameras of the project. The selected raster is the reference if viewpoint rotation is selected.");
case FP_CAMERA_SCALE : return QString("Scale the camera, or all the cameras of the project. The selected raster is the reference if viewpoint scaling is selected.");
case FP_CAMERA_TRANSLATE : return QString("Translate the camera, or all the cameras of the project.");
case FP_CAMERA_TRANSFORM : return QString("Transform the camera extrinsics, or all the cameras of the project.");
case FP_CAMERA_EDIT : return QString("Allow to edit the current raster camera allowing to tweak intrinsics.");
case FP_CAMERA_TRANSLATE : return QString("Translate the camera, or all the cameras of the project.");
case FP_CAMERA_TRANSFORM : return QString("Transform the camera extrinsics, or all the cameras of the project.");
case FP_CAMERA_EDIT : return QString("Allow to edit the current raster camera allowing to tweak intrinsics.");
case FP_ORIENT_NORMALS_WITH_CAMERAS:return QString("Reorient vertex normals using cameras. For this filter to work the mesh needs to have the attribute 'correspondences' which is only created when loading Bundler files (.out projects)");
default : assert(0);
}
}
}
// This function define the needed parameters for each filter.
void FilterCameraPlugin::initParameterSet(QAction *action, MeshDocument &/*m*/, RichParameterSet & parlst)
{
Shotf defShot;
switch(ID(action))
{
case FP_CAMERA_EDIT :
parlst.addParam(new RichDynamicFloat("fov_scale", 0, -3,3,"Scaling exp", "Exponent of the scaling factor. 0 means no scaling, 1 means 10 times larger, -1 means 1/10."));
break;
case FP_CAMERA_ROTATE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
QStringList rotMethod;
rotMethod.push_back("X axis");
rotMethod.push_back("Y axis");
rotMethod.push_back("Z axis");
rotMethod.push_back("custom axis");
parlst.addParam(new RichEnum("rotAxis", 0, rotMethod, tr("Rotation on:"), tr("Choose a method")));
QStringList rotCenter;
rotCenter.push_back("origin");
rotCenter.push_back("camera viewpoint");
rotCenter.push_back("custom point");
parlst.addParam(new RichEnum("rotCenter", 0, rotCenter, tr("Center of rotation:"), tr("Choose a method")));
parlst.addParam(new RichDynamicFloat("angle",0,-360,360,"Rotation Angle","Angle of rotation (in <b>degree</b>). If snapping is enable this vaule is rounded according to the snap value"));
parlst.addParam(new RichPoint3f("customAxis",Point3f(0,0,0),"Custom axis","This rotation axis is used only if the 'custom axis' option is chosen."));
parlst.addParam(new RichPoint3f("customCenter",Point3f(0,0,0),"Custom center","This rotation center is used only if the 'custom point' option is chosen."));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
case FP_CAMERA_SCALE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
QStringList scaleCenter;
scaleCenter.push_back("origin");
scaleCenter.push_back("camera viewpoint");
scaleCenter.push_back("custom point");
parlst.addParam(new RichEnum("scaleCenter", 0, scaleCenter, tr("Center of scaling:"), tr("Choose a method")));
parlst.addParam(new RichPoint3f("customCenter",Point3f(0,0,0),"Custom center","This scaling center is used only if the 'custom point' option is chosen."));
parlst.addParam(new RichFloat("scale", 1.0, "Scale factor", "The scale factor that has to be applied to the camera"));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
case FP_CAMERA_TRANSLATE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
parlst.addParam(new RichDynamicFloat("axisX",0,-1000,1000,"X Axis","Absolute translation amount along the X axis"));
parlst.addParam(new RichDynamicFloat("axisY",0,-1000,1000,"Y Axis","Absolute translation amount along the Y axis"));
parlst.addParam(new RichDynamicFloat("axisZ",0,-1000,1000,"Z Axis","Absolute translation amount along the Z axis"));
parlst.addParam(new RichBool("centerFlag",false,"translate viewpoint position to the origin","If selected, the camera viewpoint is translated to the origin"));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
Shotf defShot;
switch(ID(action))
{
case FP_CAMERA_EDIT :
parlst.addParam(new RichDynamicFloat("fov_scale", 0, -3,3,"Scaling exp", "Exponent of the scaling factor. 0 means no scaling, 1 means 10 times larger, -1 means 1/10."));
break;
case FP_CAMERA_ROTATE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
QStringList rotMethod;
rotMethod.push_back("X axis");
rotMethod.push_back("Y axis");
rotMethod.push_back("Z axis");
rotMethod.push_back("custom axis");
parlst.addParam(new RichEnum("rotAxis", 0, rotMethod, tr("Rotation on:"), tr("Choose a method")));
QStringList rotCenter;
rotCenter.push_back("origin");
rotCenter.push_back("camera viewpoint");
rotCenter.push_back("custom point");
parlst.addParam(new RichEnum("rotCenter", 0, rotCenter, tr("Center of rotation:"), tr("Choose a method")));
parlst.addParam(new RichDynamicFloat("angle",0,-360,360,"Rotation Angle","Angle of rotation (in <b>degree</b>). If snapping is enable this vaule is rounded according to the snap value"));
parlst.addParam(new RichPoint3f("customAxis",Point3f(0,0,0),"Custom axis","This rotation axis is used only if the 'custom axis' option is chosen."));
parlst.addParam(new RichPoint3f("customCenter",Point3f(0,0,0),"Custom center","This rotation center is used only if the 'custom point' option is chosen."));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
case FP_CAMERA_SCALE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
QStringList scaleCenter;
scaleCenter.push_back("origin");
scaleCenter.push_back("camera viewpoint");
scaleCenter.push_back("custom point");
parlst.addParam(new RichEnum("scaleCenter", 0, scaleCenter, tr("Center of scaling:"), tr("Choose a method")));
parlst.addParam(new RichPoint3f("customCenter",Point3f(0,0,0),"Custom center","This scaling center is used only if the 'custom point' option is chosen."));
parlst.addParam(new RichFloat("scale", 1.0, "Scale factor", "The scale factor that has to be applied to the camera"));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
case FP_CAMERA_TRANSLATE :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
parlst.addParam(new RichDynamicFloat("axisX",0,-1000,1000,"X Axis","Absolute translation amount along the X axis"));
parlst.addParam(new RichDynamicFloat("axisY",0,-1000,1000,"Y Axis","Absolute translation amount along the Y axis"));
parlst.addParam(new RichDynamicFloat("axisZ",0,-1000,1000,"Z Axis","Absolute translation amount along the Z axis"));
parlst.addParam(new RichBool("centerFlag",false,"translate viewpoint position to the origin","If selected, the camera viewpoint is translated to the origin"));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break;
case FP_CAMERA_TRANSFORM :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
QStringList behaviour;
behaviour.push_back("The matrix is the transformation to apply to the extrinsics");
behaviour.push_back("The matrix represent the new extrinsics");
case FP_CAMERA_TRANSFORM :
{
QStringList shotType;
shotType.push_back("Raster Camera");
shotType.push_back("Mesh Camera");
QStringList behaviour;
behaviour.push_back("The matrix is the transformation to apply to the extrinsics");
behaviour.push_back("The matrix represent the new extrinsics");
Matrix44m mat; mat.SetIdentity();
parlst.addParam(new RichMatrix44f("TransformMatrix",mat,""));
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
parlst.addParam(new RichEnum("behaviour", 0, behaviour, tr("Matrix semantic"), tr("What the matrix is used for")));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
Matrix44m mat; mat.SetIdentity();
parlst.addParam(new RichMatrix44f("TransformMatrix",mat,""));
parlst.addParam(new RichEnum("camera", 0, shotType, tr("Camera type"), tr("Choose the camera to scale")));
parlst.addParam(new RichEnum("behaviour", 0, behaviour, tr("Matrix semantic"), tr("What the matrix is used for")));
parlst.addParam(new RichBool ("toallRaster", false, "Apply to all Raster layers", "Apply the same scaling to all the Raster layers: it is taken into account only if 'Raster Camera' is selected"));
parlst.addParam(new RichBool ("toall", false, "Apply to all Raster and Mesh layers", "Apply the same scaling to all the layers, including any 3D layer"));
}
break; case FP_SET_RASTER_CAMERA :
parlst.addParam(new RichShotf ("Shot", defShot, "New shot", "This filter allow to set a shot for the current raster."));
break;
}
break; case FP_SET_RASTER_CAMERA :
parlst.addParam(new RichShotf ("Shot", defShot, "New shot", "This filter allow to set a shot for the current raster."));
break;
case FP_SET_MESH_CAMERA :
parlst.addParam(new RichShotf ("Shot", defShot, "New shot", "This filter allow to set a shot for the current mesh."));
break;
case FP_QUALITY_FROM_CAMERA :
parlst.addParam(new RichBool ("Depth", true, "Depth", "Use depth as a factor."));
parlst.addParam(new RichBool ("Facing", false, "ViewAngle", "Use cosine of viewing angle as a factor."));
parlst.addParam(new RichBool ("Clip", false, "Clipping", "clip values outside the viewport to zero."));
parlst.addParam(new RichBool("normalize",false,"normalize","if checked normalize all quality values in range [0..1]"));
parlst.addParam(new RichBool("map",false,"map into color", "if checked map quality generated values into per-vertex color"));
break;
default: break; // do not add any parameter for the other filters
}
case FP_SET_MESH_CAMERA :
parlst.addParam(new RichShotf ("Shot", defShot, "New shot", "This filter allow to set a shot for the current mesh."));
break;
case FP_QUALITY_FROM_CAMERA :
parlst.addParam(new RichBool ("Depth", true, "Depth", "Use depth as a factor."));
parlst.addParam(new RichBool ("Facing", false, "ViewAngle", "Use cosine of viewing angle as a factor."));
parlst.addParam(new RichBool ("Clip", false, "Clipping", "clip values outside the viewport to zero."));
parlst.addParam(new RichBool("normalize",false,"normalize","if checked normalize all quality values in range [0..1]"));
parlst.addParam(new RichBool("map",false,"map into color", "if checked map quality generated values into per-vertex color"));
break;
default: break; // do not add any parameter for the other filters
}
}
// Core Function doing the actual mesh processing.
bool FilterCameraPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos */*cb*/)
{
CMeshO &cm=md.mm()->cm;
RasterModel *rm = md.rm();
CMeshO &cm=md.mm()->cm;
RasterModel *rm = md.rm();
switch(ID(filter))
{
case FP_CAMERA_ROTATE :
{
Matrix44m trRot; trRot.SetIdentity();
Point3m axis, tranVec;
Matrix44m trTran,trTranInv;
switch(par.getEnum("rotAxis"))
case FP_CAMERA_ROTATE :
{
Matrix44m trRot; trRot.SetIdentity();
Point3m axis, tranVec;
Matrix44m trTran,trTranInv;
switch(par.getEnum("rotAxis"))
{
case 0: axis=Point3m(1,0,0); break;
case 1: axis=Point3m(0,1,0);break;
case 2: axis=Point3m(0,0,1);break;
case 3: axis=par.getPoint3m("customAxis");break;
}
switch(par.getEnum("rotCenter"))
{
}
switch(par.getEnum("rotCenter"))
{
case 0: tranVec=Point3m(0,0,0); break;
case 1: {
switch(par.getEnum("camera"))
{
case 0: tranVec=rm->shot.Extrinsics.Tra();
break;
case 1: tranVec=cm.shot.Extrinsics.Tra();
}
switch(par.getEnum("camera"))
{
case 0: tranVec=rm->shot.Extrinsics.Tra();
break;
case 1: tranVec=cm.shot.Extrinsics.Tra();
}
break;
}
break;
case 2: tranVec=par.getPoint3m("customCenter");break;
}
float angleDeg= par.getDynamicFloat("angle");
trRot.SetRotateDeg(angleDeg,axis);
trTran.SetTranslate(tranVec);
trTranInv.SetTranslate(-tranVec);
//cm.Tr=trTran*trRot*trTranInv;
Matrix44m transf=trTran*trRot*trTranInv;
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr=transf;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(transf);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(transf);
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(transf);
float angleDeg= par.getDynamicFloat("angle");
trRot.SetRotateDeg(angleDeg,axis);
trTran.SetTranslate(tranVec);
trTranInv.SetTranslate(-tranVec);
//cm.Tr=trTran*trRot*trTranInv;
Matrix44m transf=trTran*trRot*trTranInv;
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr=transf;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(transf);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(transf);
}
}
}
else switch(par.getEnum("camera"))
{
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(transf);
}
}
else switch(par.getEnum("camera"))
{
case 0:
{
rm->shot.ApplyRigidTransformation(transf);
rm->shot.ApplyRigidTransformation(transf);
}
case 1:
case 1:
{
cm.shot.ApplyRigidTransformation(transf);
cm.shot.ApplyRigidTransformation(transf);
}
}
}
}
break;
case FP_CAMERA_SCALE :
{
Matrix44m trScale; trScale.SetIdentity();
Point3m tranVec;
Matrix44m trTran,trTranInv;
float Scale= par.getFloat("scale");
trScale.SetScale(Scale,Scale,Scale);
switch(par.getEnum("scaleCenter"))
break;
case FP_CAMERA_SCALE :
{
Matrix44m trScale; trScale.SetIdentity();
Point3m tranVec;
Matrix44m trTran,trTranInv;
float Scale= par.getFloat("scale");
trScale.SetScale(Scale,Scale,Scale);
switch(par.getEnum("scaleCenter"))
{
case 0: tranVec=Point3m(0,0,0); break;
case 1:
{
switch(par.getEnum("camera"))
{
case 0: tranVec=rm->shot.Extrinsics.Tra();
break;
case 1: tranVec=cm.shot.Extrinsics.Tra();
case 0: tranVec=rm->shot.Extrinsics.Tra();
break;
case 1: tranVec=cm.shot.Extrinsics.Tra();
}
}
break;
case 2: tranVec=par.getPoint3m("customCenter");break;
}
}
trTran.SetTranslate(tranVec);
trTranInv.SetTranslate(-tranVec);
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
trTran.SetTranslate(tranVec);
trTranInv.SetTranslate(-tranVec);
if (par.getBool("toall"))
{
md.meshList[i]->cm.Tr=trTran*trScale*trTranInv;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTran);
md.meshList[i]->cm.shot.RescalingWorld(trScale[0][0], false);
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTranInv);
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr=trTran*trScale*trTranInv;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTran);
md.meshList[i]->cm.shot.RescalingWorld(trScale[0][0], false);
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTranInv);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
md.rasterList[i]->shot.RescalingWorld(trScale[0][0], false);
md.rasterList[i]->shot.ApplyRigidTransformation(trTranInv);
}
}
for (int i=0; i<md.rasterList.size(); i++)
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
md.rasterList[i]->shot.RescalingWorld(trScale[0][0], false);
md.rasterList[i]->shot.ApplyRigidTransformation(trTranInv);
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
md.rasterList[i]->shot.RescalingWorld(trScale[0][0], false);
md.rasterList[i]->shot.ApplyRigidTransformation(trTranInv);
}
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
for (int i=0; i<md.rasterList.size(); i++)
else switch(par.getEnum("camera"))
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
md.rasterList[i]->shot.RescalingWorld(trScale[0][0], false);
md.rasterList[i]->shot.ApplyRigidTransformation(trTranInv);
}
}
else switch(par.getEnum("camera"))
{
case 0:
{
rm->shot.ApplyRigidTransformation(trTran);
rm->shot.RescalingWorld(Scale, false);
rm->shot.ApplyRigidTransformation(trTranInv);
rm->shot.ApplyRigidTransformation(trTran);
rm->shot.RescalingWorld(Scale, false);
rm->shot.ApplyRigidTransformation(trTranInv);
}
case 1:
case 1:
{
cm.shot.ApplyRigidTransformation(trTran);
cm.shot.RescalingWorld(Scale, false);
cm.shot.ApplyRigidTransformation(trTranInv);
cm.shot.ApplyRigidTransformation(trTran);
cm.shot.RescalingWorld(Scale, false);
cm.shot.ApplyRigidTransformation(trTranInv);
}
}
}
break;
case FP_CAMERA_TRANSLATE :
{
Matrix44m trTran; trTran.SetIdentity();
float xScale= par.getDynamicFloat("axisX");
float yScale= par.getDynamicFloat("axisY");
float zScale= par.getDynamicFloat("axisZ");
trTran.SetTranslate(xScale,yScale,zScale);
if(par.getBool("centerFlag"))
switch(par.getEnum("camera"))
{
case 0: trTran.SetTranslate(-rm->shot.Extrinsics.Tra());
break;
case 1: trTran.SetTranslate(-cm.shot.Extrinsics.Tra());
}
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr=trTran;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTran);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
break;
case FP_CAMERA_TRANSLATE :
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
Matrix44m trTran; trTran.SetIdentity();
float xScale= par.getDynamicFloat("axisX");
float yScale= par.getDynamicFloat("axisY");
float zScale= par.getDynamicFloat("axisZ");
trTran.SetTranslate(xScale,yScale,zScale);
if(par.getBool("centerFlag"))
switch(par.getEnum("camera"))
{
case 0: trTran.SetTranslate(-rm->shot.Extrinsics.Tra());
break;
case 1: trTran.SetTranslate(-cm.shot.Extrinsics.Tra());
}
}
else switch(par.getEnum("camera"))
{
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr=trTran;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerVertexMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplyRigidTransformation(trTran);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplyRigidTransformation(trTran);
}
}
else switch(par.getEnum("camera"))
{
case 0:
{
rm->shot.ApplyRigidTransformation(trTran);
rm->shot.ApplyRigidTransformation(trTran);
}
case 1:
case 1:
{
cm.shot.ApplyRigidTransformation(trTran);
cm.shot.ApplyRigidTransformation(trTran);
}
}
}
break;
case FP_CAMERA_TRANSFORM :
{
Matrix44m mat,inv;
inv.SetIdentity();
Point3m tra;
mat = par.getMatrix44m("TransformMatrix");
if(par.getEnum("behaviour") == 1){
inv = rm->shot.Extrinsics.Rot();
tra = inv * rm->shot.Extrinsics.Tra();
inv[0][3] = -tra[0];
inv[1][3] = -tra[1];
inv[2][3] = -tra[2];
mat = mat * inv;
mat = inv;
}
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr = mat;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplySimilarity(mat);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplySimilarity(mat);
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
break;
case FP_CAMERA_TRANSFORM :
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplySimilarity(mat);
Matrix44m mat,inv;
inv.SetIdentity();
Point3m tra;
mat = par.getMatrix44m("TransformMatrix");
if(par.getEnum("behaviour") == 1){
inv = rm->shot.Extrinsics.Rot();
tra = inv * rm->shot.Extrinsics.Tra();
inv[0][3] = -tra[0];
inv[1][3] = -tra[1];
inv[2][3] = -tra[2];
mat = mat * inv;
mat = inv;
}
}
else switch(par.getEnum("camera"))
{
if (par.getBool("toall"))
{
for (int i=0; i<md.meshList.size(); i++)
{
md.meshList[i]->cm.Tr = mat;
tri::UpdatePosition<CMeshO>::Matrix(md.meshList[i]->cm, md.meshList[i]->cm.Tr);
tri::UpdateNormal<CMeshO>::PerFaceMatrix(md.meshList[i]->cm,md.meshList[i]->cm.Tr);
tri::UpdateBounding<CMeshO>::Box(md.meshList[i]->cm);
md.meshList[i]->cm.Tr.SetIdentity();
md.meshList[i]->cm.shot.ApplySimilarity(mat);
}
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplySimilarity(mat);
}
}
else if (par.getBool("toallRaster") && (par.getEnum("camera")==0))
{
for (int i=0; i<md.rasterList.size(); i++)
{
md.rasterList[i]->shot.ApplySimilarity(mat);
}
}
else switch(par.getEnum("camera"))
{
case 0:
{
rm->shot.ApplyRigidTransformation(mat);
rm->shot.ApplyRigidTransformation(mat);
}
case 1:
case 1:
{
cm.shot.ApplyRigidTransformation(mat);
cm.shot.ApplyRigidTransformation(mat);
}
}
}
}
break;
break;
case FP_SET_RASTER_CAMERA :
{
case FP_SET_RASTER_CAMERA :
{
Shotm shotGot=par.getShotm("Shot");
rm->shot = shotGot;
float ratio=(float)rm->currentPlane->image.height()/(float)shotGot.Intrinsics.ViewportPx[1];
@ -464,77 +464,77 @@ bool FilterCameraPlugin::applyFilter(QAction *filter, MeshDocument &md, RichPara
rm->shot.Intrinsics.PixelSizeMm[0]/=ratio;
rm->shot.Intrinsics.CenterPx[0]=(int)((float)rm->shot.Intrinsics.ViewportPx[0]/2.0);
rm->shot.Intrinsics.CenterPx[1]=(int)((float)rm->shot.Intrinsics.ViewportPx[1]/2.0);
}
break;
}
break;
case FP_SET_MESH_CAMERA :
cm.shot = par.getShotm("Shot");
break;
cm.shot = par.getShotm("Shot");
break;
case FP_QUALITY_FROM_CAMERA :
{
if(!cm.shot.IsValid())
{
this->errorMessage="Mesh has not a valid camera";
return false;
}
md.mm()->updateDataMask(MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR);
bool clipFlag = par.getBool("Clip");
bool depthFlag = par.getBool("Depth");
bool facingFlag = par.getBool("Facing");
CMeshO::VertexIterator vi;
float deltaN = cm.bbox.Diag()/100.0f;
for(vi=cm.vert.begin();vi!=cm.vert.end();++vi)
{
Point2m pp = cm.shot.Project( (*vi).P());
float depth = cm.shot.Depth((*vi).P());
Point3m pc = cm.shot.ConvertWorldToCameraCoordinates((*vi).P());
Point3m pn = cm.shot.ConvertWorldToCameraCoordinates((*vi).P()+(*vi).N()*deltaN);
float q=1.0;
if(depthFlag) q*=depth;
if(facingFlag) q*=pn[2]-pc[2];
if(clipFlag)
if(!cm.shot.IsValid())
{
if(pp[0]<0 || pp[1]<0 ||
pp[0]>cm.shot.Intrinsics.ViewportPx[0] || pp[1]>cm.shot.Intrinsics.ViewportPx[1])
q=0;
this->errorMessage="Mesh has not a valid camera";
return false;
}
(*vi).Q() = q;
}
if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::VertexNormalize(cm);
if(par.getBool("map")) tri::UpdateColor<CMeshO>::PerVertexQualityRamp(cm);
md.mm()->updateDataMask(MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR);
bool clipFlag = par.getBool("Clip");
bool depthFlag = par.getBool("Depth");
bool facingFlag = par.getBool("Facing");
CMeshO::VertexIterator vi;
float deltaN = cm.bbox.Diag()/100.0f;
for(vi=cm.vert.begin();vi!=cm.vert.end();++vi)
{
Point2m pp = cm.shot.Project( (*vi).P());
float depth = cm.shot.Depth((*vi).P());
Point3m pc = cm.shot.ConvertWorldToCameraCoordinates((*vi).P());
Point3m pn = cm.shot.ConvertWorldToCameraCoordinates((*vi).P()+(*vi).N()*deltaN);
float q=1.0;
}
break;
if(depthFlag) q*=depth;
if(facingFlag) q*=pn[2]-pc[2];
if(clipFlag)
{
if(pp[0]<0 || pp[1]<0 ||
pp[0]>cm.shot.Intrinsics.ViewportPx[0] || pp[1]>cm.shot.Intrinsics.ViewportPx[1])
q=0;
}
(*vi).Q() = q;
}
if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::VertexNormalize(cm);
if(par.getBool("map")) tri::UpdateColor<CMeshO>::PerVertexQualityRamp(cm);
case FP_ORIENT_NORMALS_WITH_CAMERAS:
{
struct Correspondence{unsigned int id_img;float padding[3];};
typedef vector<Correspondence> CorrVec;
CMeshO::PerVertexAttributeHandle<CorrVec> ch =
vcg::tri::Allocator<CMeshO>::FindPerVertexAttribute<CorrVec>(cm,"correspondences");
if(!vcg::tri::Allocator<CMeshO>::IsValidHandle<CorrVec>(cm,ch)){
this->errorMessage="Vertices have no associated camera.\n This filter works only for point clouds loaded within a Bundler project (.out)";
return false;
}
for(CMeshO::VertexIterator vi= cm.vert.begin(); vi != cm.vert.end();++vi){
unsigned int camera_id = ch[*vi][0].id_img;
Point3m n=md.rasterList[camera_id]->shot.GetViewPoint()-(*vi).P() ;
if( n*(*vi).cN()<0)
(*vi). N()=-(*vi).cN();
}
}
break;
}
case FP_ORIENT_NORMALS_WITH_CAMERAS:
{
struct Correspondence{unsigned int id_img;float padding[3];};
typedef vector<Correspondence> CorrVec;
CMeshO::PerVertexAttributeHandle<CorrVec> ch =
vcg::tri::Allocator<CMeshO>::FindPerVertexAttribute<CorrVec>(cm,"correspondences");
if(!vcg::tri::Allocator<CMeshO>::IsValidHandle<CorrVec>(cm,ch)){
this->errorMessage="Vertices have no associated camera.\n This filter works only for point clouds loaded within a Bundler project (.out)";
return false;
}
for(CMeshO::VertexIterator vi= cm.vert.begin(); vi != cm.vert.end();++vi){
unsigned int camera_id = ch[*vi][0].id_img;
Point3m n=md.rasterList[camera_id]->shot.GetViewPoint()-(*vi).P() ;
if( n*(*vi).cN()<0)
(*vi). N()=-(*vi).cN();
}
}
break;
}
return true;
}
int FilterCameraPlugin::postCondition(QAction * filter) const
{
switch (ID(filter))
{
switch (ID(filter))
{
case FP_SET_MESH_CAMERA :
case FP_CAMERA_ROTATE :
case FP_CAMERA_TRANSLATE :
@ -544,46 +544,65 @@ int FilterCameraPlugin::postCondition(QAction * filter) const
case FP_QUALITY_FROM_CAMERA :
return MeshModel::MM_VERTQUALITY + MeshModel::MM_VERTCOLOR;
default : return MeshModel::MM_UNKNOWN;
}
}
}
FilterCameraPlugin::FilterClass FilterCameraPlugin::getClass(QAction *a)
FilterCameraPlugin::FilterClass FilterCameraPlugin::getClass(QAction *a)
{
switch(ID(a))
{
case FP_CAMERA_ROTATE :
case FP_CAMERA_SCALE :
case FP_CAMERA_TRANSLATE :
case FP_CAMERA_EDIT :
case FP_CAMERA_TRANSFORM:
case FP_SET_MESH_CAMERA :
case FP_QUALITY_FROM_CAMERA :
return MeshFilterInterface::Camera;
case FP_SET_RASTER_CAMERA :
return FilterClass (MeshFilterInterface::Camera + MeshFilterInterface::RasterLayer) ;
case FP_ORIENT_NORMALS_WITH_CAMERAS:
return MeshFilterInterface::Camera;
}
assert(0);
switch(ID(a))
{
case FP_CAMERA_ROTATE :
case FP_CAMERA_SCALE :
case FP_CAMERA_TRANSLATE :
case FP_CAMERA_EDIT :
case FP_CAMERA_TRANSFORM:
case FP_SET_MESH_CAMERA :
case FP_QUALITY_FROM_CAMERA :
return MeshFilterInterface::Camera;
case FP_SET_RASTER_CAMERA :
return FilterClass (MeshFilterInterface::Camera + MeshFilterInterface::RasterLayer) ;
case FP_ORIENT_NORMALS_WITH_CAMERAS:
return MeshFilterInterface::Camera;
}
assert(0);
}
int FilterCameraPlugin::getPreConditions( QAction * a) const
{
switch(ID(a))
{
case FP_CAMERA_ROTATE :
case FP_CAMERA_SCALE :
case FP_CAMERA_TRANSLATE :
case FP_CAMERA_EDIT :
case FP_CAMERA_TRANSFORM:
case FP_QUALITY_FROM_CAMERA :
case FP_SET_RASTER_CAMERA :
case FP_SET_MESH_CAMERA :
int FilterCameraPlugin::getPreConditions( QAction * a) const
{
switch(ID(a))
{
case FP_CAMERA_ROTATE :
case FP_CAMERA_SCALE :
case FP_CAMERA_TRANSLATE :
case FP_CAMERA_EDIT :
case FP_CAMERA_TRANSFORM:
case FP_QUALITY_FROM_CAMERA :
case FP_SET_RASTER_CAMERA :
case FP_SET_MESH_CAMERA :
return MeshModel::MM_NONE;
case FP_ORIENT_NORMALS_WITH_CAMERAS:
case FP_ORIENT_NORMALS_WITH_CAMERAS:
return MeshModel::MM_VERTNORMAL;
}
assert(0);
}
}
assert(0);
}
MeshFilterInterface::FILTER_ARITY FilterCameraPlugin::filterArity( QAction* act ) const
{
switch(ID(act))
{
case FP_CAMERA_ROTATE :
case FP_CAMERA_SCALE :
case FP_CAMERA_TRANSLATE :
case FP_CAMERA_EDIT :
case FP_CAMERA_TRANSFORM:
case FP_QUALITY_FROM_CAMERA :
case FP_SET_RASTER_CAMERA :
return SINGLE_MESH;
case FP_SET_MESH_CAMERA :
return SINGLE_MESH;
case FP_ORIENT_NORMALS_WITH_CAMERAS:
return SINGLE_MESH;
}
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterCameraPlugin)

View File

@ -53,6 +53,7 @@ public:
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction* act) const;
};
#endif

View File

@ -29,51 +29,52 @@
class CleanFilter : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
/* naming convention :
- FP -> Filter Plugin
- name of the plugin separated by _
*/
enum {
FP_BALL_PIVOTING,
FP_REMOVE_ISOLATED_COMPLEXITY,
FP_REMOVE_ISOLATED_DIAMETER,
FP_REMOVE_WRT_Q,
FP_REMOVE_TVERTEX_FLIP,
FP_SNAP_MISMATCHED_BORDER,
FP_REMOVE_TVERTEX_COLLAPSE,
FP_REMOVE_FOLD_FACE,
FP_REMOVE_DUPLICATE_FACE,
FP_REMOVE_NON_MANIF_EDGE,
FP_REMOVE_NON_MANIF_VERT,
FP_MERGE_CLOSE_VERTEX,
FP_COMPACT_VERT,
FP_COMPACT_FACE
} ;
/* default values for standard parameters' values of the plugin actions */
public:
/* naming convention :
- FP -> Filter Plugin
- name of the plugin separated by _
*/
enum {
FP_BALL_PIVOTING,
FP_REMOVE_ISOLATED_COMPLEXITY,
FP_REMOVE_ISOLATED_DIAMETER,
FP_REMOVE_WRT_Q,
FP_REMOVE_TVERTEX_FLIP,
FP_SNAP_MISMATCHED_BORDER,
FP_REMOVE_TVERTEX_COLLAPSE,
FP_REMOVE_FOLD_FACE,
FP_REMOVE_DUPLICATE_FACE,
FP_REMOVE_NON_MANIF_EDGE,
FP_REMOVE_NON_MANIF_VERT,
FP_MERGE_CLOSE_VERTEX,
FP_COMPACT_VERT,
FP_COMPACT_FACE
} ;
/* default values for standard parameters' values of the plugin actions */
float maxDiag1;
float maxDiag2;
int minCC;
float val1;
CleanFilter();
~CleanFilter();
CleanFilter();
~CleanFilter();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual FilterClass getClass(QAction *);
virtual int getRequirements(QAction *);
virtual FilterClass getClass(QAction *);
virtual int getRequirements(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
};

View File

@ -29,27 +29,29 @@
class FilterColorProjectionPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum { FP_SINGLEIMAGEPROJ, FP_MULTIIMAGETRIVIALPROJ, FP_MULTIIMAGETRIVIALPROJTEXTURE };
enum { FP_SINGLEIMAGEPROJ, FP_MULTIIMAGETRIVIALPROJ, FP_MULTIIMAGETRIVIALPROJTEXTURE };
FilterColorProjectionPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
int postCondition( QAction* ) const;
FilterColorProjectionPlugin();
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual int getRequirements(QAction *);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
int postCondition( QAction* ) const;
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual int getRequirements(QAction *);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
private:
int calculateNearFarAccurate(MeshDocument &md, std::vector<float> *near, std::vector<float> *far);
int calculateNearFarAccurate(MeshDocument &md, std::vector<float> *near, std::vector<float> *far);
};

View File

@ -187,7 +187,7 @@ int RenderHelper::initializeMeshBuffers(MeshModel *mesh, vcg::CallBackPos *cb)
return 0;
}
void RenderHelper::renderScene(Shotm &view, MeshModel *mesh, RenderingMode mode, float camNear = 0, float camFar = 0)
void RenderHelper::renderScene(Shotm &view, MeshModel *mesh, RenderingMode mode, MLPluginGLContext* plugcontext, float camNear, float camFar)
{
int wt = view.Intrinsics.ViewportPx[0];
int ht = view.Intrinsics.ViewportPx[1];
@ -241,46 +241,44 @@ void RenderHelper::renderScene(Shotm &view, MeshModel *mesh, RenderingMode mode,
int program = programs[rendmode];
glDisable(GL_LIGHTING);
//bind indices
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
MLRenderingData dt;
MLRenderingData::RendAtts atts;
MLPerViewGLOptions opts;
//bind vertices
glEnable(GL_COLOR_MATERIAL);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glEnableClientState(GL_VERTEX_ARRAY); // activate vertex coords array
glVertexPointer(3, GL_FLOAT, 0, 0); // last param is offset, not ptr
//glDisable(GL_LIGHTING);
err = glGetError();
////bind indices
//glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
////bind vertices
//glEnable(GL_COLOR_MATERIAL);
//glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
//glEnableClientState(GL_VERTEX_ARRAY); // activate vertex coords array
//glVertexPointer(3, GL_FLOAT, 0, 0); // last param is offset, not ptr
//err = glGetError();
glUseProgram(program);
err = glGetError();
if(use_colors)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cbo);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
}
if(use_normals)
{
glBindBufferARB(GL_ARRAY_BUFFER_ARB, nbo);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, 0);
}
err = glGetError();
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = use_normals;
atts[MLRenderingData::ATT_NAMES::ATT_VERTCOLOR] = use_colors;
if (mesh->cm.fn > 0)
{
glDrawElements(GL_TRIANGLES, mesh->cm.fn*3, GL_UNSIGNED_INT, (void *)0);
opts._persolid_noshading = true;
dt.set(MLRenderingData::PR_SOLID,atts);
}
else
{
glDrawArrays(GL_POINTS, 0, mesh->cm.vn);
opts._perpoint_noshading = true;
dt.set(MLRenderingData::PR_POINTS,atts);
}
dt.set(opts);
plugcontext->setRenderingData(mesh->id(),dt);
plugcontext->drawMeshModel(mesh->id());
if(color != NULL) delete []color;
if(depth != NULL) delete []depth;

View File

@ -61,7 +61,7 @@ class RenderHelper {
int initializeMeshBuffers(MeshModel *mesh, vcg::CallBackPos *cb);
// draw & readback
void renderScene(Shotm &view, MeshModel *mesh, RenderingMode mode, float camNear, float camFar);
void renderScene(Shotm &view, MeshModel *mesh, RenderingMode mode, MLPluginGLContext* plugcontext, float camNear = 0, float camFar = 0);
private:

File diff suppressed because it is too large Load Diff

View File

@ -57,9 +57,9 @@ public:
ExtraMeshColorizePlugin();
~ExtraMeshColorizePlugin(){}
QString filterName(FilterIDType filter) const;
QString filterInfo(FilterIDType filterId) const;
FILTER_ARITY filterArity(QAction* ) const;
QString filterName(FilterIDType filter) const;
QString filterInfo(FilterIDType filterId) const;
int getPreConditions(QAction *) const;
int postCondition( QAction* ) const;
FilterClass getClass(QAction *);

View File

@ -512,4 +512,30 @@ int FilterColorProc::getPreConditions( QAction * filter ) const
}
}
MeshFilterInterface::FILTER_ARITY FilterColorProc::filterArity( QAction *act ) const
{
switch(ID(act))
{
case CP_FILLING :
case CP_COLOURISATION :
case CP_PERLIN_COLOR :
case CP_COLOR_NOISE :
case CP_THRESHOLDING :
case CP_BRIGHTNESS :
case CP_CONTRAST :
case CP_CONTR_BRIGHT :
case CP_GAMMA :
case CP_INVERT :
case CP_EQUALIZE :
case CP_DESATURATION :
case CP_WHITE_BAL :
case CP_LEVELS :
return MeshFilterInterface::SINGLE_MESH;
case CP_SCATTER_PER_MESH:
return MeshFilterInterface::VARIABLE;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterColorProc)

View File

@ -30,40 +30,41 @@
class FilterColorProc : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum { CP_FILLING,
CP_THRESHOLDING,
CP_BRIGHTNESS,
CP_CONTRAST,
CP_CONTR_BRIGHT,
CP_GAMMA,
CP_LEVELS,
CP_INVERT,
CP_COLOURISATION,
CP_DESATURATION,
CP_WHITE_BAL,
CP_EQUALIZE,
CP_PERLIN_COLOR,
CP_COLOR_NOISE,
CP_SCATTER_PER_MESH
};
public:
enum { CP_FILLING,
CP_THRESHOLDING,
CP_BRIGHTNESS,
CP_CONTRAST,
CP_CONTR_BRIGHT,
CP_GAMMA,
CP_LEVELS,
CP_INVERT,
CP_COLOURISATION,
CP_DESATURATION,
CP_WHITE_BAL,
CP_EQUALIZE,
CP_PERLIN_COLOR,
CP_COLOR_NOISE,
CP_SCATTER_PER_MESH
};
FilterColorProc();
~FilterColorProc();
FilterColorProc();
~FilterColorProc();
virtual FilterClass getClass(QAction *);
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual int getRequirements(QAction *);
virtual int getRequirements(QAction *);
virtual void initParameterSet(QAction *,MeshDocument&, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument&, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
int postCondition(QAction* filter) const;
int getPreConditions(QAction *) const;
int postCondition(QAction* filter) const;
int getPreConditions(QAction *) const;
FILTER_ARITY filterArity(QAction *act) const;
};
#endif

View File

@ -56,6 +56,7 @@ class FilterCreate : public QObject, public MeshFilterInterface
bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
QString filterScriptFunctionName(FilterIDType filterID);
QString pluginName(void) const { return "FilterCreate"; }
FILTER_ARITY filterArity(QAction *) const {return NONE;}
};
#endif

View File

@ -62,6 +62,7 @@ public:
virtual bool applyFilter(QAction *, MeshModel &, RichParameterSet &, vcg::CallBackPos *) { assert(0); return false; }
virtual FilterClass getClass(QAction *) { return MeshFilterInterface::FilterClass( MeshFilterInterface::Layer + MeshFilterInterface::Remeshing ); }
FILTER_ARITY filterArity(QAction*) const {return FIXED;}
};

View File

@ -168,9 +168,7 @@ bool FilterDirt::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet
if(cb) (*cb)(50,"Generating Particles...");
GenerateParticles(currMM,dust_points,/*dust_particles,*/n_p,0.6);
RenderMode rm;
rm.drawMode = GLW::DMPoints;
MeshModel* dmm=md.addNewMesh("","dust_mesh",true,rm);
MeshModel* dmm=md.addNewMesh("","dust_mesh",true);
dmm->cm.Clear();
tri::Allocator<CMeshO>::AddVertices(dmm->cm,dust_points.size());
CMeshO::VertexIterator vi;

View File

@ -69,8 +69,7 @@ public:
virtual bool applyFilter(QAction * /*filter */, MeshModel &, RichParameterSet & /*parent*/, vcg::CallBackPos *) { assert(0); return false;} ;
virtual int postCondition(QAction*) const;
virtual FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction*) const {return SINGLE_MESH;}
};

View File

@ -304,6 +304,21 @@ int FilterFractal::postCondition(QAction *filter) const
default: assert(0);
}
}
MeshFilterInterface::FILTER_ARITY FilterFractal::filterArity( QAction* act ) const
{
switch(ID(act))
{
case FP_FRACTAL_MESH:
return MeshFilterInterface::SINGLE_MESH;
case CR_FRACTAL_TERRAIN:
return MeshFilterInterface::NONE;
case FP_CRATERS:
return MeshFilterInterface::VARIABLE;
}
return MeshFilterInterface::NONE;
}
// ----------------------------------------------------------------------
MESHLAB_PLUGIN_NAME_EXPORTER(FilterFractal)

View File

@ -52,7 +52,7 @@ public:
int postCondition(QAction *action) const;
FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction* act) const;
private:
void initParameterSetForFractalDisplacement (QAction *, MeshDocument &, RichParameterSet &);
void initParameterSetForCratersGeneration (MeshDocument &md, RichParameterSet &par);

View File

@ -1363,4 +1363,30 @@ void FilterFunctionPlugin::setPerFaceVariables(Parser &p, CMeshO &m)
}
MeshFilterInterface::FILTER_ARITY FilterFunctionPlugin::filterArity( QAction* filter ) const
{
switch(ID(filter))
{
case FF_VERT_SELECTION:
case FF_FACE_SELECTION:
case FF_GEOM_FUNC:
case FF_FACE_COLOR:
case FF_FACE_QUALITY:
case FF_VERT_COLOR:
case FF_VERT_QUALITY:
case FF_VERT_TEXTURE_FUNC:
case FF_WEDGE_TEXTURE_FUNC:
case FF_VERT_NORMAL:
case FF_DEF_VERT_ATTRIB:
case FF_DEF_FACE_ATTRIB:
case FF_REFINE:
return MeshFilterInterface::SINGLE_MESH;
case FF_GRID:
case FF_ISOSURFACE:
return MeshFilterInterface::NONE;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterFunctionPlugin)

View File

@ -81,6 +81,8 @@ public:
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
virtual int getRequirements(QAction *);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction* filter) const;
void showParserError(const QString &s, mu::Parser::exception_type &e);
void setAttributes(CMeshO::VertexIterator &vi,CMeshO &m);

View File

@ -271,6 +271,7 @@ void VisibilityCheck_ShadowMap::shadowProjMatrices()
// Define the bias matrix that will enable to go from clipping space to texture space.
// from [-1,1] to [0,1]
const float biasMatData[16] = { 0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
@ -316,11 +317,15 @@ void VisibilityCheck_ShadowMap::updateShadowTexture()
// Set up the OpenGL transformation matrices so as to place the viewpoint on the raster's camera.
glMatrixMode( GL_PROJECTION );
glPushMatrix();
vcg::glLoadMatrix( m_Proj.V() );
/*WARNING!!!!! patch added cause the vcg::glLoadMatrix assumes the matrix in row major order (it computes a transpose of the matrix)
// La Rue instead managed already them in column major order*/
vcg::glLoadMatrix( m_Proj.transpose().V() );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
vcg::glLoadMatrix( m_Pose.V() );
vcg::glLoadMatrix( m_Pose.transpose().V() );
// Perform an off-screen rendering pass so as to generate the a depth map of the model
@ -337,7 +342,7 @@ void VisibilityCheck_ShadowMap::updateShadowTexture()
glClear( GL_DEPTH_BUFFER_BIT );
if( s_AreVBOSupported )
{
glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
/*glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
glEnableClientState( GL_VERTEX_ARRAY );
m_Context.bindVertexBuffer( m_ShadowVBOVertices );
@ -348,7 +353,16 @@ void VisibilityCheck_ShadowMap::updateShadowTexture()
glDrawElements( GL_TRIANGLES, 3*m_Mesh->fn, GL_UNSIGNED_INT, 0 );
m_Context.unbindIndexBuffer();
glPopClientAttrib();
glPopClientAttrib();*/
MLRenderingData dt;
MLRenderingData::RendAtts atts;
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
dt.set(MLRenderingData::PR_SOLID,atts);
if (m_plugcontext != NULL)
{
m_plugcontext->setRenderingData(m_meshid,dt);
m_plugcontext->drawMeshModel(m_meshid);
}
}
else
{
@ -414,10 +428,10 @@ bool VisibilityCheck_ShadowMap::initShaders()
if( clipCoord.x>=0.0 && clipCoord.x<=1.0 &&
clipCoord.y>=0.0 && clipCoord.y<=1.0 &&
shadow2DProj( u_SadowMap, projVert ).r > 0.5 )
gl_FragColor = vec4( V_VISIBLE );
gl_FragColor = vec4(V_VISIBLE);
else
gl_FragColor = vec4( V_UNDEFINED );
}
}
}
);
@ -476,9 +490,10 @@ void VisibilityCheck_ShadowMap::initMeshTextures()
// Creates the VBO that will be used for the generation of the shadow map.
if( s_AreVBOSupported )
if( !s_AreVBOSupported )
{
m_ShadowVBOVertices = glw::createBuffer( m_Context, m_Mesh->vn*sizeof(Point3m), mapData );
delete [] mapData;
/*m_ShadowVBOVertices = glw::createBuffer( m_Context, m_Mesh->vn*sizeof(Point3m), mapData );
delete [] mapData;
unsigned int *indices = new unsigned int [ 3*m_Mesh->fn ];
@ -487,19 +502,19 @@ void VisibilityCheck_ShadowMap::initMeshTextures()
indices[n] = m_Mesh->face[f].V(v) - &m_Mesh->vert[0];
m_ShadowVBOIndices = glw::createBuffer( m_Context, 3*m_Mesh->fn*sizeof(unsigned int), indices );
delete [] indices;
delete [] indices;*/
}
else
delete [] mapData;
//else
// delete [] mapData;
}
void VisibilityCheck_ShadowMap::setMesh( CMeshO *mesh )
void VisibilityCheck_ShadowMap::setMesh(int meshid,CMeshO *mesh )
{
if( mesh && mesh!=m_Mesh )
{
m_Mesh = mesh;
m_meshid = meshid;
initMeshTextures();
// Create the framebuffer into which the result of the visibility computation will be stored.

View File

@ -47,19 +47,20 @@ protected:
glw::Context &m_Context;
CMeshO *m_Mesh;
int m_meshid;
RasterModel *m_Raster;
std::vector<unsigned char> m_VertFlag;
static VisibilityCheck *s_Instance;
inline VisibilityCheck( glw::Context &ctx ) : m_Context(ctx), m_Mesh(NULL), m_Raster(NULL) {}
inline VisibilityCheck( glw::Context &ctx ) : m_Context(ctx), m_Mesh(NULL), m_Raster(NULL),m_plugcontext(NULL) {}
virtual ~VisibilityCheck() {}
public:
static VisibilityCheck* GetInstance( glw::Context &ctx );
static void ReleaseInstance();
virtual void setMesh( CMeshO *mesh ) = 0;
virtual void setMesh(int meshid,CMeshO *mesh ) = 0;
virtual void setRaster( RasterModel *mesh ) = 0;
virtual void checkVisibility() = 0;
@ -70,6 +71,8 @@ public:
inline bool isFaceVisible( const unsigned int n ) const { return isFaceVisible( &m_Mesh->face[n] ); }
inline bool isFaceVisible( const CFaceO *f ) const { return isVertVisible(f->cV(0)) || isVertVisible(f->cV(1)) || isVertVisible(f->cV(2)); }
inline bool isFaceVisible( const CMeshO::FaceIterator &f ) const { return isFaceVisible( &*f ); }
MLPluginGLContext* m_plugcontext;
};
@ -95,7 +98,7 @@ private:
public:
static bool isSupported();
void setMesh( CMeshO *mesh ) { m_Mesh = mesh; }
void setMesh(int meshid,CMeshO *mesh ) { m_Mesh = mesh; m_meshid = meshid; }
void setRaster( RasterModel *rm ) { m_Raster = rm; }
void checkVisibility();
};
@ -137,7 +140,7 @@ private:
public:
static bool isSupported();
void setMesh( CMeshO *mesh );
void setMesh(int meshid,CMeshO *mesh );
void setRaster( RasterModel *rm );
void checkVisibility();
};

View File

@ -29,7 +29,7 @@
VisibleSet::VisibleSet( glw::Context &ctx,
VisibleSet::VisibleSet( glw::Context &ctx,MLPluginGLContext* plugctx,int meshid,
CMeshO &mesh,
QList<RasterModel*> &rasterList,
int weightMask ) :
@ -38,7 +38,8 @@ VisibleSet::VisibleSet( glw::Context &ctx,
m_WeightMask(weightMask)
{
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( ctx );
visibility.setMesh( &mesh );
visibility.setMesh(meshid,&mesh );
visibility.m_plugcontext = plugctx;
float depthMin = std::numeric_limits<float>::max();

View File

@ -78,7 +78,7 @@ private:
inline int id( const CFaceO& f ) const { return &f - &m_Mesh.face[0]; }
public:
VisibleSet( glw::Context &ctx,
VisibleSet( glw::Context &ctx,MLPluginGLContext* plugctx,int meshid,
CMeshO &mesh,
QList<RasterModel*> &rasterList,
int weightMask );

View File

@ -36,9 +36,9 @@
FilterImgPatchParamPlugin::FilterImgPatchParamPlugin() : m_Context(NULL)
{
typeList << FP_PATCH_PARAM_ONLY
<< FP_PATCH_PARAM_AND_TEXTURING
<< FP_RASTER_VERT_COVERAGE
<< FP_RASTER_FACE_COVERAGE;
<< FP_PATCH_PARAM_AND_TEXTURING
<< FP_RASTER_VERT_COVERAGE
<< FP_RASTER_FACE_COVERAGE;
foreach( FilterIDType tt , types() )
actionList << new QAction(filterName(tt), this);
@ -56,11 +56,11 @@ QString FilterImgPatchParamPlugin::filterName( FilterIDType id ) const
{
switch( id )
{
case FP_PATCH_PARAM_ONLY: return QString( "Parameterization from registered rasters" );
case FP_PATCH_PARAM_AND_TEXTURING: return QString( "Parameterization + texturing from registered rasters" );
case FP_RASTER_VERT_COVERAGE: return QString( "Quality from raster coverage (Vertex)" );
case FP_RASTER_FACE_COVERAGE: return QString( "Quality from raster coverage (Face)" );
default: assert(0); return QString();
case FP_PATCH_PARAM_ONLY: return QString( "Parameterization from registered rasters" );
case FP_PATCH_PARAM_AND_TEXTURING: return QString( "Parameterization + texturing from registered rasters" );
case FP_RASTER_VERT_COVERAGE: return QString( "Quality from raster coverage (Vertex)" );
case FP_RASTER_FACE_COVERAGE: return QString( "Quality from raster coverage (Face)" );
default: assert(0); return QString();
}
}
@ -69,11 +69,11 @@ QString FilterImgPatchParamPlugin::filterInfo( FilterIDType id ) const
{
switch( id )
{
case FP_PATCH_PARAM_ONLY: return QString( "The mesh is parameterized by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters.");
case FP_PATCH_PARAM_AND_TEXTURING: return QString("The mesh is parameterized and textured by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters.");
case FP_RASTER_VERT_COVERAGE: return QString( "Compute a quality value representing the number of images into which each vertex of the active mesh is visible." );
case FP_RASTER_FACE_COVERAGE: return QString( "Compute a quality value representing the number of images into which each face of the active mesh is visible." );
default: assert(0); return QString();
case FP_PATCH_PARAM_ONLY: return QString( "The mesh is parameterized by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters.");
case FP_PATCH_PARAM_AND_TEXTURING: return QString("The mesh is parameterized and textured by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters.");
case FP_RASTER_VERT_COVERAGE: return QString( "Compute a quality value representing the number of images into which each vertex of the active mesh is visible." );
case FP_RASTER_FACE_COVERAGE: return QString( "Compute a quality value representing the number of images into which each face of the active mesh is visible." );
default: assert(0); return QString();
}
}
@ -82,11 +82,11 @@ int FilterImgPatchParamPlugin::getRequirements( QAction *act )
{
switch( ID(act) )
{
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_AND_TEXTURING: return MeshModel::MM_WEDGTEXCOORD | MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTFACETOPO;
case FP_RASTER_VERT_COVERAGE: return MeshModel::MM_VERTQUALITY;
case FP_RASTER_FACE_COVERAGE: return MeshModel::MM_FACEQUALITY;
default: assert(0); return 0;
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_AND_TEXTURING: return MeshModel::MM_WEDGTEXCOORD | MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTFACETOPO;
case FP_RASTER_VERT_COVERAGE: return MeshModel::MM_VERTQUALITY;
case FP_RASTER_FACE_COVERAGE: return MeshModel::MM_FACEQUALITY;
default: assert(0); return 0;
}
}
@ -95,11 +95,11 @@ MeshFilterInterface::FilterClass FilterImgPatchParamPlugin::getClass( QAction *a
{
switch( ID(act) )
{
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_AND_TEXTURING: return Texture;
case FP_RASTER_VERT_COVERAGE:
case FP_RASTER_FACE_COVERAGE: return FilterClass(Quality + Camera + Texture);
default: assert(0); return MeshFilterInterface::Generic;
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_AND_TEXTURING: return Texture;
case FP_RASTER_VERT_COVERAGE:
case FP_RASTER_FACE_COVERAGE: return FilterClass(Quality + Camera + Texture);
default: assert(0); return MeshFilterInterface::Generic;
}
}
@ -120,65 +120,65 @@ MeshFilterInterface::FilterClass FilterImgPatchParamPlugin::getClass( QAction *a
void FilterImgPatchParamPlugin::initParameterSet( QAction *act,
MeshDocument &/*md*/,
RichParameterSet &par )
MeshDocument &/*md*/,
RichParameterSet &par )
{
switch( ID(act) )
{
case FP_PATCH_PARAM_AND_TEXTURING:
case FP_PATCH_PARAM_AND_TEXTURING:
{
par.addParam( new RichInt( "textureSize",
1024,
"Texture size",
"Specifies the dimension of the generated texture" ) );
1024,
"Texture size",
"Specifies the dimension of the generated texture" ) );
par.addParam( new RichString( "textureName",
"texture.png",
"Texture name",
"Specifies the name of the file into which the texture image will be saved" ) );
"texture.png",
"Texture name",
"Specifies the name of the file into which the texture image will be saved" ) );
par.addParam( new RichBool( "colorCorrection",
true,
"Color correction",
"If true, the final texture is corrected so as to ensure seamless transitions" ) );
true,
"Color correction",
"If true, the final texture is corrected so as to ensure seamless transitions" ) );
par.addParam( new RichInt( "colorCorrectionFilterSize",
1,
"Color correction filter",
"It is the radius (in pixel) of the kernel that is used to compute the difference between corresponding texels in different rasters. Default is 1 that generate a 3x3 kernel. Highest values increase the robustness of the color correction process in the case of strong image-to-geometry misalignments" ) );
1,
"Color correction filter",
"It is the radius (in pixel) of the kernel that is used to compute the difference between corresponding texels in different rasters. Default is 1 that generate a 3x3 kernel. Highest values increase the robustness of the color correction process in the case of strong image-to-geometry misalignments" ) );
}
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_ONLY:
{
par.addParam( new RichBool( "useDistanceWeight",
true,
"Use distance weight",
"Includes a weight accounting for the distance to the camera during the computation of reference images" ) );
true,
"Use distance weight",
"Includes a weight accounting for the distance to the camera during the computation of reference images" ) );
par.addParam( new RichBool( "useImgBorderWeight",
true,
"Use image border weight",
"Includes a weight accounting for the distance to the image border during the computation of reference images" ) );
true,
"Use image border weight",
"Includes a weight accounting for the distance to the image border during the computation of reference images" ) );
par.addParam( new RichBool( "useAlphaWeight",
false,
"Use image alpha weight",
"If true, alpha channel of the image is used as additional weight. In this way it is possible to mask-out parts of the images that should not be projected on the mesh. Please note this is not a transparency effect, but just influences the weigthing between different images" ) );
false,
"Use image alpha weight",
"If true, alpha channel of the image is used as additional weight. In this way it is possible to mask-out parts of the images that should not be projected on the mesh. Please note this is not a transparency effect, but just influences the weigthing between different images" ) );
par.addParam( new RichBool( "cleanIsolatedTriangles",
true,
"Clean isolated triangles",
"Remove all patches compound of a single triangle by aggregating them to adjacent patches" ) );
true,
"Clean isolated triangles",
"Remove all patches compound of a single triangle by aggregating them to adjacent patches" ) );
par.addParam( new RichBool( "stretchingAllowed",
false,
"UV stretching",
"If true, texture coordinates are stretched so as to cover the full interval [0,1] for both directions" ) );
false,
"UV stretching",
"If true, texture coordinates are stretched so as to cover the full interval [0,1] for both directions" ) );
par.addParam( new RichInt( "textureGutter",
4,
"Texture gutter",
"Extra boundary to add to each patch before packing in texture space (in pixels)" ) );
4,
"Texture gutter",
"Extra boundary to add to each patch before packing in texture space (in pixels)" ) );
break;
}
case FP_RASTER_VERT_COVERAGE:
case FP_RASTER_FACE_COVERAGE:
case FP_RASTER_VERT_COVERAGE:
case FP_RASTER_FACE_COVERAGE:
{
par.addParam( new RichBool( "normalizeQuality",
false,
"Normalize",
"Rescale quality values to the range [0,1]" ) );
false,
"Normalize",
"Rescale quality values to the range [0,1]" ) );
break;
}
}
@ -186,18 +186,18 @@ void FilterImgPatchParamPlugin::initParameterSet( QAction *act,
bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
MeshDocument &md,
RichParameterSet &par,
vcg::CallBackPos * /*cb*/ )
MeshDocument &md,
RichParameterSet &par,
vcg::CallBackPos * /*cb*/ )
{
glContext->makeCurrent();
if( glewInit() != GLEW_OK )
{
this->errorMessage="Failed GLEW intialization";
return false;
}
this->errorMessage="Failed GLEW intialization";
return false;
}
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -207,13 +207,12 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
if( !VisibilityCheck::GetInstance(*m_Context) )
{
this->errorMessage="VisibilityCheck failed";
return false;
}
this->errorMessage="VisibilityCheck failed";
return false;
}
VisibilityCheck::ReleaseInstance();
bool retValue = true;
CMeshO &mesh = md.mm()->cm;
@ -225,21 +224,21 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
initialShots.push_back( rm->shot );
rm->shot.ApplyRigidTransformation( vcg::Inverse(mesh.Tr) );
if( rm->visible )
activeRasters.push_back( rm );
activeRasters.push_back( rm );
}
if( activeRasters.empty() ) {
this->errorMessage="No active Raster";
{
glContext->doneCurrent();
errorMessage = "You need to have at least one valid raster layer in your project, to apply this filter"; // text
return false;
}
this->errorMessage="No active Raster";
{
glContext->doneCurrent();
errorMessage = "You need to have at least one valid raster layer in your project, to apply this filter"; // text
return false;
}
}
switch( ID(act) )
{
case FP_PATCH_PARAM_ONLY:
case FP_PATCH_PARAM_ONLY:
{
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
{
@ -251,17 +250,19 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
vcg::tri::Allocator<CMeshO>::CompactVertexVector(md.mm()->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
RasterPatchMap patches;
PatchVec nullPatches;
patchBasedTextureParameterization( patches,
nullPatches,
mesh,
activeRasters,
par );
nullPatches,
md.mm()->id(),
mesh,
activeRasters,
par );
break;
}
case FP_PATCH_PARAM_AND_TEXTURING:
case FP_PATCH_PARAM_AND_TEXTURING:
{
if (vcg::tri::Clean<CMeshO>::CountNonManifoldEdgeFF(md.mm()->cm)>0)
{
@ -272,6 +273,7 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
vcg::tri::Allocator<CMeshO>::CompactEveryVector(md.mm()->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(md.mm()->cm);
vcg::tri::UpdateTopology<CMeshO>::VertexFace(md.mm()->cm);
glContext->meshAttributesUpdated(md.mm()->id(),true,MLRenderingData::RendAtts());
QString texName = par.getString( "textureName" ).simplified();
int pathEnd = std::max( texName.lastIndexOf('/'), texName.lastIndexOf('\\') );
if( pathEnd != -1 )
@ -282,10 +284,11 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
RasterPatchMap patches;
PatchVec nullPatches;
patchBasedTextureParameterization( patches,
nullPatches,
mesh,
activeRasters,
par );
nullPatches,
md.mm()->id(),
mesh,
activeRasters,
par );
TexturePainter painter( *m_Context, par.getInt("textureSize") );
if( (retValue = painter.isInitialized()) )
@ -307,11 +310,11 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
break;
}
case FP_RASTER_VERT_COVERAGE:
case FP_RASTER_VERT_COVERAGE:
{
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
visibility.setMesh( &mesh );
visibility.setMesh(md.mm()->id(),&mesh );
visibility.m_plugcontext = glContext;
for( CMeshO::VertexIterator vi=mesh.vert.begin(); vi!=mesh.vert.end(); ++vi )
vi->Q() = 0.0f;
@ -333,10 +336,11 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
break;
}
case FP_RASTER_FACE_COVERAGE:
case FP_RASTER_FACE_COVERAGE:
{
VisibilityCheck &visibility = *VisibilityCheck::GetInstance( *m_Context );
visibility.setMesh( &mesh );
visibility.setMesh(md.mm()->id(),&mesh );
visibility.m_plugcontext = glContext;
for( CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end(); ++fi )
fi->Q() = 0.0f;
@ -383,7 +387,7 @@ bool FilterImgPatchParamPlugin::applyFilter( QAction *act,
void FilterImgPatchParamPlugin::getNeighbors( CVertexO *v,
NeighbSet &neighb ) const
NeighbSet &neighb ) const
{
vcg::face::Pos<CFaceO> p( v->VFp(), v ), ori = p;
do
@ -396,7 +400,7 @@ void FilterImgPatchParamPlugin::getNeighbors( CVertexO *v,
void FilterImgPatchParamPlugin::getFaceNeighbors( CFaceO *f,
NeighbSet &neighb ) const
NeighbSet &neighb ) const
{
getNeighbors( f->V(0), neighb );
getNeighbors( f->V(1), neighb );
@ -405,8 +409,8 @@ void FilterImgPatchParamPlugin::getFaceNeighbors( CFaceO *f,
void FilterImgPatchParamPlugin::boundaryOptimization( CMeshO &mesh,
VisibleSet &faceVis,
bool mostFrontFacing )
VisibleSet &faceVis,
bool mostFrontFacing )
{
std::set<CFaceO*> toOptim;
@ -432,8 +436,8 @@ void FilterImgPatchParamPlugin::boundaryOptimization( CMeshO &mesh,
for( NeighbSet::iterator n=neighb.begin(); n!=neighb.end(); ++n )
toOptim.insert( *n );
}
p.FlipV();
p.FlipE();
p.FlipV();
p.FlipE();
}
f->SetV();
}
@ -466,88 +470,88 @@ void FilterImgPatchParamPlugin::boundaryOptimization( CMeshO &mesh,
}
if( mostFrontFacing )
{
// Look for the one that appears the most, and that belongs to the list of visible rasters
// of the considered face.
std::vector<RasterModel*> appearsMost;
int nbMaxAppear = 0;
for( QMap<RasterModel*,int>::iterator n=neighbRefCount.begin(); n!=neighbRefCount.end(); ++n )
if( n.value()>=nbMaxAppear && faceVis[f].contains(n.key()) )
{
if( n.value() > nbMaxAppear )
appearsMost.clear();
nbMaxAppear = n.value();
appearsMost.push_back( n.key() );
}
// If multiple neighboring reference images have the same number of occurences, the one with the highest
// weight with respect to the current face is chosen.
RasterModel *candidate = faceVis[f].ref();
if( appearsMost.size() > 1 )
if( mostFrontFacing )
{
float maxWeight = -std::numeric_limits<float>::max();
for( std::vector<RasterModel*>::iterator r=appearsMost.begin(); r!=appearsMost.end(); ++r )
{
float weight = faceVis.getWeight( *r, *f );
if( weight > maxWeight )
// Look for the one that appears the most, and that belongs to the list of visible rasters
// of the considered face.
std::vector<RasterModel*> appearsMost;
int nbMaxAppear = 0;
for( QMap<RasterModel*,int>::iterator n=neighbRefCount.begin(); n!=neighbRefCount.end(); ++n )
if( n.value()>=nbMaxAppear && faceVis[f].contains(n.key()) )
{
maxWeight = weight;
candidate = *r;
if( n.value() > nbMaxAppear )
appearsMost.clear();
nbMaxAppear = n.value();
appearsMost.push_back( n.key() );
}
// If multiple neighboring reference images have the same number of occurences, the one with the highest
// weight with respect to the current face is chosen.
RasterModel *candidate = faceVis[f].ref();
if( appearsMost.size() > 1 )
{
float maxWeight = -std::numeric_limits<float>::max();
for( std::vector<RasterModel*>::iterator r=appearsMost.begin(); r!=appearsMost.end(); ++r )
{
float weight = faceVis.getWeight( *r, *f );
if( weight > maxWeight )
{
maxWeight = weight;
candidate = *r;
}
}
}
else if( appearsMost.size() == 1 )
candidate = appearsMost.front();
// If the reference image of the current face is different from the candidate image, change it accordingly.
// Triangles of its neighborhood are reintroduced in the queue only if their reference images is different
// from the new one.
if( candidate != faceVis[f].ref() )
{
faceVis[f].setRef( candidate );
for( NeighbSet::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( *n && *n!=f && faceVis[*n].ref()!=candidate )
toOptim.insert( *n );
}
}
}
else if( appearsMost.size() == 1 )
candidate = appearsMost.front();
// If the reference image of the current face is different from the candidate image, change it accordingly.
// Triangles of its neighborhood are reintroduced in the queue only if their reference images is different
// from the new one.
if( candidate != faceVis[f].ref() )
else
{
faceVis[f].setRef( candidate );
for( NeighbSet::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( *n && *n!=f && faceVis[*n].ref()!=candidate )
toOptim.insert( *n );
// Look for the one that appears the most, and that belongs to the list of visible rasters
// of the considered face.
RasterModel *appearsMost = faceVis[f].ref();
int nbMaxAppear = 0;
for( QMap<RasterModel*,int>::iterator n=neighbRefCount.begin(); n!=neighbRefCount.end(); ++n )
if( n.value()>nbMaxAppear && faceVis[f].contains(n.key()) )
{
nbMaxAppear = n.value();
appearsMost = n.key();
}
// If the reference image of the current face is different from the candidate image, change it accordingly.
// Triangles of its neighborhood are reintroduced in the queue only if their reference images is different
// from the new one.
if( appearsMost != faceVis[f].ref() )
{
faceVis[f].setRef( appearsMost );
for( NeighbSet::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( *n && *n!=f && faceVis[*n].ref()!=appearsMost )
toOptim.insert( *n );
}
}
}
else
{
// Look for the one that appears the most, and that belongs to the list of visible rasters
// of the considered face.
RasterModel *appearsMost = faceVis[f].ref();
int nbMaxAppear = 0;
for( QMap<RasterModel*,int>::iterator n=neighbRefCount.begin(); n!=neighbRefCount.end(); ++n )
if( n.value()>nbMaxAppear && faceVis[f].contains(n.key()) )
{
nbMaxAppear = n.value();
appearsMost = n.key();
}
// If the reference image of the current face is different from the candidate image, change it accordingly.
// Triangles of its neighborhood are reintroduced in the queue only if their reference images is different
// from the new one.
if( appearsMost != faceVis[f].ref() )
{
faceVis[f].setRef( appearsMost );
for( NeighbSet::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( *n && *n!=f && faceVis[*n].ref()!=appearsMost )
toOptim.insert( *n );
}
}
}
}
int FilterImgPatchParamPlugin::cleanIsolatedTriangles( CMeshO &mesh,
VisibleSet &faceVis )
VisibleSet &faceVis )
{
int nbTrianglesChanged = 0;
@ -567,27 +571,27 @@ int FilterImgPatchParamPlugin::cleanIsolatedTriangles( CMeshO &mesh,
neighb[r] = 1;
}
// If the reference image of T doesn't appear in its neighborhood, it seems that T is isolated.
// In that case, the reference image that appears the most in its neighborhood is chosen as
// the new reference image of T.
if( !neighb.contains(faceVis[f].ref()) )
{
RasterModel *appearsMost = NULL;
int nAppearanceMax = 0;
for( QMap<RasterModel*,int>::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( n.value() > nAppearanceMax )
{
appearsMost = n.key();
nAppearanceMax = n.value();
}
if( appearsMost )
// If the reference image of T doesn't appear in its neighborhood, it seems that T is isolated.
// In that case, the reference image that appears the most in its neighborhood is chosen as
// the new reference image of T.
if( !neighb.contains(faceVis[f].ref()) )
{
faceVis[f].setRef( appearsMost );
nbTrianglesChanged ++;
RasterModel *appearsMost = NULL;
int nAppearanceMax = 0;
for( QMap<RasterModel*,int>::iterator n=neighb.begin(); n!=neighb.end(); ++n )
if( n.value() > nAppearanceMax )
{
appearsMost = n.key();
nAppearanceMax = n.value();
}
if( appearsMost )
{
faceVis[f].setRef( appearsMost );
nbTrianglesChanged ++;
}
}
}
}
@ -596,10 +600,10 @@ int FilterImgPatchParamPlugin::cleanIsolatedTriangles( CMeshO &mesh,
int FilterImgPatchParamPlugin::extractPatches( RasterPatchMap &patches,
PatchVec &nullPatches,
CMeshO &mesh,
VisibleSet &faceVis,
QList<RasterModel*> &rasterList )
PatchVec &nullPatches,
CMeshO &mesh,
VisibleSet &faceVis,
QList<RasterModel*> &rasterList )
{
int nbPatches = 0;
@ -643,12 +647,12 @@ int FilterImgPatchParamPlugin::extractPatches( RasterPatchMap &patches,
nullPatches.push_back( patch );
}
return nbPatches;
return nbPatches;
}
void FilterImgPatchParamPlugin::constructPatchBoundary( Patch &p,
VisibleSet &faceVis )
VisibleSet &faceVis )
{
for( std::vector<CFaceO*>::iterator f=p.faces.begin(); f!=p.faces.end(); ++f )
{
@ -681,8 +685,8 @@ void FilterImgPatchParamPlugin::constructPatchBoundary( Patch &p,
void FilterImgPatchParamPlugin::computePatchUV( CMeshO &mesh,
RasterModel *rm,
PatchVec &patches )
RasterModel *rm,
PatchVec &patches )
{
// Recovers the view frustum of the current raster.
CMeshO::ScalarType zNear, zFar;
@ -736,22 +740,22 @@ void FilterImgPatchParamPlugin::computePatchUV( CMeshO &mesh,
p->bbox.Add( (*f)->WT(i).P() );
}
// Computes UV coordinates for boundary patch faces, and update the bounding box accordingly.
for( std::vector<CFaceO*>::iterator f=p->boundary.begin(); f!=p->boundary.end(); ++f )
{
TriangleUV fuv;
for( int i=0; i<3; ++i )
// Computes UV coordinates for boundary patch faces, and update the bounding box accordingly.
for( std::vector<CFaceO*>::iterator f=p->boundary.begin(); f!=p->boundary.end(); ++f )
{
Point3m &vp = (*f)->V(i)->P();
TriangleUV fuv;
for( int i=0; i<3; ++i )
{
Point3m &vp = (*f)->V(i)->P();
fuv.v[i].U() = mesh2clip.GetRow3(0)*vp + mesh2clip[0][3];
fuv.v[i].V() = mesh2clip.GetRow3(1)*vp + mesh2clip[1][3];
fuv.v[i].P() *= 1.0f / (mesh2clip.GetRow3(3)*vp + mesh2clip[3][3]);
fuv.v[i].U() = mesh2clip.GetRow3(0)*vp + mesh2clip[0][3];
fuv.v[i].V() = mesh2clip.GetRow3(1)*vp + mesh2clip[1][3];
fuv.v[i].P() *= 1.0f / (mesh2clip.GetRow3(3)*vp + mesh2clip[3][3]);
p->bbox.Add( fuv.v[i].P() );
p->bbox.Add( fuv.v[i].P() );
}
p->boundaryUV.push_back( fuv );
}
p->boundaryUV.push_back( fuv );
}
}
}
@ -787,32 +791,32 @@ void FilterImgPatchParamPlugin::mergeOverlappingPatches( PatchVec &patches )
}
}
if( candidate != patches.end() )
if( candidate != patches.end() )
{
p1->faces.insert( p1->faces.end(), candidate->faces.begin(), candidate->faces.end() );
p1->boundary.insert( p1->boundary.end(), candidate->boundary.begin(), candidate->boundary.end() );
p1->boundaryUV.insert( p1->boundaryUV.end(), candidate->boundaryUV.begin(), candidate->boundaryUV.end() );
p1->bbox.Add( candidate->bbox );
candidate->valid = false;
globalGain += maxOccupancyGain;
}
}
for( PatchVec::iterator p=patches.begin(); p!=patches.end(); )
if( p->valid )
++ p;
else
{
p1->faces.insert( p1->faces.end(), candidate->faces.begin(), candidate->faces.end() );
p1->boundary.insert( p1->boundary.end(), candidate->boundary.begin(), candidate->boundary.end() );
p1->boundaryUV.insert( p1->boundaryUV.end(), candidate->boundaryUV.begin(), candidate->boundaryUV.end() );
p1->bbox.Add( candidate->bbox );
candidate->valid = false;
globalGain += maxOccupancyGain;
*p = patches.back();
patches.pop_back();
}
}
for( PatchVec::iterator p=patches.begin(); p!=patches.end(); )
if( p->valid )
++ p;
else
{
*p = patches.back();
patches.pop_back();
}
}
void FilterImgPatchParamPlugin::patchPacking( RasterPatchMap &patches,
int textureGutter,
bool allowUVStretching )
int textureGutter,
bool allowUVStretching )
{
std::vector<vcg::Box2f> patchRect;
std::vector<vcg::Similarity2f> patchPackingTr;
@ -829,69 +833,70 @@ void FilterImgPatchParamPlugin::patchPacking( RasterPatchMap &patches,
totalArea += p->bbox.Area();
}
if( patchRect.empty() )
return;
if( patchRect.empty() )
return;
float edgeLen = std::sqrt( totalArea );
float edgeLen = std::sqrt( totalArea );
// Performs the packing.
vcg::Point2f coveredArea;
vcg::RectPacker<float>::Pack( patchRect, vcg::Point2i(edgeLen,edgeLen), patchPackingTr, coveredArea );
// Performs the packing.
vcg::Point2f coveredArea;
vcg::RectPacker<float>::Pack( patchRect, vcg::Point2i(edgeLen,edgeLen), patchPackingTr, coveredArea );
// Applies to the UV coordinates the transformations computed by the packing algorithm, as well as a scaling
// so as to make them ranging the interval [0,1]x[0,1].
float scaleU, scaleV;
// Applies to the UV coordinates the transformations computed by the packing algorithm, as well as a scaling
// so as to make them ranging the interval [0,1]x[0,1].
float scaleU, scaleV;
if( allowUVStretching )
{
scaleU = 1.0f / coveredArea.X();
scaleV = 1.0f / coveredArea.Y();
}
else
scaleU = scaleV = 1.0f / std::max( coveredArea.X(), coveredArea.Y() );
int n = 0;
for( RasterPatchMap::iterator rp=patches.begin(); rp!=patches.end(); ++rp )
for( PatchVec::iterator p=rp->begin(); p!=rp->end(); ++p, ++n )
if( allowUVStretching )
{
vcg::Similarity2f &tr = patchPackingTr[n];
float c = std::cos( tr.rotRad );
float s = std::sin( tr.rotRad );
p->img2tex.SetIdentity();
p->img2tex[0][0] = c * tr.sca * scaleU;
p->img2tex[0][1] = -s * tr.sca * scaleU;
p->img2tex[0][3] = tr.tra.X() * scaleU;
p->img2tex[1][0] = s * tr.sca * scaleV;
p->img2tex[1][1] = c * tr.sca * scaleV;
p->img2tex[1][3] = tr.tra.Y() * scaleV;
for( std::vector<CFaceO*>::iterator f=p->faces.begin(); f!=p->faces.end(); ++f )
for( int i=0; i<3; ++i )
{
(*f)->WT(i).P() = tr * (*f)->WT(i).P();
(*f)->WT(i).U() *= scaleU;
(*f)->WT(i).V() *= scaleV;
}
for( std::vector<TriangleUV>::iterator f=p->boundaryUV.begin(); f!=p->boundaryUV.end(); ++f )
for( int i=0; i<3; ++i )
{
f->v[i].P() = tr * f->v[i].P();
f->v[i].U() *= scaleU;
f->v[i].V() *= scaleV;
}
scaleU = 1.0f / coveredArea.X();
scaleV = 1.0f / coveredArea.Y();
}
else
scaleU = scaleV = 1.0f / std::max( coveredArea.X(), coveredArea.Y() );
int n = 0;
for( RasterPatchMap::iterator rp=patches.begin(); rp!=patches.end(); ++rp )
for( PatchVec::iterator p=rp->begin(); p!=rp->end(); ++p, ++n )
{
vcg::Similarity2f &tr = patchPackingTr[n];
float c = std::cos( tr.rotRad );
float s = std::sin( tr.rotRad );
p->img2tex.SetIdentity();
p->img2tex[0][0] = c * tr.sca * scaleU;
p->img2tex[0][1] = -s * tr.sca * scaleU;
p->img2tex[0][3] = tr.tra.X() * scaleU;
p->img2tex[1][0] = s * tr.sca * scaleV;
p->img2tex[1][1] = c * tr.sca * scaleV;
p->img2tex[1][3] = tr.tra.Y() * scaleV;
for( std::vector<CFaceO*>::iterator f=p->faces.begin(); f!=p->faces.end(); ++f )
for( int i=0; i<3; ++i )
{
(*f)->WT(i).P() = tr * (*f)->WT(i).P();
(*f)->WT(i).U() *= scaleU;
(*f)->WT(i).V() *= scaleV;
}
for( std::vector<TriangleUV>::iterator f=p->boundaryUV.begin(); f!=p->boundaryUV.end(); ++f )
for( int i=0; i<3; ++i )
{
f->v[i].P() = tr * f->v[i].P();
f->v[i].U() *= scaleU;
f->v[i].V() *= scaleV;
}
}
}
void FilterImgPatchParamPlugin::patchBasedTextureParameterization( RasterPatchMap &patches,
PatchVec &nullPatches,
CMeshO &mesh,
QList<RasterModel*> &rasterList,
RichParameterSet &par )
PatchVec &nullPatches,
int meshid,
CMeshO &mesh,
QList<RasterModel*> &rasterList,
RichParameterSet &par )
{
// Computes the visibility set for all mesh faces. It contains the set of all images
// into which the face is visible, as well as a reference image, namely the one whith
@ -904,7 +909,7 @@ void FilterImgPatchParamPlugin::patchBasedTextureParameterization( RasterPatchMa
weightMask |= VisibleSet::W_IMG_BORDER;
if( par.getBool("useAlphaWeight") )
weightMask |= VisibleSet::W_IMG_ALPHA;
VisibleSet faceVis( *m_Context, mesh, rasterList, weightMask );
VisibleSet faceVis( *m_Context,glContext,meshid, mesh, rasterList, weightMask );
Log( "VISIBILITY CHECK: %.3f sec.", 0.001f*t.elapsed() );
@ -965,7 +970,7 @@ void FilterImgPatchParamPlugin::patchBasedTextureParameterization( RasterPatchMa
// in the space of their patches' reference images but UV coordinates are all defined in a common texture
// space, ranging from [0,0] to [1,1].
t.start();
patchPacking( patches, par.getInt("textureGutter"), par.getBool("stretchingAllowed") );
patchPacking( patches, par.getInt("textureGutter"), par.getBool("stretchingAllowed") );
Log( "PATCH TEXTURE PACKING: %.3f sec.", 0.001f*t.elapsed() );
@ -976,7 +981,7 @@ void FilterImgPatchParamPlugin::patchBasedTextureParameterization( RasterPatchMa
(*f)->WT(i).P() = vcg::Point2f(0.0f,0.0f);
for(CMeshO::FaceIterator fi=mesh.face.begin(); fi!=mesh.face.end();++fi)
for(int i=0;i<3;++i) fi->WT(i).N()=0;
for(int i=0;i<3;++i) fi->WT(i).N()=0;
}

View File

@ -86,6 +86,7 @@ class FilterImgPatchParamPlugin : public QObject, public MeshFilterInterface
void patchBasedTextureParameterization( RasterPatchMap &patches,
PatchVec &nullPatches,
int meshid,
CMeshO &mesh,
QList<RasterModel*> &rasterList,
RichParameterSet &par );
@ -93,6 +94,7 @@ class FilterImgPatchParamPlugin : public QObject, public MeshFilterInterface
float computeTotalPatchArea( RasterPatchMap &patches );
int computePatchCount( RasterPatchMap &patches );
public:
FilterImgPatchParamPlugin();
~FilterImgPatchParamPlugin();
@ -113,6 +115,8 @@ public:
MeshDocument &md,
RichParameterSet &par,
vcg::CallBackPos *cb );
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};

View File

@ -529,4 +529,21 @@ int FilterIsoParametrization::postCondition( QAction* /*filter*/ ) const
return MeshModel::MM_UNKNOWN;
}
MeshFilterInterface::FILTER_ARITY FilterIsoParametrization::filterArity( QAction* filter) const
{
switch(ID(filter))
{
case ISOP_PARAM :
case ISOP_REMESHING :
case ISOP_DIAMPARAM :
case ISOP_LOAD :
case ISOP_SAVE :
return MeshFilterInterface::SINGLE_MESH;
case ISOP_TRANSFER:
return MeshFilterInterface::FIXED;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterIsoParametrization)

View File

@ -48,19 +48,20 @@ class FilterIsoParametrization : public QObject, public MeshFilterInterface
ISOP_TRANSFER
};
FilterIsoParametrization();
~FilterIsoParametrization();
FilterIsoParametrization();
~FilterIsoParametrization();
virtual FilterClass getClass(QAction *);
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual FilterClass getClass(QAction *);
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual int getRequirements(QAction *);
virtual int getRequirements(QAction *);
virtual void initParameterSet(QAction *,MeshDocument&, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument&, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
int postCondition(QAction* filter) const;
void PrintStats(CMeshO *mesh);
virtual void initParameterSet(QAction *,MeshDocument&, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument&, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
int postCondition(QAction* filter) const;
void PrintStats(CMeshO *mesh);
FILTER_ARITY filterArity(QAction*) const;
};
};
#endif

View File

@ -182,12 +182,8 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
case FP_SPLITSELECTEDVERTICES :
{
MeshModel* currentmesh = md.mm();
RenderMode rm;
rm.drawMode = GLW::DMPoints;
if (currentmesh->hasDataMask(MeshModel::MM_VERTCOLOR))
rm.colorMode = GLW::CMPerVert;
MeshModel* destmesh = md.addNewMesh("","SelectedVerticesSubset",true,rm);
MeshModel* destmesh = md.addNewMesh("","SelectedVerticesSubset",true);
destmesh->updateDataMask(currentmesh);
numVertSel = tri::UpdateSelection<CMeshO>::VertexCount(currentmesh->cm);
tri::Append<CMeshO,CMeshO>::Mesh(destmesh->cm, currentmesh->cm, true);
@ -228,7 +224,7 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
// creating the new layer
// that is the back one
MeshModel *currentMesh = md.mm(); // source = current
RenderMode rm;
/* RenderMode rm;
if (currentMesh->hasDataMask(MeshModel::MM_VERTCOLOR))
rm.colorMode = GLW::CMPerVert;
else if (currentMesh->hasDataMask(MeshModel::MM_FACECOLOR))
@ -239,9 +235,9 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
if (currentMesh->hasDataMask(MeshModel::MM_WEDGTEXCOORD))
rm.textureMode = GLW::TMPerWedgeMulti;
else if (currentMesh->hasDataMask(MeshModel::MM_VERTTEXCOORD))
rm.textureMode = GLW::TMPerVert;
rm.textureMode = GLW::TMPerVert;*/
//vcg::GLW::TextureMode tex = rm.textureMode;
MeshModel *destMesh= md.addNewMesh("","SelectedFacesSubset",true,rm); // After Adding a mesh to a MeshDocument the new mesh is the current one
MeshModel *destMesh= md.addNewMesh("","SelectedFacesSubset",true); // After Adding a mesh to a MeshDocument the new mesh is the current one
destMesh->updateDataMask(currentMesh);
// select all points involved
@ -330,14 +326,17 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
tri::UpdatePosition<CMeshO>::Matrix(mmp->cm,mmp->cm.Tr,true);
toBeDeletedList.push_back(mmp);
if(!alsoUnreferenced)
{
vcg::tri::Clean<CMeshO>::RemoveUnreferencedVertex(mmp->cm);
}
destMesh->updateDataMask(mmp);
tri::Append<CMeshO,CMeshO>::Mesh(destMesh->cm,mmp->cm);
tri::UpdatePosition<CMeshO>::Matrix(mmp->cm,Inverse(mmp->cm.Tr),true);
}
}
}
if( deleteLayer ) {
Log( "Deleted %d merged layers", toBeDeletedList.size());
foreach(MeshModel *mmp,toBeDeletedList) {
@ -351,7 +350,6 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
Log( "Removed %d duplicated vertices", delvert);
}
destMesh->UpdateBoxAndNormals();
Log("Merged all the layers to single mesh of %i vertices",md.mm()->cm.vn);
} break;
@ -366,14 +364,15 @@ bool FilterLayerPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParam
{
tri::UpdateSelection<CMeshO>::FaceClear(cm);
connectedCompVec[i].second->SetS();
tri::UpdateSelection<CMeshO>::FaceConnectedFF(cm);
tri::UpdateSelection<CMeshO>::FaceConnectedFF(cm,true);
tri::UpdateSelection<CMeshO>::VertexClear(cm);
tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(cm);
MeshModel *destMesh= md.addNewMesh("",QString("CC %1").arg(i));
tri::Append<CMeshO,CMeshO>::Mesh(destMesh->cm, cm, true);
destMesh->UpdateBoxAndNormals();
destMesh->cm.Tr = cm.Tr; // copy transformation
destMesh->cm.Tr = cm.Tr; // copy transformation
destMesh->updateDataMask(md.mm());
}
} break;
}
@ -405,4 +404,27 @@ FilterLayerPlugin::FilterClass FilterLayerPlugin::getClass(QAction *a)
}
}
MeshFilterInterface::FILTER_ARITY FilterLayerPlugin::filterArity( QAction* filter) const
{
switch(ID(filter))
{
case FP_RENAME_MESH :
case FP_SPLITSELECTEDFACES :
case FP_SPLITSELECTEDVERTICES:
case FP_DUPLICATE :
case FP_SELECTCURRENT :
case FP_SPLITCONNECTED :
case FP_DELETE_MESH :
return MeshFilterInterface::SINGLE_MESH;
case FP_RENAME_RASTER :
case FP_DELETE_RASTER :
case FP_DELETE_NON_SELECTED_RASTER :
return MeshFilterInterface::NONE;
case FP_FLATTEN :
case FP_DELETE_NON_VISIBLE_MESH :
return MeshFilterInterface::VARIABLE;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterLayerPlugin)

View File

@ -30,20 +30,21 @@
class FilterLayerPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum { FP_FLATTEN, FP_SPLITSELECTEDFACES, FP_SPLITSELECTEDVERTICES, FP_SPLITCONNECTED, FP_DUPLICATE, FP_RENAME_MESH, FP_RENAME_RASTER, FP_DELETE_MESH, FP_DELETE_NON_VISIBLE_MESH,FP_DELETE_RASTER, FP_DELETE_NON_SELECTED_RASTER,FP_SELECTCURRENT };
enum { FP_FLATTEN, FP_SPLITSELECTEDFACES, FP_SPLITSELECTEDVERTICES, FP_SPLITCONNECTED, FP_DUPLICATE, FP_RENAME_MESH, FP_RENAME_RASTER, FP_DELETE_MESH, FP_DELETE_NON_VISIBLE_MESH,FP_DELETE_RASTER, FP_DELETE_NON_SELECTED_RASTER,FP_SELECTCURRENT };
FilterLayerPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
FilterLayerPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual FilterClass getClass(QAction *);
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction*) const;
};
#endif

View File

@ -29,82 +29,83 @@
class ExtraMeshFilterPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
enum RefPlane { REF_CENTER,REF_MIN,REF_ORIG};
enum RefPlane { REF_CENTER,REF_MIN,REF_ORIG};
public:
/* naming convention :
- FP -> Filter Plugin
- name of the filter separated by _
/* naming convention :
- FP -> Filter Plugin
- name of the filter separated by _
*/
enum {
FP_LOOP_SS,
FP_BUTTERFLY_SS,
FP_REMOVE_UNREFERENCED_VERTEX,
FP_REMOVE_DUPLICATED_VERTEX,
FP_SELECT_FACES_BY_AREA,
FP_SELECT_FACES_BY_EDGE,
FP_CLUSTERING,
FP_QUADRIC_SIMPLIFICATION,
FP_QUADRIC_TEXCOORD_SIMPLIFICATION,
FP_NORMAL_EXTRAPOLATION,
FP_NORMAL_SMOOTH_POINTCLOUD,
FP_COMPUTE_PRINC_CURV_DIR,
FP_SLICE_WITH_A_PLANE,
FP_MIDPOINT,
FP_REORIENT ,
FP_FLIP_AND_SWAP,
FP_ROTATE,
FP_ROTATE_FIT,
FP_SCALE,
FP_CENTER,
FP_PRINCIPAL_AXIS,
FP_INVERT_FACES,
FP_FREEZE_TRANSFORM,
FP_RESET_TRANSFORM,
FP_CLOSE_HOLES_TRIVIAL,
FP_CLOSE_HOLES,
FP_CYLINDER_UNWRAP,
FP_REFINE_CATMULL,
FP_REFINE_HALF_CATMULL,
FP_QUAD_DOMINANT,
FP_MAKE_PURE_TRI,
FP_QUAD_PAIRING,
FP_FAUX_CREASE,
FP_FAUX_EXTRACT,
FP_VATTR_SEAM,
FP_REFINE_LS3_LOOP
} ;
enum {
FP_LOOP_SS,
FP_BUTTERFLY_SS,
FP_REMOVE_UNREFERENCED_VERTEX,
FP_REMOVE_DUPLICATED_VERTEX,
FP_SELECT_FACES_BY_AREA,
FP_SELECT_FACES_BY_EDGE,
FP_CLUSTERING,
FP_QUADRIC_SIMPLIFICATION,
FP_QUADRIC_TEXCOORD_SIMPLIFICATION,
FP_NORMAL_EXTRAPOLATION,
FP_NORMAL_SMOOTH_POINTCLOUD,
FP_COMPUTE_PRINC_CURV_DIR,
FP_SLICE_WITH_A_PLANE,
FP_MIDPOINT,
FP_REORIENT ,
FP_FLIP_AND_SWAP,
FP_ROTATE,
FP_ROTATE_FIT,
FP_SCALE,
FP_CENTER,
FP_PRINCIPAL_AXIS,
FP_INVERT_FACES,
FP_FREEZE_TRANSFORM,
FP_RESET_TRANSFORM,
FP_CLOSE_HOLES_TRIVIAL,
FP_CLOSE_HOLES,
FP_CYLINDER_UNWRAP,
FP_REFINE_CATMULL,
FP_REFINE_HALF_CATMULL,
FP_QUAD_DOMINANT,
FP_MAKE_PURE_TRI,
FP_QUAD_PAIRING,
FP_FAUX_CREASE,
FP_FAUX_EXTRACT,
FP_VATTR_SEAM,
FP_REFINE_LS3_LOOP
} ;
ExtraMeshFilterPlugin();
~ExtraMeshFilterPlugin(){}
QString filterName(FilterIDType filter) const;
QString filterInfo(FilterIDType filter) const;
ExtraMeshFilterPlugin();
~ExtraMeshFilterPlugin(){}
QString filterName(FilterIDType filter) const;
QString filterInfo(FilterIDType filter) const;
FilterClass getClass(QAction *);
void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
int postCondition(QAction *filter) const;
int getPreCondition(QAction *filter) const;
FilterClass getClass(QAction *);
void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
int postCondition(QAction *filter) const;
int getPreCondition(QAction *filter) const;
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
protected:
float lastq_QualityThr;
bool lastq_QualityWeight;
bool lastq_PreserveBoundary;
bool lastq_Selected;
bool lastq_PreserveNormal;
bool lastq_BoundaryWeight;
bool lastq_PreserveTopology;
bool lastq_OptimalPlacement;
bool lastq_PlanarQuadric;
float lastq_QualityThr;
bool lastq_QualityWeight;
bool lastq_PreserveBoundary;
bool lastq_Selected;
bool lastq_PreserveNormal;
bool lastq_BoundaryWeight;
bool lastq_PreserveTopology;
bool lastq_OptimalPlacement;
bool lastq_PlanarQuadric;
float lastqtex_QualityThr;
float lastqtex_extratw;
float lastqtex_QualityThr;
float lastqtex_extratw;
};
#endif

View File

@ -65,10 +65,10 @@ public:
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
FilterClass getClass(QAction *a);
virtual void initParameterSet(QAction *,MeshDocument &md, RichParameterSet &parent);
virtual void initParameterSet(QAction *,MeshDocument &md, RichParameterSet &parent);
virtual int getRequirements(QAction *action);
virtual bool applyFilter(QAction *filter, MeshDocument &m, RichParameterSet &parent, vcg::CallBackPos *cb) ;
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};
#endif

View File

@ -39,6 +39,7 @@ public:
FilterClass getClass(QAction *a);
QString filterScriptFunctionName(FilterIDType filterID);
void outputToFile(QTextStream &out, Shotf &s, Image &img, CameraParameters &cam);
FILTER_ARITY filterArity(QAction *) const {return NONE;}
};
#endif /* FILTER_PHOTOSYNTH_PLUGIN_H */

View File

@ -206,4 +206,14 @@ bool PlyMCPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSe
return true;
}
MeshFilterInterface::FILTER_ARITY PlyMCPlugin::filterArity( QAction * filter ) const
{
switch(ID(filter))
{
case FP_PLYMC : return MeshFilterInterface::VARIABLE;
case FP_MC_SIMPLIFY : return MeshFilterInterface::SINGLE_MESH;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(PlyMCPlugin)

View File

@ -28,21 +28,21 @@
class PlyMCPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum { FP_PLYMC, FP_MC_SIMPLIFY } ;
enum { FP_PLYMC, FP_MC_SIMPLIFY } ;
PlyMCPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
PlyMCPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
MeshFilterInterface::FILTER_ARITY filterArity(QAction * filter) const;
};
#endif

View File

@ -21,7 +21,7 @@
* *
****************************************************************************/
/****************************************************************************
History
History
****************************************************************************/
@ -33,34 +33,34 @@
class QhullPlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
/* naming convention :
- FP -> Filter Plugin
- name of the plugin separated by _
*/
/* naming convention :
- FP -> Filter Plugin
- name of the plugin separated by _
*/
enum {
FP_QHULL_CONVEX_HULL,
FP_QHULL_DELAUNAY_TRIANGULATION,
FP_QHULL_VORONOI_FILTERING,
FP_QHULL_ALPHA_COMPLEX_AND_SHAPE,
FP_QHULL_VISIBLE_POINTS
} ;
enum {
FP_QHULL_CONVEX_HULL,
FP_QHULL_DELAUNAY_TRIANGULATION,
FP_QHULL_VORONOI_FILTERING,
FP_QHULL_ALPHA_COMPLEX_AND_SHAPE,
FP_QHULL_VISIBLE_POINTS
} ;
QhullPlugin();
~QhullPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
QhullPlugin();
~QhullPlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &m, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
virtual FilterClass getClass(QAction *);
virtual FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};
#endif

View File

@ -43,39 +43,40 @@ using namespace vcg;
using namespace std;
class Frange
{
public:
class Frange
{
public:
Frange(){}
Frange(std::pair<float,float> minmax):minV(minmax.first),maxV(minmax.second){}
Frange(float _min,float _max):minV(_min),maxV(_max){}
float minV;
float maxV;
};
};
class QualityMapperFilter : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
private:
Frange _meshMinMaxQuality;
Frange _meshMinMaxQuality;
public:
enum { FP_QUALITY_MAPPER } ;
enum { FP_QUALITY_MAPPER } ;
QualityMapperFilter();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
int getPreConditions(QAction *) const;
int postCondition( QAction* ) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
QualityMapperFilter();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
int getPreConditions(QAction *) const;
int postCondition( QAction* ) const;
virtual void initParameterSet(QAction *,MeshModel &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
virtual FilterClass getClass(QAction *);
virtual FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};
#endif

View File

@ -1297,4 +1297,27 @@ int FilterDocSampling::postCondition( QAction* a ) const
return MeshModel::MM_UNKNOWN;
}
MeshFilterInterface::FILTER_ARITY FilterDocSampling::filterArity( QAction * filter ) const
{
switch(ID(filter))
{
case FP_VERTEX_RESAMPLING :
case FP_ELEMENT_SUBSAMPLING :
case FP_MONTECARLO_SAMPLING :
case FP_STRATIFIED_SAMPLING :
case FP_CLUSTERED_SAMPLING :
case FP_REGULAR_RECURSIVE_SAMPLING :
case FP_UNIFORM_MESH_RESAMPLING:
case FP_POINTCLOUD_SIMPLIFICATION :
return MeshFilterInterface::SINGLE_MESH;
case FP_DISTANCE_REFERENCE :
case FP_HAUSDORFF_DISTANCE :
case FP_POISSONDISK_SAMPLING :
case FP_DISK_COLORING :
case FP_VORONOI_COLORING :
return MeshFilterInterface::FIXED;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterDocSampling)

View File

@ -58,6 +58,7 @@ class FilterDocSampling : public QObject, public MeshFilterInterface
int getRequirements(QAction *action);
int postCondition( QAction* ) const;
FilterClass getClass(QAction *);
FILTER_ARITY filterArity(QAction * filter) const;
};
#endif

View File

@ -18,18 +18,18 @@ using namespace vcg;
#define PIXEL_COUNT_THRESHOLD 100
SdfGpuPlugin::SdfGpuPlugin()
: mPeelingTextureSize(256),
mTempDepthComplexity(0),
mDepthComplexity(0),
mDepthComplexityWarning(false)
: mPeelingTextureSize(256),
mTempDepthComplexity(0),
mDepthComplexity(0),
mDepthComplexityWarning(false)
{
typeList
<< SDF_SDF
<< SDF_DEPTH_COMPLEXITY
<< SDF_OBSCURANCE;
<< SDF_SDF
<< SDF_DEPTH_COMPLEXITY
<< SDF_OBSCURANCE;
foreach(FilterIDType tt , types())
actionList << new QAction(filterName(tt), this);
actionList << new QAction(filterName(tt), this);
}
@ -37,212 +37,207 @@ void SdfGpuPlugin::initParameterSet(QAction *action, MeshModel &/*m*/, RichParam
{
qDebug() << "called here!";
mAction = ID(action);
mAction = ID(action);
QStringList onPrimitive; onPrimitive.push_back("On vertices"); onPrimitive.push_back("On Faces");
par.addParam( new RichEnum("onPrimitive", 0, onPrimitive, "Metric:",
"Choose whether to trace rays from faces or from vertices. " ));
par.addParam( new RichInt("numberRays",128, "Number of rays: ",
"The number of rays that will be casted around "
"the normals."));
par.addParam(new RichInt("DepthTextureSize", 512, "Depth texture size",
"Size of the depth texture for depth peeling. Higher resolutions provide better sampling of the mesh, with a small performance penalty."));
par.addParam(new RichInt("peelingIteration", 10, "Peeling Iteration",
"Number of depth peeling iteration. Actually is the maximum number of layers that a ray can hit while traversing the mesh. "
"For example, in the case of a sphere, you should specify 2 in this parameter. For a torus, specify 4. "
"<b>For more complex geometry you should run the depth complexity filter to know the exact value</b>."));
par.addParam(new RichFloat("peelingTolerance", 0.0000001f, "Peeling Tolerance",
"Depth tolerance used during depth peeling. This is the threshold used to differentiate layers between each others."
"Two elements whose distance is below this value will be considered as belonging to the same layer."));
par.addParam( new RichEnum("onPrimitive", 0, onPrimitive, "Metric:",
"Choose whether to trace rays from faces or from vertices. " ));
par.addParam( new RichInt("numberRays",128, "Number of rays: ",
"The number of rays that will be casted around "
"the normals."));
par.addParam(new RichInt("DepthTextureSize", 512, "Depth texture size",
"Size of the depth texture for depth peeling. Higher resolutions provide better sampling of the mesh, with a small performance penalty."));
par.addParam(new RichInt("peelingIteration", 10, "Peeling Iteration",
"Number of depth peeling iteration. Actually is the maximum number of layers that a ray can hit while traversing the mesh. "
"For example, in the case of a sphere, you should specify 2 in this parameter. For a torus, specify 4. "
"<b>For more complex geometry you should run the depth complexity filter to know the exact value</b>."));
par.addParam(new RichFloat("peelingTolerance", 0.0000001f, "Peeling Tolerance",
"Depth tolerance used during depth peeling. This is the threshold used to differentiate layers between each others."
"Two elements whose distance is below this value will be considered as belonging to the same layer."));
if(mAction != SDF_DEPTH_COMPLEXITY)
if(mAction != SDF_DEPTH_COMPLEXITY)
par.addParam(new RichFloat("coneAngle",120,"Cone amplitude", "Cone amplitude around normals in degrees. Rays are traced within this cone."));
switch(mAction)
switch(mAction)
{
case SDF_OBSCURANCE:
par.addParam(new RichFloat("obscuranceExponent", 0.1f, "Obscurance Exponent",
"This parameter controls the spatial decay term in the obscurance formula. "
"The greater the exponent, the greater the influence of distance; that is: "
"even if a ray is blocked by an occluder its contribution to the obscurance term is non zero, but proportional to this parameter. "
"It turs out that if you choose a value of zero, you get the standard ambient occlusion term. "
"<b>(In this case, only a value of two, in the peeling iteration parameter, has a sense)</b>"));
break;
case SDF_OBSCURANCE:
par.addParam(new RichFloat("obscuranceExponent", 0.1f, "Obscurance Exponent",
"This parameter controls the spatial decay term in the obscurance formula. "
"The greater the exponent, the greater the influence of distance; that is: "
"even if a ray is blocked by an occluder its contribution to the obscurance term is non zero, but proportional to this parameter. "
"It turs out that if you choose a value of zero, you get the standard ambient occlusion term. "
"<b>(In this case, only a value of two, in the peeling iteration parameter, has a sense)</b>"));
break;
default:
{
break;
}
default:
{
break;
}
}
par.addParam(new RichBool("useVBO",USEVBO_BY_DEFAULT,"Use VBO if supported","By using VBO, Meshlab loads all the vertex structure in the VRam, greatly increasing rendering speed (for both CPU and GPU mode). Disable it if problem occurs"));
if(mAction == SDF_SDF)
{
if(mAction == SDF_SDF)
{
par.addParam(new RichBool("removeFalse",true,"Remove false intersections","For each"
"ray we check the normal at the point of intersection,"
"and ignore intersections where the normal at the intersection"
"points is in the same direction as the point-of-origin"
"(the same direction is defined as an angle difference less"
"than 90) "));
"ray we check the normal at the point of intersection,"
"and ignore intersections where the normal at the intersection"
"points is in the same direction as the point-of-origin"
"(the same direction is defined as an angle difference less"
"than 90) "));
par.addParam(new RichBool("removeOutliers",false,"Remove outliers","The outliers removal is made on the fly with a supersampling of the depth buffer. "
"For each ray that we trace, we take multiple depth values near the point of intersection and we output only the median of these values. "
"Some mesh can benefit from this additional calculation. "));
}
"For each ray that we trace, we take multiple depth values near the point of intersection and we output only the median of these values. "
"Some mesh can benefit from this additional calculation. "));
}
}
QString SdfGpuPlugin::filterName(FilterIDType filterId) const
{
switch(filterId)
{
case SDF_SDF : return QString("Shape Diameter Function");
case SDF_DEPTH_COMPLEXITY : return QString("Depth complexity");
case SDF_OBSCURANCE : return QString("Volumetric obscurance");
switch(filterId)
{
case SDF_SDF : return QString("Shape Diameter Function");
case SDF_DEPTH_COMPLEXITY : return QString("Depth complexity");
case SDF_OBSCURANCE : return QString("Volumetric obscurance");
default : assert(0);
}
default : assert(0);
}
return QString("");
return QString("");
}
QString SdfGpuPlugin::filterInfo(FilterIDType filterId) const
{
switch(filterId)
{
case SDF_SDF : return QString("Calculate the SDF (<b>shape diameter function</b>) on the mesh, you can visualize the result colorizing the mesh. "
"The SDF is a scalar function on the mesh surface and represents the neighborhood diameter of the object at each point. "
"Given a point on the mesh surface,"
"several rays are sent inside a cone, centered around the point's inward-normal, to the other side of the mesh. The result is a weighted sum of all rays lenghts. "
"For further details, see the reference paper:<br>"
"<b>Shapira Shamir Cohen-Or,<br>"
"Consistent Mesh Partitioning and Skeletonisation using the shaper diamter function, Visual Comput. J. (2008)</b> ");
case SDF_DEPTH_COMPLEXITY : return QString("Calculate the depth complexity of the mesh, that is: the maximum number of layers that a ray can hit while traversing the mesh. To have a correct value, you should specify and high value in the peeling iteration paramater. "
"You can read the result in the MeshLab log window. <b>If warnings are not present, you have the exact value, otherwise try increasing the peeling iteration paramater. After having calulated the correct value,"
"you can ignore further warnings that you may get using that value.</b>. ");
case SDF_OBSCURANCE : return QString("Calculates obscurance coefficents for the mesh. Obscurance is introduced to avoid the "
"disadvantages of both classical ambient term and ambient occlusion. "
"In ambient occlusion, totally occluded parts of the mesh are black. "
"Instead obscurance, despite still based on a perfectly diffuse light coming "
"from everywhere, accounts for multiple bounces of indirect illumination by means "
"of a function of both the openness of a point and the distance to his occluder (if any). "
"Obscurance is inversely proportional to the number of ray casted from the point "
"that hit an occluder and proportional to the distance a ray travels before hitting the occluder. "
"You can control how much the distance factor influences the final result with the obscurance exponenent (see help below). "
"Obscurance is a value in the range [0,1]. \nFor further details see the reference paper:<br>"
"<b>Iones Krupkin Sbert Zhukov <br> "
"Fast, Realistic Lighting for Video Games <br>"
"IEEECG&A 2003</b> ");
switch(filterId)
{
case SDF_SDF : return QString("Calculate the SDF (<b>shape diameter function</b>) on the mesh, you can visualize the result colorizing the mesh. "
"The SDF is a scalar function on the mesh surface and represents the neighborhood diameter of the object at each point. "
"Given a point on the mesh surface,"
"several rays are sent inside a cone, centered around the point's inward-normal, to the other side of the mesh. The result is a weighted sum of all rays lenghts. "
"For further details, see the reference paper:<br>"
"<b>Shapira Shamir Cohen-Or,<br>"
"Consistent Mesh Partitioning and Skeletonisation using the shaper diamter function, Visual Comput. J. (2008)</b> ");
case SDF_DEPTH_COMPLEXITY : return QString("Calculate the depth complexity of the mesh, that is: the maximum number of layers that a ray can hit while traversing the mesh. To have a correct value, you should specify and high value in the peeling iteration paramater. "
"You can read the result in the MeshLab log window. <b>If warnings are not present, you have the exact value, otherwise try increasing the peeling iteration paramater. After having calulated the correct value,"
"you can ignore further warnings that you may get using that value.</b>. ");
case SDF_OBSCURANCE : return QString("Calculates obscurance coefficents for the mesh. Obscurance is introduced to avoid the "
"disadvantages of both classical ambient term and ambient occlusion. "
"In ambient occlusion, totally occluded parts of the mesh are black. "
"Instead obscurance, despite still based on a perfectly diffuse light coming "
"from everywhere, accounts for multiple bounces of indirect illumination by means "
"of a function of both the openness of a point and the distance to his occluder (if any). "
"Obscurance is inversely proportional to the number of ray casted from the point "
"that hit an occluder and proportional to the distance a ray travels before hitting the occluder. "
"You can control how much the distance factor influences the final result with the obscurance exponenent (see help below). "
"Obscurance is a value in the range [0,1]. \nFor further details see the reference paper:<br>"
"<b>Iones Krupkin Sbert Zhukov <br> "
"Fast, Realistic Lighting for Video Games <br>"
"IEEECG&A 2003</b> ");
default : assert(0);
}
default : assert(0);
}
return QString("");
return QString("");
}
bool SdfGpuPlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & pars, vcg::CallBackPos *cb)
{
MeshModel* mm = md.mm();
MeshModel* mm = md.mm();
//RETRIEVE PARAMETERS
mOnPrimitive = (ONPRIMITIVE) pars.getEnum("onPrimitive");
// assert( mOnPrimitive==ON_VERTICES && "Face mode not supported yet" );
unsigned int numViews = pars.getInt("numberRays");
int peel = pars.getInt("peelingIteration");
mTolerance = pars.getFloat("peelingTolerance");
mPeelingTextureSize = pars.getInt("DepthTextureSize");
mUseVBO = pars.getBool("useVBO");
//RETRIEVE PARAMETERS
mOnPrimitive = (ONPRIMITIVE) pars.getEnum("onPrimitive");
// assert( mOnPrimitive==ON_VERTICES && "Face mode not supported yet" );
unsigned int numViews = pars.getInt("numberRays");
int peel = pars.getInt("peelingIteration");
mTolerance = pars.getFloat("peelingTolerance");
mPeelingTextureSize = pars.getInt("DepthTextureSize");
if(mAction != SDF_DEPTH_COMPLEXITY)
mMinCos = vcg::math::Cos(math::ToRad(pars.getFloat("coneAngle")/2.0));
if(mAction != SDF_DEPTH_COMPLEXITY)
mMinCos = vcg::math::Cos(math::ToRad(pars.getFloat("coneAngle")/2.0));
std::vector<Point3f> coneDirVec;
std::vector<Point3f> coneDirVec;
if(mAction == SDF_OBSCURANCE)
mTau = pars.getFloat("obscuranceExponent");
else if(mAction==SDF_SDF)
{
mRemoveFalse = pars.getBool("removeFalse");
mRemoveOutliers = pars.getBool("removeOutliers");
if(mAction == SDF_OBSCURANCE)
mTau = pars.getFloat("obscuranceExponent");
else if(mAction==SDF_SDF)
{
mRemoveFalse = pars.getBool("removeFalse");
mRemoveOutliers = pars.getBool("removeOutliers");
}
//MESH CLEAN UP
setupMesh( md, mOnPrimitive );
//glContext->makeCurrent();
//GL INIT
if(!initGL(*mm)) return false;
}
//MESH CLEAN UP
setupMesh( md, mOnPrimitive );
//GL INIT
if(!initGL(*mm)) return false;
//
if(mOnPrimitive==ON_VERTICES)
//
if(mOnPrimitive==ON_VERTICES)
vertexDataToTexture(*mm);
else
faceDataToTexture(*mm);
else
faceDataToTexture(*mm);
//Uniform sampling of directions over a sphere
std::vector<Point3f> unifDirVec;
GenNormal<float>::Fibonacci(numViews,unifDirVec);
//Uniform sampling of directions over a sphere
std::vector<Point3f> unifDirVec;
GenNormal<float>::Fibonacci(numViews,unifDirVec);
Log(0, "Number of rays: %i ", unifDirVec.size() );
Log(0, "Number of rays for GPU outliers removal: %i ", coneDirVec.size() );
Log(0, "Number of rays: %i ", unifDirVec.size() );
Log(0, "Number of rays for GPU outliers removal: %i ", coneDirVec.size() );
coneDirVec.clear();
coneDirVec.clear();
vector<int> mDepthDistrib(peel,0);
//Do the actual calculation of sdf or obscurance for each ray
unsigned int tracedRays = 0;
for(vector<vcg::Point3f>::iterator vi = unifDirVec.begin(); vi != unifDirVec.end(); vi++)
{
(*vi).Normalize();
vector<int> mDepthDistrib(peel,0);
//Do the actual calculation of sdf or obscurance for each ray
unsigned int tracedRays = 0;
for(vector<vcg::Point3f>::iterator vi = unifDirVec.begin(); vi != unifDirVec.end(); vi++)
{
(*vi).Normalize();
TraceRay(peel, (*vi), md.mm());
cb(100*((float)tracedRays/(float)unifDirVec.size()), "Tracing rays...");
this->glContext->makeCurrent();
glContext->makeCurrent();
++tracedRays;
mDepthComplexity = std::max(mDepthComplexity, mTempDepthComplexity);
mDepthDistrib[mTempDepthComplexity]++;
mTempDepthComplexity = 0;
}
}
//read back the result texture and store result in the mesh
if(mAction == SDF_OBSCURANCE)
{
if(mOnPrimitive == ON_VERTICES)
applyObscurancePerVertex(*mm,unifDirVec.size());
else
applyObscurancePerFace(*mm,unifDirVec.size());
}
else if(mAction == SDF_SDF)
{
if(mOnPrimitive == ON_VERTICES)
//read back the result texture and store result in the mesh
if(mAction == SDF_OBSCURANCE)
{
if(mOnPrimitive == ON_VERTICES)
applyObscurancePerVertex(*mm,unifDirVec.size());
else
applyObscurancePerFace(*mm,unifDirVec.size());
}
else if(mAction == SDF_SDF)
{
if(mOnPrimitive == ON_VERTICES)
applySdfPerVertex(*mm);
else
applySdfPerFace(*mm);
else
applySdfPerFace(*mm);
}
}
Log(0, "Mesh depth complexity %i (The accuracy of the result depends on the value you provided for the max number of peeling iterations, \n if you get warnings try increasing"
" the peeling iteration parameter)\n", mDepthComplexity );
Log(0, "Mesh depth complexity %i (The accuracy of the result depends on the value you provided for the max number of peeling iterations, \n if you get warnings try increasing"
" the peeling iteration parameter)\n", mDepthComplexity );
//Depth complexity distribution log. Useful to know which is the probability to find a number of layers looking at the mesh or scene.
Log(0, "Depth complexity NumberOfViews\n", mDepthComplexity );
for(int j = 0; j < peel; j++)
{
Log(0, " %i %i\n", j, mDepthDistrib[j] );
}
//Depth complexity distribution log. Useful to know which is the probability to find a number of layers looking at the mesh or scene.
Log(0, "Depth complexity NumberOfViews\n", mDepthComplexity );
for(int j = 0; j < peel; j++)
{
Log(0, " %i %i\n", j, mDepthDistrib[j] );
}
//Clean & Exit
releaseGL(*mm);
//Clean & Exit
releaseGL(*mm);
//glContext->doneCurrent();
mDepthComplexity = 0;
mDepthComplexity = 0;
return true;
return true;
}
bool SdfGpuPlugin::initGL(MeshModel& mm)
@ -272,37 +267,37 @@ bool SdfGpuPlugin::initGL(MeshModel& mm)
GLenum err = glewInit();
if (GLEW_OK != err)
{
Log(0,(const char*)glewGetErrorString(err));
return false;
Log(0,(const char*)glewGetErrorString(err));
return false;
}
//CHECK HARDWARE CAPABILITIES
if (!glewIsSupported("GL_ARB_vertex_shader GL_ARB_fragment_shader"))
{
if (!glewIsSupported("GL_EXT_vertex_shader GL_EXT_fragment_shader"))
{
Log(0, "Your hardware doesn't support Shaders, which are required for hw occlusion");
return false;
}
if (!glewIsSupported("GL_EXT_vertex_shader GL_EXT_fragment_shader"))
{
Log(0, "Your hardware doesn't support Shaders, which are required for hw occlusion");
return false;
}
}
if ( !glewIsSupported("GL_EXT_framebuffer_object") )
{
Log(0, "Your hardware doesn't support FBOs, which are required for hw occlusion");
return false;
Log(0, "Your hardware doesn't support FBOs, which are required for hw occlusion");
return false;
}
if ( glewIsSupported("GL_ARB_texture_float") )
{
if ( !glewIsSupported("GL_EXT_gpu_shader4") ) //Only DX10-grade cards support FP32 blending
{
Log(0,"Your hardware can't do FP32 blending, and currently the FP16 version is not yet implemented.");
return false;
}
if ( !glewIsSupported("GL_EXT_gpu_shader4") ) //Only DX10-grade cards support FP32 blending
{
Log(0,"Your hardware can't do FP32 blending, and currently the FP16 version is not yet implemented.");
return false;
}
}
else
{
Log(0,"Your hardware doesn't support floating point textures, which are required for hw occlusion");
return false;
Log(0,"Your hardware doesn't support floating point textures, which are required for hw occlusion");
return false;
}
GLint maxColorAttachments;
@ -325,13 +320,13 @@ bool SdfGpuPlugin::initGL(MeshModel& mm)
//CHECK MODEL SIZE
if ((maxTexSize*maxTexSize) < numElems)
{
Log(0, "That's a really huge model, I can't handle it in hardware, sorry..");
return false;
Log(0, "That's a really huge model, I can't handle it in hardware, sorry..");
return false;
}
for( mResTextureDim = 16; mResTextureDim*mResTextureDim < numElems; mResTextureDim *= 2 ){}
mNumberOfTexRows = ceil( ((float)numElems) / ((float)mResTextureDim));
mNumberOfTexRows = ceil( ((float)numElems) / ((float)mResTextureDim));
Log(0, "Mesh has %i vertices\n", numVertices );
Log(0, "Mesh has %i faces\n", numFaces);
@ -359,7 +354,7 @@ bool SdfGpuPlugin::initGL(MeshModel& mm)
for(int i = 0; i < 3; i++)
{
mDepthTextureArray[i] = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mPeelingTextureSize, mPeelingTextureSize, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT ),
TextureParams( GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE ) );
TextureParams( GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE ) );
mColorTextureArray[i] = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mPeelingTextureSize, mPeelingTextureSize, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_NEAREST, GL_NEAREST ) );
@ -420,13 +415,6 @@ bool SdfGpuPlugin::initGL(MeshModel& mm)
assert(mFboArray[2]->isValid());
//If required from the user, we use VBO to speed up mesh rendering
if(mUseVBO)
{
mm.glw.SetHint(vcg::GLW::HNUseVBO);
mm.glw.Update();
}
glGenQueriesARB( 1, &mOcclusionQuery );
checkGLError::debugInfo("GL Init failed");
@ -435,7 +423,7 @@ bool SdfGpuPlugin::initGL(MeshModel& mm)
}
void SdfGpuPlugin::faceDataToTexture(MeshModel &m)
{
{
unsigned int texSize = mResTextureDim*mResTextureDim*4;
GLfloat *facePosition= new GLfloat[texSize];
@ -445,22 +433,22 @@ void SdfGpuPlugin::faceDataToTexture(MeshModel &m)
//Copies each face's position and normal in new vectors
for (int i=0; i < m.cm.fn; ++i)
{
//face position
facePosition[i*4+0] = (m.cm.face[i].P(0).X() + m.cm.face[i].P(1).X() + m.cm.face[i].P(2).X())*(1.0/3.0);
facePosition[i*4+1] = (m.cm.face[i].P(0).Y() + m.cm.face[i].P(1).Y() + m.cm.face[i].P(2).Y())*(1.0/3.0);
facePosition[i*4+2] = (m.cm.face[i].P(0).Z() + m.cm.face[i].P(1).Z() + m.cm.face[i].P(2).Z())*(1.0/3.0);
facePosition[i*4+3] = 1.0;
//face position
facePosition[i*4+0] = (m.cm.face[i].P(0).X() + m.cm.face[i].P(1).X() + m.cm.face[i].P(2).X())*(1.0/3.0);
facePosition[i*4+1] = (m.cm.face[i].P(0).Y() + m.cm.face[i].P(1).Y() + m.cm.face[i].P(2).Y())*(1.0/3.0);
facePosition[i*4+2] = (m.cm.face[i].P(0).Z() + m.cm.face[i].P(1).Z() + m.cm.face[i].P(2).Z())*(1.0/3.0);
facePosition[i*4+3] = 1.0;
//Normal vector for each face
n = m.cm.face[i].N();
//Normal vector for each face
n = m.cm.face[i].N();
faceNormals[i*4+0] = n.X();
faceNormals[i*4+1] = n.Y();
faceNormals[i*4+2] = n.Z();
faceNormals[i*4+3] = 0.0;
faceNormals[i*4+0] = n.X();
faceNormals[i*4+1] = n.Y();
faceNormals[i*4+2] = n.Z();
faceNormals[i*4+3] = 0.0;
}
//Write vertex coordinates
//Write vertex coordinates
mVertexCoordsTexture->bind();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mResTextureDim, mResTextureDim, 0, GL_RGBA, GL_FLOAT, facePosition);
@ -472,43 +460,43 @@ void SdfGpuPlugin::faceDataToTexture(MeshModel &m)
delete [] facePosition;
}
}
void SdfGpuPlugin::vertexDataToTexture(MeshModel &m)
{
unsigned int texSize = mResTextureDim*mResTextureDim*4;
unsigned int texSize = mResTextureDim*mResTextureDim*4;
GLfloat *vertexPosition= new GLfloat[texSize];
GLfloat *vertexNormals = new GLfloat[texSize];
vcg::Point3<CMeshO::ScalarType> vn;
GLfloat *vertexPosition= new GLfloat[texSize];
GLfloat *vertexNormals = new GLfloat[texSize];
vcg::Point3<CMeshO::ScalarType> vn;
//Copies each vertex's position and normal in new vectors
for (int i=0; i < m.cm.vn; ++i)
{
//Vertex position
vertexPosition[i*4+0] = m.cm.vert[i].P().X();
vertexPosition[i*4+1] = m.cm.vert[i].P().Y();
vertexPosition[i*4+2] = m.cm.vert[i].P().Z();
vertexPosition[i*4+3] = 1.0;
//Copies each vertex's position and normal in new vectors
for (int i=0; i < m.cm.vn; ++i)
{
//Vertex position
vertexPosition[i*4+0] = m.cm.vert[i].P().X();
vertexPosition[i*4+1] = m.cm.vert[i].P().Y();
vertexPosition[i*4+2] = m.cm.vert[i].P().Z();
vertexPosition[i*4+3] = 1.0;
//Normal vector for each vertex
vn = m.cm.vert[i].N();
vertexNormals[i*4+0] = vn.X();
vertexNormals[i*4+1] = vn.Y();
vertexNormals[i*4+2] = vn.Z();
vertexNormals[i*4+3] = 0.0;
}
//Normal vector for each vertex
vn = m.cm.vert[i].N();
vertexNormals[i*4+0] = vn.X();
vertexNormals[i*4+1] = vn.Y();
vertexNormals[i*4+2] = vn.Z();
vertexNormals[i*4+3] = 0.0;
}
//Write vertex coordinates
mVertexCoordsTexture->bind();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mResTextureDim, mResTextureDim, 0, GL_RGBA, GL_FLOAT, vertexPosition);
//Write vertex coordinates
mVertexCoordsTexture->bind();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mResTextureDim, mResTextureDim, 0, GL_RGBA, GL_FLOAT, vertexPosition);
//Write normal directions
mVertexNormalsTexture->bind();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mResTextureDim, mResTextureDim, 0, GL_RGBA, GL_FLOAT, vertexNormals);
//Write normal directions
mVertexNormalsTexture->bind();
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mResTextureDim, mResTextureDim, 0, GL_RGBA, GL_FLOAT, vertexNormals);
delete [] vertexNormals;
delete [] vertexPosition;
delete [] vertexNormals;
delete [] vertexPosition;
}
void SdfGpuPlugin::releaseGL(MeshModel &m)
@ -531,11 +519,6 @@ void SdfGpuPlugin::releaseGL(MeshModel &m)
delete mColorTextureArray[i];
}
if (mUseVBO)
{
m.glw.ClearHint(vcg::GLW::HNUseVBO);
}
glDeleteQueriesARB( 1, &mOcclusionQuery );
checkGLError::debugInfo("GL release failed");
@ -545,16 +528,26 @@ void SdfGpuPlugin::releaseGL(MeshModel &m)
void SdfGpuPlugin::fillFrameBuffer(bool front, MeshModel* mm)
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glCullFace((front)?GL_BACK:GL_FRONT);
//the most recent GPUs can do double speed Z-only rendering
//(also alpha test must be turned off, depth replace and texkill must not be used in fragment shader)
//glColorMask(0, 0, 0, 0);
mm->glw.DrawFill<GLW::NMPerVert, GLW::CMNone, GLW::TMNone>();
//glColorMask(1, 1, 1, 1);
glDisable(GL_CULL_FACE);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_CULL_FACE);
glCullFace((front)?GL_BACK:GL_FRONT);
//the most recent GPUs can do double speed Z-only rendering
//(also alpha test must be turned off, depth replace and texkill must not be used in fragment shader)
//glColorMask(0, 0, 0, 0);
if (mm != NULL)
{
MLRenderingData dt;
MLRenderingData::RendAtts atts;
atts[MLRenderingData::ATT_NAMES::ATT_VERTPOSITION] = true;
atts[MLRenderingData::ATT_NAMES::ATT_VERTNORMAL] = true;
dt.set(MLRenderingData::PR_SOLID,atts);
glContext->setRenderingData(mm->id(),dt);
glContext->drawMeshModel(mm->id());
}
//mm->glw.DrawFill<GLW::NMPerVert, GLW::CMNone, GLW::TMNone>();
//glColorMask(1, 1, 1, 1);
//delete wid;
glDisable(GL_CULL_FACE);
}
void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive )
@ -566,9 +559,9 @@ void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive )
//If on vertices, do some cleaning first
if( onPrimitive == ON_VERTICES )
{
int dup = tri::Clean<CMeshO>::RemoveDuplicateVertex(m);
int unref = tri::Clean<CMeshO>::RemoveUnreferencedVertex(m);
if (dup > 0 || unref > 0) Log("Removed %i duplicate and %i unreferenced vertices\n",dup,unref);
int dup = tri::Clean<CMeshO>::RemoveDuplicateVertex(m);
int unref = tri::Clean<CMeshO>::RemoveUnreferencedVertex(m);
if (dup > 0 || unref > 0) Log("Removed %i duplicate and %i unreferenced vertices\n",dup,unref);
}
//Updating mesh metadata
@ -580,11 +573,11 @@ void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive )
//Enable & Reset the necessary attributes
switch(onPrimitive)
{
case ON_VERTICES:
case ON_VERTICES:
mm->updateDataMask(MeshModel::MM_VERTQUALITY);
tri::UpdateQuality<CMeshO>::VertexConstant(m,0);
break;
case ON_FACES:
case ON_FACES:
mm->updateDataMask(MeshModel::MM_FACEQUALITY);
mm->updateDataMask(MeshModel::MM_FACENORMAL);
mm->updateDataMask(MeshModel::MM_FACECOLOR);
@ -592,18 +585,19 @@ void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive )
break;
}
if(!vcg::tri::HasPerVertexAttribute(m,"maxQualityDir") && onPrimitive == ON_VERTICES)
mMaxQualityDirPerVertex = vcg::tri::Allocator<CMeshO>::AddPerVertexAttribute<Point3f>(m,std::string("maxQualityDir"));
else if(!vcg::tri::HasPerFaceAttribute(m,"maxQualityDir") && onPrimitive == ON_FACES)
if(!vcg::tri::HasPerVertexAttribute(m,"maxQualityDir") && onPrimitive == ON_VERTICES)
mMaxQualityDirPerVertex = vcg::tri::Allocator<CMeshO>::AddPerVertexAttribute<Point3f>(m,std::string("maxQualityDir"));
else if(!vcg::tri::HasPerFaceAttribute(m,"maxQualityDir") && onPrimitive == ON_FACES)
mMaxQualityDirPerFace = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<Point3f>(m,std::string("maxQualityDir"));
glContext->meshAttributesUpdated(mm->id(),true,MLRenderingData::RendAtts());
}
void SdfGpuPlugin::setCamera(Point3f camDir, Box3f meshBBox)
{
GLfloat d = (meshBBox.Diag()/2.0),
k = 0.1f;
k = 0.1f;
Point3f eye = meshBBox.Center() + camDir * (d+k);
mScale = 2*k+(2.0*d);
@ -617,18 +611,18 @@ void SdfGpuPlugin::setCamera(Point3f camDir, Box3f meshBBox)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eye.X(), eye.Y(), eye.Z(),
meshBBox.Center().X(), meshBBox.Center().Y(), meshBBox.Center().Z(),
0.0, 1.0, 0.0);
meshBBox.Center().X(), meshBBox.Center().Y(), meshBBox.Center().Z(),
0.0, 1.0, 0.0);
}
void SdfGpuPlugin::useDepthPeelingShader(FramebufferObject* fbo)
{
glUseProgram(mDeepthPeelingProgram->id());
mDeepthPeelingProgram->setUniform1f("tolerance", mTolerance);
mDeepthPeelingProgram->setUniform2f("oneOverBufSize", 1.0f/mPeelingTextureSize, 1.0f/mPeelingTextureSize);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo->getAttachedId(GL_DEPTH_ATTACHMENT));
mDeepthPeelingProgram->setUniform1i("textureLastDepth",0);
glUseProgram(mDeepthPeelingProgram->id());
mDeepthPeelingProgram->setUniform1f("tolerance", mTolerance);
mDeepthPeelingProgram->setUniform2f("oneOverBufSize", 1.0f/mPeelingTextureSize, 1.0f/mPeelingTextureSize);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, fbo->getAttachedId(GL_DEPTH_ATTACHMENT));
mDeepthPeelingProgram->setUniform1i("textureLastDepth",0);
}
void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* fboPrevBack, const vcg::Point3f& cameraDir)
@ -657,7 +651,7 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
// glDepthMask(GL_FALSE);
// glDepthMask(GL_FALSE);
glEnable (GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE);
@ -721,12 +715,12 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject
if(fboPrevBack == NULL)
mSDFProgram->setUniform1i("firstRendering",1);
else
mSDFProgram->setUniform1i("firstRendering",0);
mSDFProgram->setUniform1i("firstRendering",0);
if(mRemoveFalse)
mSDFProgram->setUniform1i("removeFalse",1);
else
mSDFProgram->setUniform1i("removeFalse",0);
mSDFProgram->setUniform1i("removeFalse",0);
if(mRemoveOutliers)
mSDFProgram->setUniform1i("removeOutliers",1);
@ -735,17 +729,17 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject
// Screen-aligned Quad
glBegin(GL_QUADS);
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glEnd();
mFboResult->unbind();
glEnable(GL_DEPTH_TEST);
// glDepthMask(GL_TRUE);
// glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
}
@ -775,7 +769,7 @@ void SdfGpuPlugin::applySdfPerVertex(MeshModel &m)
Point3f dir = Point3f(result[i*4], result[i*4+1], result[i*4+2]);
vcg::Normalize(dir);
mMaxQualityDirPerVertex[i] = dir;
// Log(0,"vertice %i: %f %f %f",i,dir.X(),dir.Y(),dir.Z());
// Log(0,"vertice %i: %f %f %f",i,dir.X(),dir.Y(),dir.Z());
}
@ -810,7 +804,7 @@ void SdfGpuPlugin::applySdfPerFace(MeshModel &m)
Point3f dir = Point3f(result[i*4], result[i*4+1], result[i*4+2]);
vcg::Normalize(dir);
mMaxQualityDirPerFace[i] = dir;
// Log(0,"vertice %i: %f %f %f",i,dir.X(),dir.Y(),dir.Z());
// Log(0,"vertice %i: %f %f %f",i,dir.X(),dir.Y(),dir.Z());
}
@ -901,14 +895,14 @@ void SdfGpuPlugin::calculateObscurance(FramebufferObject* fboFront, FramebufferO
if(nextBack == NULL)
mObscuranceProgram->setUniform1i("firstRendering",1);
else
mObscuranceProgram->setUniform1i("firstRendering",0);
mObscuranceProgram->setUniform1i("firstRendering",0);
// Screen-aligned Quad
glBegin(GL_QUADS);
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glVertex3f(-1.0f, -1.0f, 0.0f); //L-L
glVertex3f( 1.0f, -1.0f, 0.0f); //L-R
glVertex3f( 1.0f, 1.0f, 0.0f); //U-R
glVertex3f(-1.0f, 1.0f, 0.0f); //U-L
glEnd();
assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)==GL_FRAMEBUFFER_COMPLETE_EXT && "after draw");
@ -980,7 +974,7 @@ void SdfGpuPlugin::applyObscurancePerFace(MeshModel &m, float numberOfRays)
Point3f dir = Point3f(result[i*4], result[i*4+1], result[i*4+2]);
vcg::Normalize(dir);
mMaxQualityDirPerFace[i] = dir;
mMaxQualityDirPerFace[i] = dir;
}
@ -992,7 +986,7 @@ void SdfGpuPlugin::applyObscurancePerFace(MeshModel &m, float numberOfRays)
void SdfGpuPlugin::preRender(unsigned int peelingIteration)
{
if( peelingIteration != 0 )
glBeginQueryARB( GL_SAMPLES_PASSED_ARB, mOcclusionQuery );
glBeginQueryARB( GL_SAMPLES_PASSED_ARB, mOcclusionQuery );
}
@ -1022,13 +1016,13 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
for( int i = 0; i < peelingIteration; i++ )
{
if( i == 0 )
glUseProgram(0);
glUseProgram(0);
else
{
if(j > 0)
useDepthPeelingShader(mFboArray[j-1]);
else
useDepthPeelingShader(mFboArray[2]);
if(j > 0)
useDepthPeelingShader(mFboArray[j-1]);
else
useDepthPeelingShader(mFboArray[2]);
}
mFboArray[j]->bind();
@ -1046,49 +1040,49 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
if(i==(peelingIteration-1))
Log(0,"WARNING: You may have underestimated the depth complexity of the mesh. Run the filter with a higher number of peeling iteration.");
mFboArray[j]->unbind();
//we use 3 FBOs to avoid z-fighting (Inspired from Woo's shadow mapping method)
if(i%2)
{
//we use the same method as in sdf, see below
if(mAction==SDF_OBSCURANCE )
{
if(i>1)
{
int prevBack = (j+1)%3;
int front = (j==0)? 2 : (j-1);
calculateObscurance( mFboArray[front], mFboArray[prevBack], mFboArray[j], dir, mm->cm.bbox.Diag());//front prevBack Back
}
else
{
assert(j!=0);
calculateObscurance( mFboArray[j-1], mFboArray[j], NULL, dir, mm->cm.bbox.Diag());//front back nextBack
mFboArray[j]->unbind();
//we use 3 FBOs to avoid z-fighting (Inspired from Woo's shadow mapping method)
if(i%2)
{
//we use the same method as in sdf, see below
if(mAction==SDF_OBSCURANCE )
{
if(i>1)
{
int prevBack = (j+1)%3;
int front = (j==0)? 2 : (j-1);
calculateObscurance( mFboArray[front], mFboArray[prevBack], mFboArray[j], dir, mm->cm.bbox.Diag());//front prevBack Back
}
else
{
assert(j!=0);
calculateObscurance( mFboArray[j-1], mFboArray[j], NULL, dir, mm->cm.bbox.Diag());//front back nextBack
}
}
else if(mAction == SDF_SDF)
{
if(i>1)
{
//We are interested in vertices belonging to the front layer. Then in the shader, we check that
//the vertex's depth is greater than the previous depth layer and smaller than the next one.
int prevBack = (j+1)%3;
int prevFront = (j==0)? 2 : (j-1);
calculateSdfHW( mFboArray[prevFront], mFboArray[j], mFboArray[prevBack],dir );// front back prevback
}
else
{ //we have first and second depth layers, so we can use "second-depth shadow mapping" to avoid z-fighting
assert(j!=0);
calculateSdfHW( mFboArray[j-1], mFboArray[j], NULL, dir );// front back prevback
}
}
}
}
else if(mAction == SDF_SDF)
{
if(i>1)
{
//We are interested in vertices belonging to the front layer. Then in the shader, we check that
//the vertex's depth is greater than the previous depth layer and smaller than the next one.
int prevBack = (j+1)%3;
int prevFront = (j==0)? 2 : (j-1);
calculateSdfHW( mFboArray[prevFront], mFboArray[j], mFboArray[prevBack],dir );// front back prevback
}
else
{ //we have first and second depth layers, so we can use "second-depth shadow mapping" to avoid z-fighting
assert(j!=0);
calculateSdfHW( mFboArray[j-1], mFboArray[j], NULL, dir );// front back prevback
}
}
}
}
//increment and wrap around
j = (j+1) % 3;
}
//increment and wrap around
j = (j+1) % 3;
}
assert(mFboResult->isValid());
assert(mFboArray[0]->isValid());
@ -1098,5 +1092,10 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel*
checkGLError::debugInfo("Error during depth peeling");
}
MeshFilterInterface::FILTER_ARITY SdfGpuPlugin::filterArity( QAction *) const
{
return MeshFilterInterface::SINGLE_MESH;
}
MESHLAB_PLUGIN_NAME_EXPORTER(SdfGpuPlugin)

View File

@ -32,6 +32,8 @@ public:
return MeshFilterInterface::VertexColoring;
}
FILTER_ARITY filterArity(QAction *act) const;
//Main plugin function
bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb);
@ -101,7 +103,6 @@ public:
FramebufferObject* mFboArray[3]; //Fbos and textures for depth peeling
FloatTexture2D* mDepthTextureArray[3];
FloatTexture2D* mColorTextureArray[3];
bool mUseVBO;
unsigned int mPeelingTextureSize;
float mTolerance;
float mMinCos;
@ -122,7 +123,6 @@ public:
CMeshO::PerFaceAttributeHandle<vcg::Point3f> mMaxQualityDirPerFace;
CMeshO::PerVertexAttributeHandle<vcg::Point3f> mMaxQualityDirPerVertex;
};
#endif // FILTER_SDFGPU_H

View File

@ -72,6 +72,7 @@ class SelectionFilterPlugin : public QObject, public MeshFilterInterface
int postCondition( QAction* ) const;
int getRequirements(QAction *);
bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};
#endif

View File

@ -33,37 +33,37 @@
class FilterSSynth : public QObject,public MeshIOInterface, public MeshFilterInterface{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum {CR_SSYNTH} ;
public:
enum {CR_SSYNTH} ;
FilterSSynth();
~FilterSSynth(){}
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual int getRequirements(QAction *);
virtual void initParameterSet(QAction* filter,MeshModel &,RichParameterSet &){};
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction* filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb);
virtual FilterClass getClass(QAction* filter);
void setAttributes(CMeshO::VertexIterator &vi, CMeshO &m);
static void openX3D(const QString &fileName, MeshModel &m, int& mask, vcg::CallBackPos *cb, QWidget *parent=0);
virtual int postCondition(QAction* filter) const;
QList<Format> importFormats() const;
QList<Format> exportFormats() const;
virtual void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const;
void initPreOpenParameter(const QString &formatName, const QString &filename, RichParameterSet &parlst);
bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent=0);
bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet &, vcg::CallBackPos *cb, QWidget *parent);
FilterSSynth();
~FilterSSynth(){}
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual int getRequirements(QAction *);
virtual void initParameterSet(QAction* filter,MeshModel &,RichParameterSet &){};
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction* filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb);
virtual FilterClass getClass(QAction* filter);
void setAttributes(CMeshO::VertexIterator &vi, CMeshO &m);
static void openX3D(const QString &fileName, MeshModel &m, int& mask, vcg::CallBackPos *cb, QWidget *parent=0);
virtual int postCondition(QAction* filter) const;
QList<Format> importFormats() const;
QList<Format> exportFormats() const;
virtual void GetExportMaskCapability(QString &format, int &capability, int &defaultBits) const;
void initPreOpenParameter(const QString &formatName, const QString &filename, RichParameterSet &parlst);
bool open(const QString &formatName, const QString &fileName, MeshModel &m, int& mask, const RichParameterSet & par, vcg::CallBackPos *cb=0, QWidget *parent=0);
bool save(const QString &formatName, const QString &fileName, MeshModel &m, const int mask, const RichParameterSet &, vcg::CallBackPos *cb, QWidget *parent);
MeshFilterInterface::FILTER_ARITY filterArity(QAction *) const {return NONE;}
private:
QString ssynth(QString grammar,int maxdepth,int seed,vcg::CallBackPos *cb);
QString GetTemplate(int sphereres);
void ParseGram(QString* grammar,int max,QString pattern);
int seed;
QString renderTemplate;
QString spheres[6];
};
QString ssynth(QString grammar,int maxdepth,int seed,vcg::CallBackPos *cb);
QString GetTemplate(int sphereres);
void ParseGram(QString* grammar,int max,QString pattern);
int seed;
QString renderTemplate;
QString spheres[6];
};
#endif // FILTER_SSYNTH_H

View File

@ -1049,4 +1049,24 @@ bool FilterTexturePlugin::applyFilter(QAction *filter, MeshDocument &md, RichPar
return true;
}
MeshFilterInterface::FILTER_ARITY FilterTexturePlugin::filterArity( QAction * filter ) const
{
switch(ID(filter))
{
case FP_VORONOI_ATLAS :
case FP_UV_WEDGE_TO_VERTEX :
case FP_UV_VERTEX_TO_WEDGE :
case FP_BASIC_TRIANGLE_MAPPING :
case FP_PLANAR_MAPPING :
case FP_SET_TEXTURE :
case FP_COLOR_TO_TEXTURE :
return MeshFilterInterface::SINGLE_MESH;
case FP_TRANSFER_TO_TEXTURE :
case FP_TEX_TO_VCOLOR_TRANSFER :
return MeshFilterInterface::FIXED;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterTexturePlugin)

View File

@ -36,34 +36,34 @@
class FilterTexturePlugin : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
public:
enum {
FP_VORONOI_ATLAS,
FP_UV_WEDGE_TO_VERTEX,
FP_UV_VERTEX_TO_WEDGE,
FP_BASIC_TRIANGLE_MAPPING,
FP_PLANAR_MAPPING,
FP_SET_TEXTURE,
FP_COLOR_TO_TEXTURE,
FP_TRANSFER_TO_TEXTURE,
FP_TEX_TO_VCOLOR_TRANSFER
};
enum {
FP_VORONOI_ATLAS,
FP_UV_WEDGE_TO_VERTEX,
FP_UV_VERTEX_TO_WEDGE,
FP_BASIC_TRIANGLE_MAPPING,
FP_PLANAR_MAPPING,
FP_SET_TEXTURE,
FP_COLOR_TO_TEXTURE,
FP_TRANSFER_TO_TEXTURE,
FP_TEX_TO_VCOLOR_TRANSFER
};
FilterTexturePlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
FilterTexturePlugin();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb);
virtual int getRequirements(QAction *);
virtual int getPreConditions(QAction *) const;
virtual int postCondition( QAction* ) const;
virtual int getRequirements(QAction *);
virtual int getPreConditions(QAction *) const;
virtual int postCondition( QAction* ) const;
FilterClass getClass(QAction *a);
FILTER_ARITY filterArity(QAction * filter) const;
};
#endif

View File

@ -51,6 +51,7 @@ public:
int getRequirements(QAction *);
FilterClass getClass(QAction *);
int postCondition( QAction* ) const;
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
};

View File

@ -671,5 +671,35 @@ bool FilterUnsharp::applyFilter(QAction *filter, MeshDocument &md, RichParameter
return true;
}
MeshFilterInterface::FILTER_ARITY FilterUnsharp::filterArity( QAction * filter ) const
{
switch(ID(filter))
{
case FP_LAPLACIAN_SMOOTH :
case FP_HC_LAPLACIAN_SMOOTH :
case FP_SD_LAPLACIAN_SMOOTH :
case FP_TWO_STEP_SMOOTH :
case FP_TAUBIN_SMOOTH :
case FP_DEPTH_SMOOTH :
case FP_DIRECTIONAL_PRESERVATION :
case FP_CREASE_CUT :
case FP_FACE_NORMAL_NORMALIZE:
case FP_VERTEX_NORMAL_NORMALIZE:
case FP_FACE_NORMAL_SMOOTHING:
case FP_VERTEX_QUALITY_SMOOTHING:
case FP_UNSHARP_NORMAL:
case FP_UNSHARP_GEOMETRY:
case FP_UNSHARP_QUALITY:
case FP_UNSHARP_VERTEX_COLOR:
case FP_RECOMPUTE_VERTEX_NORMAL:
case FP_RECOMPUTE_FACE_NORMAL:
case FP_RECOMPUTE_QUADFACE_NORMAL:
return MeshFilterInterface::SINGLE_MESH;
case FP_LINEAR_MORPH :
return MeshFilterInterface::FIXED;
}
return MeshFilterInterface::NONE;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterUnsharp)

View File

@ -74,9 +74,8 @@ class FilterUnsharp : public QObject, public MeshFilterInterface
void initParameterSet(QAction *action, MeshDocument &/*m*/, RichParameterSet & parlst);
int postCondition( QAction* ) const;
int getPreConditions(QAction *) const;
FILTER_ARITY filterArity(QAction * filter) const;
protected:
};

View File

@ -50,24 +50,24 @@ struct aux_info {
float eps; //epsilon
//Add segment c to border
virtual bool AddToBorder( vcg::Segment3<CMeshO::ScalarType> c, std::pair<int, int> v ) {
/****Insert new segment****/
/****Insert new segment****/
//Search for segment S having S.P0() == c.P1 or S.P1 == c.P0()
if ( v.first == 4013 && v.second == 4015 )
int stop = 3;
if ( v.first == v.second ) return false;
if ( v.first == 4013 && v.second == 4015 )
int stop = 3;
if ( v.first == v.second ) return false;
if ( c.Length() < eps ) {
c.P0() = c.P1();
v.first = v.second;
//if segment is too short (it's basically a point) check if it's one of the vertices
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
if ( vcg::Distance<Scalarm>( trash[i].edges[j].P0(), c.P0() ) < eps ) return false;
}
}
}
c.P0() = c.P1();
v.first = v.second;
//if segment is too short (it's basically a point) check if it's one of the vertices
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
if ( vcg::Distance<Scalarm>( trash[i].edges[j].P0(), c.P0() ) < eps ) return false;
}
}
}
if ( v.first == 4013 && v.second == 4013 )
int stop = 3;
if ( v.first == 4013 && v.second == 4013 )
int stop = 3;
//check if c doesn't lie on existing edges
//if it does, split edge
for ( size_t i = 0; i < trash.size(); i ++ ) {
@ -132,8 +132,8 @@ struct aux_info {
for ( unsigned int j = 0; j < border.size(); j ++ ) {
for ( size_t i = 0; i < border[j].verts.size() && !found; i ++ ) {
if ( border[j].verts[i].first == v.second ) { found = true; border[j].edges.insert( border[j].edges.begin() + i, c ); border[j].verts.insert( border[j].verts.begin() + i, v ); } //insert before i-th element
else
if ( border[j].verts[i].second == v.first ) { found = true; border[j].edges.insert( border[j].edges.begin() + i + 1, c ); border[j].verts.insert( border[j].verts.begin() + i + 1, v ); } //insert after i-th element
else
if ( border[j].verts[i].second == v.first ) { found = true; border[j].edges.insert( border[j].edges.begin() + i + 1, c ); border[j].verts.insert( border[j].verts.begin() + i + 1, v ); } //insert after i-th element
}
}
if (!found) { //Create a new polyline ad add it to the border list
@ -147,11 +147,11 @@ struct aux_info {
border[j].verts.insert( border[j].verts.begin(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
else if ( border[j].verts.back().second == border[i].verts.front().first ) {
border[j].edges.insert( border[j].edges.end(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.end(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
else if ( border[j].verts.back().second == border[i].verts.front().first ) {
border[j].edges.insert( border[j].edges.end(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.end(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
}
}//end if (!found)
@ -162,10 +162,10 @@ struct aux_info {
trash[i].edges[j].P0() = border[k].edges.back().P1();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
} else
if ( trash[i].verts[j].first == border[k].verts.front().first ) {
trash[i].edges[j].P0() = border[k].edges.front().P0();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
}
if ( trash[i].verts[j].first == border[k].verts.front().first ) {
trash[i].edges[j].P0() = border[k].edges.front().P0();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
}
}
}
}
@ -190,11 +190,11 @@ struct aux_info {
virtual void Init( CMeshO::FaceType f, int a, int b, int c ) {
if (!trash.empty()) return;
polyline tri; tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(0), f.P(1)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(1), f.P(2)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(2), f.P(0)) );
tri.verts.push_back( std::make_pair(a, b) );
tri.verts.push_back( std::make_pair(b, c) );
tri.verts.push_back( std::make_pair(c, a) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(1), f.P(2)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(2), f.P(0)) );
tri.verts.push_back( std::make_pair(a, b) );
tri.verts.push_back( std::make_pair(b, c) );
tri.verts.push_back( std::make_pair(c, a) );
AddTComponent( tri );
}
@ -218,254 +218,254 @@ struct aux_info {
return trash.size();
}
// Add vertex in original triangle
virtual bool addVertex( CMeshO::VertexPointer v, int v_index ) {
int cnt = 0; int split = -1;
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
// Add vertex in original triangle
virtual bool addVertex( CMeshO::VertexPointer v, int v_index ) {
int cnt = 0; int split = -1;
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //search for closest edge
if ( trash[i].verts[j].first == v_index ) return false;
}
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //search for closest edge
if ( trash[i].verts[j].first == v_index ) return false;
}
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
//if ( vcg::SquaredDistance<float>( trash[i].edges[j], v->P() ) <= eps ) {
Scalarm dist;
Point3m clos;
vcg::SegmentPointSquaredDistance<Scalarm>(trash[i].edges[j], v->P(),clos,dist);
if (dist <= eps ) {
cnt++; split = j;
}
}
}
if (!cnt) return false;
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
//if ( vcg::SquaredDistance<float>( trash[i].edges[j], v->P() ) <= eps ) {
Scalarm dist;
Point3m clos;
vcg::SegmentPointSquaredDistance<Scalarm>(trash[i].edges[j], v->P(),clos,dist);
if (dist <= eps ) {
cnt++; split = j;
}
}
}
if (!cnt) return false;
if ( cnt == 1 ) { //one edge only -> split the edge
vcg::Segment3<CMeshO::ScalarType> splitting_edge = trash[0].edges[split];
std::pair<int, int> splitting_edge_v = trash[0].verts[split];
if ( cnt == 1 ) { //one edge only -> split the edge
vcg::Segment3<CMeshO::ScalarType> splitting_edge = trash[0].edges[split];
std::pair<int, int> splitting_edge_v = trash[0].verts[split];
trash[0].edges.erase(trash[0].edges.begin()+split); //remove edge
trash[0].verts.erase(trash[0].verts.begin()+split);
//replace edge using two new edges
trash[0].edges.insert(trash[0].edges.begin()+split, vcg::Segment3<CMeshO::ScalarType>( splitting_edge.P0(), v->P() ) );
trash[0].edges.insert(trash[0].edges.begin()+split+1, vcg::Segment3<CMeshO::ScalarType>( v->P(), splitting_edge.P1() ) );
trash[0].verts.insert(trash[0].verts.begin()+split, std::make_pair( splitting_edge_v.first, v_index ) );
trash[0].verts.insert(trash[0].verts.begin()+split+1, std::make_pair( v_index, splitting_edge_v.second ) );
}
trash[0].edges.erase(trash[0].edges.begin()+split); //remove edge
trash[0].verts.erase(trash[0].verts.begin()+split);
//replace edge using two new edges
trash[0].edges.insert(trash[0].edges.begin()+split, vcg::Segment3<CMeshO::ScalarType>( splitting_edge.P0(), v->P() ) );
trash[0].edges.insert(trash[0].edges.begin()+split+1, vcg::Segment3<CMeshO::ScalarType>( v->P(), splitting_edge.P1() ) );
trash[0].verts.insert(trash[0].verts.begin()+split, std::make_pair( splitting_edge_v.first, v_index ) );
trash[0].verts.insert(trash[0].verts.begin()+split+1, std::make_pair( v_index, splitting_edge_v.second ) );
}
if ( cnt == 2 ) { // search for closest vertex and copy vertex coords
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
if ( vcg::Distance<Scalarm>( trash[i].edges[j].P0(), v->P() ) <= eps ) {
v->P() = trash[i].edges[j].P0();
}
}
}
}
if ( cnt == 2 ) { // search for closest vertex and copy vertex coords
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
if ( vcg::Distance<Scalarm>( trash[i].edges[j].P0(), v->P() ) <= eps ) {
v->P() = trash[i].edges[j].P0();
}
}
}
}
return true;
}
return true;
}
};//end struct
class compareFaceQuality {
public:
compareFaceQuality() { };
public:
compareFaceQuality() { };
bool operator () (const std::pair<CMeshO::FacePointer,char> f1, const std::pair<CMeshO::FacePointer,char> f2) {
//quality f1 < quality f2 return true
return ( f1.first->Q() > f2.first->Q() );
}
bool operator () (const std::pair<CMeshO::FacePointer,char> f1, const std::pair<CMeshO::FacePointer,char> f2) {
//quality f1 < quality f2 return true
return ( f1.first->Q() > f2.first->Q() );
}
};
class FilterZippering : public QObject, public MeshFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESH_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshFilterInterface)
typedef vcg::GridStaticPtr<CMeshO::FaceType, CMeshO::ScalarType > MeshFaceGrid;
typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType > MeshVertGrid;
public:
//Different operations in different plugins
enum { FP_REDUNDANCY,
FP_ZIPPERING };
//Different operations in different plugins
enum { FP_REDUNDANCY,
FP_ZIPPERING };
FilterZippering();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
int getRequirements(QAction *action);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
virtual int postCondition( QAction */*a*/ ) const { return MeshModel::MM_FACEFACETOPO|MeshModel::MM_VERTNORMAL; }
FilterZippering();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
int getRequirements(QAction *action);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
virtual int postCondition( QAction */*a*/ ) const { return MeshModel::MM_FACEFACETOPO|MeshModel::MM_VERTNORMAL; }
FILTER_ARITY filterArity(QAction *) const {return FIXED;}
private:
template <class ScalarType>
ScalarType SquaredDistance( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
template <class ScalarType>
vcg::Point3<ScalarType> ClosestPoint( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
template <class ScalarType>
ScalarType SquaredDistance( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
bool checkRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist ); //Max search distance
bool simpleCheckRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist,//Max search distance
bool test );
bool isBorderVert( CMeshO::FacePointer f, int i);
bool isOnBorder( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isOnEdge( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isAdjacent( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
int sharesVertex( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
void handleBorder( aux_info &info, //Auxiliar information for triangulatio
vcg::Point3<CMeshO::ScalarType> N, //face normal (useful for proiection)
std::vector<CMeshO::CoordType> &coords, //output coords
std::vector<int> &output ); //output v. pointers
polyline cutComponent( polyline comp, //Component to be cut
polyline border, //border
vcg::Matrix44<CMeshO::ScalarType> rot_mat ); //Rotation matrix
int searchComponent( aux_info &info, //Auxiliar info
vcg::Point3<CMeshO::ScalarType> P0, //Start border point
vcg::Point3<CMeshO::ScalarType> P1, //End border point
bool &conn );
bool findIntersection( CMeshO::FacePointer currentF, //face
vcg::Segment3<CMeshO::ScalarType> edge, //edge
int last_split, //last splitted edge
int &splitted_edge, //currently splitted edge
vcg::Point3<CMeshO::ScalarType> &hit ); //approximate intersection point
template <class ScalarType>
vcg::Point3<ScalarType> ClosestPoint( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
bool checkRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist ); //Max search distance
bool simpleCheckRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist,//Max search distance
bool test );
bool isBorderVert( CMeshO::FacePointer f, int i);
bool isOnBorder( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isOnEdge( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isAdjacent( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
int sharesVertex( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
void handleBorder( aux_info &info, //Auxiliar information for triangulatio
vcg::Point3<CMeshO::ScalarType> N, //face normal (useful for proiection)
std::vector<CMeshO::CoordType> &coords, //output coords
std::vector<int> &output ); //output v. pointers
polyline cutComponent( polyline comp, //Component to be cut
polyline border, //border
vcg::Matrix44<CMeshO::ScalarType> rot_mat ); //Rotation matrix
int searchComponent( aux_info &info, //Auxiliar info
vcg::Point3<CMeshO::ScalarType> P0, //Start border point
vcg::Point3<CMeshO::ScalarType> P1, //End border point
bool &conn );
bool findIntersection( CMeshO::FacePointer currentF, //face
vcg::Segment3<CMeshO::ScalarType> edge, //edge
int last_split, //last splitted edge
int &splitted_edge, //currently splitted edge
vcg::Point3<CMeshO::ScalarType> &hit ); //approximate intersection point
//init unsorted queue
bool Init_q( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess ); //fullProcess flag
//init priority queue (overload)
bool Init_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess );
//select redundant face (normal method, unsorted queue)
int selectRedundant( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//select redundant face (normal method, priority queue)
int selectRedundant_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//refine border of a mesh, splitting faces having two border edges
int refineBorder( MeshModel* m );
//project face of B on the surface of A
void projectFace( CMeshO::FacePointer f, //pointer to the face that will be projected
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A
float max_dist, //max dist search
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector< CMeshO::FacePointer >& tbt_faces, //vector to-be-triangulated faces
std::vector< CMeshO::FacePointer >& tbr_faces, //vector to-be-removed faces
std::vector< int >& verts ); //vector of indices
//case 01: vertices of border edge project on the same face
void handleBorderEdgeSF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//init unsorted queue
bool Init_q( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess ); //fullProcess flag
//init priority queue (overload)
bool Init_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess );
//select redundant face (normal method, unsorted queue)
int selectRedundant( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//select redundant face (normal method, priority queue)
int selectRedundant_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//refine border of a mesh, splitting faces having two border edges
int refineBorder( MeshModel* m );
//project face of B on the surface of A
void projectFace( CMeshO::FacePointer f, //pointer to the face that will be projected
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A
float max_dist, //max dist search
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector< CMeshO::FacePointer >& tbt_faces, //vector to-be-triangulated faces
std::vector< CMeshO::FacePointer >& tbr_faces, //vector to-be-removed faces
std::vector< int >& verts ); //vector of indices
//case 02: vertices of border edge project on adjacent faces
void handleBorderEdgeAF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 01: vertices of border edge project on the same face
void handleBorderEdgeSF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 03: vertices of border edge project on non-adjacent faces
void handleBorderEdgeNF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 02: vertices of border edge project on adjacent faces
void handleBorderEdgeAF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
vcg::Point3<CMeshO::ScalarType> closestStart, //closest point on startF
vcg::Point3<CMeshO::ScalarType> closestEnd, //closest point on endF
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 03: vertices of border edge project on non-adjacent faces
void handleBorderEdgeNF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
vcg::Point3<CMeshO::ScalarType> closestStart, //closest point on startF
vcg::Point3<CMeshO::ScalarType> closestEnd, //closest point on endF
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 05: one of the vertices doesn't project on the surface of the mesh
void handleBorderEdgeOB ( std::pair< int, int >& current_edge, //current border edge
int direction, //splitting direction (1 from start to end, 0 from end to start)
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< CMeshO::FacePointer >& tbt_faces, //stack containing pointers to face that wille be retriangulated
std::vector< int >& verts ); //vector of indices
int preProcess ( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
//case 05: one of the vertices doesn't project on the surface of the mesh
void handleBorderEdgeOB ( std::pair< int, int >& current_edge, //current border edge
int direction, //splitting direction (1 from start to end, 0 from end to start)
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< CMeshO::FacePointer >& tbt_faces, //stack containing pointers to face that wille be retriangulated
std::vector< int >& verts ); //vector of indices
int preProcess_pq ( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
int preProcess ( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
int preProcess_pq ( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
float eps;
float eps;
int dbg_cnt;
int dbg_cnt;
};
#endif