mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-20 03:16:10 +00:00
- bug fixing
- integration - so on...
This commit is contained in:
parent
bd33bba9e1
commit
d311c3f2a6
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 ¶ms);
|
||||
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet ¶ms, vcg::CallBackPos *cb);
|
||||
virtual FilterClass getClass(QAction *);
|
||||
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet ¶ms, 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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) ;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
@ -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 *);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -51,6 +51,7 @@ public:
|
||||
int getRequirements(QAction *);
|
||||
FilterClass getClass(QAction *);
|
||||
int postCondition( QAction* ) const;
|
||||
FILTER_ARITY filterArity(QAction *) const {return SINGLE_MESH;}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user