added a slightly faster version of the longest edge stratified subdivision sampling
This commit is contained in:
parent
6e3f10928e
commit
1c0ae1268c
|
@ -463,58 +463,56 @@ static int SingleFaceSubdivision(int sampleNum, const CoordType & v0, const Coor
|
||||||
if(sampleNum == 1)
|
if(sampleNum == 1)
|
||||||
{
|
{
|
||||||
// ground case.
|
// ground case.
|
||||||
CoordType SamplePoint;
|
CoordType SamplePoint;
|
||||||
if(randSample)
|
if(randSample)
|
||||||
{
|
{
|
||||||
CoordType rb=RandomBaricentric();
|
CoordType rb=RandomBaricentric();
|
||||||
SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
|
SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
|
||||||
}
|
}
|
||||||
else SamplePoint=((v0+v1+v2)/3.0f);
|
else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
|
||||||
|
|
||||||
CoordType SampleBary;
|
|
||||||
InterpolationParameters(*fp,SamplePoint,SampleBary[0],SampleBary[1],SampleBary[2]);
|
|
||||||
ps.AddFace(*fp,SampleBary);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int s0 = sampleNum /2;
|
ps.AddFace(*fp,SamplePoint);
|
||||||
int s1 = sampleNum-s0;
|
return 1;
|
||||||
assert(s0>0);
|
}
|
||||||
assert(s1>0);
|
|
||||||
|
int s0 = sampleNum /2;
|
||||||
|
int s1 = sampleNum-s0;
|
||||||
|
assert(s0>0);
|
||||||
|
assert(s1>0);
|
||||||
|
|
||||||
ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
|
ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
|
||||||
ScalarType w1 = 1.0-w0;
|
ScalarType w1 = 1.0-w0;
|
||||||
// compute the longest edge.
|
// compute the longest edge.
|
||||||
double maxd01 = SquaredDistance(v0,v1);
|
ScalarType maxd01 = SquaredDistance(v0,v1);
|
||||||
double maxd12 = SquaredDistance(v1,v2);
|
ScalarType maxd12 = SquaredDistance(v1,v2);
|
||||||
double maxd20 = SquaredDistance(v2,v0);
|
ScalarType maxd20 = SquaredDistance(v2,v0);
|
||||||
int res;
|
int res;
|
||||||
if(maxd01 > maxd12)
|
if(maxd01 > maxd12)
|
||||||
if(maxd01 > maxd20) res = 0;
|
if(maxd01 > maxd20) res = 0;
|
||||||
else res = 2;
|
else res = 2;
|
||||||
else
|
else
|
||||||
if(maxd12 > maxd20) res = 1;
|
if(maxd12 > maxd20) res = 1;
|
||||||
else res = 2;
|
else res = 2;
|
||||||
|
|
||||||
int faceSampleNum=0;
|
int faceSampleNum=0;
|
||||||
// break the input triangle along the midpoint of the longest edge.
|
// break the input triangle along the midpoint of the longest edge.
|
||||||
CoordType pp;
|
CoordType pp;
|
||||||
switch(res)
|
switch(res)
|
||||||
{
|
{
|
||||||
case 0 : pp = v0*w0 + v1*w1;
|
case 0 : pp = v0*w0 + v1*w1;
|
||||||
faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
|
||||||
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
||||||
break;
|
break;
|
||||||
case 1 : pp = v1*w0 + v2*w1;
|
case 1 : pp = v1*w0 + v2*w1;
|
||||||
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
||||||
faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
|
||||||
break;
|
break;
|
||||||
case 2 : pp = v0*w0 + v2*w1;
|
case 2 : pp = v0*w0 + v2*w1;
|
||||||
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
||||||
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return faceSampleNum;
|
return faceSampleNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -527,12 +525,114 @@ static void FaceSubdivision(MetroMesh & m, VertexSampler &ps,int sampleNum, bool
|
||||||
//qDebug("samplePerAreaUnit %f",samplePerAreaUnit);
|
//qDebug("samplePerAreaUnit %f",samplePerAreaUnit);
|
||||||
std::vector<FacePointer> faceVec;
|
std::vector<FacePointer> faceVec;
|
||||||
FillAndShuffleFacePointerVector(m,faceVec);
|
FillAndShuffleFacePointerVector(m,faceVec);
|
||||||
|
tri::UpdateNormals<MetroMesh>::PerFaceNormalized(m);
|
||||||
|
tri::UpdateFlags<MetroMesh>::FaceProjection(m);
|
||||||
double floatSampleNum = 0.0;
|
double floatSampleNum = 0.0;
|
||||||
int faceSampleNum;
|
int faceSampleNum;
|
||||||
// Subdivision sampling.
|
// Subdivision sampling.
|
||||||
typename std::vector<FacePointer>::iterator fi;
|
typename std::vector<FacePointer>::iterator fi;
|
||||||
for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
|
for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
|
||||||
|
{
|
||||||
|
const CoordType b0(1.0, 0.0, 0.0);
|
||||||
|
const CoordType b1(0.0, 1.0, 0.0);
|
||||||
|
const CoordType b2(0.0, 0.0, 1.0);
|
||||||
|
// compute # samples in the current face.
|
||||||
|
floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
|
||||||
|
faceSampleNum = (int) floatSampleNum;
|
||||||
|
if(faceSampleNum>0)
|
||||||
|
faceSampleNum = SingleFaceSubdivision(faceSampleNum,b0,b1,b2,ps,*fi,randSample);
|
||||||
|
floatSampleNum -= (double) faceSampleNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------
|
||||||
|
// Subdivision sampling of a single face.
|
||||||
|
// return number of added samples
|
||||||
|
|
||||||
|
static int SingleFaceSubdivisionOld(int sampleNum, const CoordType & v0, const CoordType & v1, const CoordType & v2, VertexSampler &ps, FacePointer fp, bool randSample)
|
||||||
|
{
|
||||||
|
// recursive face subdivision.
|
||||||
|
if(sampleNum == 1)
|
||||||
|
{
|
||||||
|
// ground case.
|
||||||
|
CoordType SamplePoint;
|
||||||
|
if(randSample)
|
||||||
|
{
|
||||||
|
CoordType rb=RandomBaricentric();
|
||||||
|
SamplePoint=v0*rb[0]+v1*rb[1]+v2*rb[2];
|
||||||
|
}
|
||||||
|
else SamplePoint=((v0+v1+v2)*(1.0f/3.0f));
|
||||||
|
|
||||||
|
CoordType SampleBary;
|
||||||
|
// int axis;
|
||||||
|
// if(fp->Flags() & FaceType::NORMX ) axis = 0;
|
||||||
|
// else if(fp->Flags() & FaceType::NORMY ) axis = 1;
|
||||||
|
// else {
|
||||||
|
// assert(fp->Flags() & FaceType::NORMZ) ;
|
||||||
|
// axis =2;
|
||||||
|
// }
|
||||||
|
// InterpolationParameters(*fp,axis,SamplePoint,SampleBary);
|
||||||
|
InterpolationParameters(*fp,SamplePoint,SampleBary[0],SampleBary[1],SampleBary[2]);
|
||||||
|
ps.AddFace(*fp,SampleBary);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s0 = sampleNum /2;
|
||||||
|
int s1 = sampleNum-s0;
|
||||||
|
assert(s0>0);
|
||||||
|
assert(s1>0);
|
||||||
|
|
||||||
|
ScalarType w0 = ScalarType(s1)/ScalarType(sampleNum);
|
||||||
|
ScalarType w1 = 1.0-w0;
|
||||||
|
// compute the longest edge.
|
||||||
|
ScalarType maxd01 = SquaredDistance(v0,v1);
|
||||||
|
ScalarType maxd12 = SquaredDistance(v1,v2);
|
||||||
|
ScalarType maxd20 = SquaredDistance(v2,v0);
|
||||||
|
int res;
|
||||||
|
if(maxd01 > maxd12)
|
||||||
|
if(maxd01 > maxd20) res = 0;
|
||||||
|
else res = 2;
|
||||||
|
else
|
||||||
|
if(maxd12 > maxd20) res = 1;
|
||||||
|
else res = 2;
|
||||||
|
|
||||||
|
int faceSampleNum=0;
|
||||||
|
// break the input triangle along the midpoint of the longest edge.
|
||||||
|
CoordType pp;
|
||||||
|
switch(res)
|
||||||
|
{
|
||||||
|
case 0 : pp = v0*w0 + v1*w1;
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,pp,v2,ps,fp,randSample);
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
||||||
|
break;
|
||||||
|
case 1 : pp = v1*w0 + v2*w1;
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s1,v0,pp,v2,ps,fp,randSample);
|
||||||
|
break;
|
||||||
|
case 2 : pp = v0*w0 + v2*w1;
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s0,v0,v1,pp,ps,fp,randSample);
|
||||||
|
faceSampleNum+=SingleFaceSubdivision(s1,pp,v1,v2,ps,fp,randSample);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return faceSampleNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Compute a sampling of the surface where the points are regularly scattered over the face surface using a recursive longest-edge subdivision rule.
|
||||||
|
static void FaceSubdivisionOld(MetroMesh & m, VertexSampler &ps,int sampleNum, bool randSample)
|
||||||
|
{
|
||||||
|
|
||||||
|
ScalarType area = Stat<MetroMesh>::ComputeMeshArea(m);
|
||||||
|
ScalarType samplePerAreaUnit = sampleNum/area;
|
||||||
|
//qDebug("samplePerAreaUnit %f",samplePerAreaUnit);
|
||||||
|
std::vector<FacePointer> faceVec;
|
||||||
|
FillAndShuffleFacePointerVector(m,faceVec);
|
||||||
|
tri::UpdateNormals<MetroMesh>::PerFaceNormalized(m);
|
||||||
|
tri::UpdateFlags<MetroMesh>::FaceProjection(m);
|
||||||
|
double floatSampleNum = 0.0;
|
||||||
|
int faceSampleNum;
|
||||||
|
// Subdivision sampling.
|
||||||
|
typename std::vector<FacePointer>::iterator fi;
|
||||||
|
for(fi=faceVec.begin(); fi!=faceVec.end(); fi++)
|
||||||
{
|
{
|
||||||
// compute # samples in the current face.
|
// compute # samples in the current face.
|
||||||
floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
|
floatSampleNum += 0.5*DoubleArea(**fi) * samplePerAreaUnit;
|
||||||
|
@ -544,6 +644,8 @@ static void FaceSubdivision(MetroMesh & m, VertexSampler &ps,int sampleNum, bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------
|
||||||
|
|
||||||
// Similar Triangles sampling.
|
// Similar Triangles sampling.
|
||||||
// Skip vertex and edges
|
// Skip vertex and edges
|
||||||
// Sample per edges includes vertexes, so here we should expect n_samples_per_edge >=4
|
// Sample per edges includes vertexes, so here we should expect n_samples_per_edge >=4
|
||||||
|
|
Loading…
Reference in New Issue