mirror of
https://github.com/lucaspalomodevelop/meshlab.git
synced 2026-03-16 09:34:36 +00:00
[FGT - filter_fractal]
- first working version of craters generation filter! Don't use too many samples for now!
This commit is contained in:
parent
9befab264c
commit
7bbe3ea6f1
@ -6,6 +6,7 @@
|
||||
#include <vcg/complex/intersection.h>
|
||||
#include <vcg/complex/trimesh/clean.h>
|
||||
#include <vcg/space/sphere3.h>
|
||||
#include <vcg/math/base.h>
|
||||
|
||||
template<class MeshType>
|
||||
class CratersUtils
|
||||
@ -48,8 +49,8 @@ public:
|
||||
static void SelectCraterFaces(MeshType *m, // target mesh
|
||||
FacePointer startingFace, // face under the crater centre
|
||||
VertexPointer centre, // crater centre
|
||||
CoordScalarType radius, // crater radius
|
||||
std::vector<FacePointer>* craterFaces // vector of crater faces (output)
|
||||
CoordScalarType radius, // crater radius
|
||||
std::vector<FacePointer>* toFill = 0
|
||||
)
|
||||
{
|
||||
assert(vcg::tri::HasFFAdjacency(*m));
|
||||
@ -60,6 +61,10 @@ public:
|
||||
std::vector<FacePointer> fl;
|
||||
fl.push_back(startingFace);
|
||||
|
||||
if(toFill)
|
||||
{
|
||||
toFill->clear();
|
||||
}
|
||||
FacePointer f;
|
||||
Point3<CoordScalarType> dummyPoint;
|
||||
std::pair<CoordScalarType, CoordScalarType> dummyPair;
|
||||
@ -75,7 +80,11 @@ public:
|
||||
if(vcg::IntersectionSphereTriangle<CoordScalarType, FaceType>
|
||||
(craterSphere, *f, dummyPoint, &dummyPair))
|
||||
{ // intersection test succedeed
|
||||
craterFaces->push_back(f);
|
||||
if(toFill)
|
||||
{
|
||||
toFill->push_back(f);
|
||||
}
|
||||
f->SetS();
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
if(!f->FFp(i)->IsV())
|
||||
@ -87,6 +96,44 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ScalarType>
|
||||
static void applyRadialPerturbation(MeshType *m, std::vector<FacePointer> &craterFaces,
|
||||
VertexPointer centre, ScalarType radius, ScalarType depth)
|
||||
{
|
||||
vcg::tri::UpdateFlags<MeshType>::VertexClearV(*m);
|
||||
typename std::vector<FacePointer>::iterator fi;
|
||||
VertexPointer vp;
|
||||
ScalarType perturbation = .0;
|
||||
|
||||
for(fi = craterFaces.begin(); fi!=craterFaces.end(); ++fi)
|
||||
{
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
vp = (*fi)->V(i);
|
||||
if(!vp->IsV())
|
||||
{
|
||||
vp->SetV();
|
||||
perturbation = CratersUtils<MeshType>::applyRadialPerturbation<ScalarType>
|
||||
(vp->P(), centre->P(), radius, depth);
|
||||
vp->P() += (centre->N() * perturbation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class ScalarType>
|
||||
static ScalarType applyRadialPerturbation(Point3<ScalarType> &p, Point3<ScalarType> ¢re,
|
||||
ScalarType radius, ScalarType depth)
|
||||
{
|
||||
ScalarType result = .0;
|
||||
ScalarType dist = vcg::Distance(p, centre);
|
||||
double exponent = - pow((2 * dist / radius), 2);
|
||||
result = - depth * exp(exponent);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -19,7 +19,6 @@ public:
|
||||
float spectralWeight[21];
|
||||
float zoom_window_side, zoom_org_x, zoom_org_y;
|
||||
|
||||
|
||||
FractalArgs(){}
|
||||
|
||||
void setFields(int algorithmId, float seed, float octaves, float lacunarity, float fractalIncrement,
|
||||
@ -60,8 +59,10 @@ public:
|
||||
CMeshO* target_mesh;
|
||||
CMeshO* samples_mesh;
|
||||
float max_radius, max_depth, min_radius, min_depth, radius_range, depth_range;
|
||||
float resolution;
|
||||
|
||||
CratersArgs(MeshModel* target, MeshModel* samples, float max_r, float max_d)
|
||||
CratersArgs(MeshModel* target, MeshModel* samples, float min_r, float max_r,
|
||||
float min_d, float max_d, float res)
|
||||
{
|
||||
generator = new vcg::math::SubtractiveRingRNG();
|
||||
|
||||
@ -74,26 +75,30 @@ public:
|
||||
vcg::tri::Allocator<CMeshO>::CompactFaceVector(*target_mesh);
|
||||
|
||||
float target_bb_diag = target_mesh->bbox.Diag();
|
||||
max_radius = target_bb_diag * 0.5 * max_r;
|
||||
min_radius = target_bb_diag * 0.5 * 0.02;
|
||||
max_radius = target_bb_diag * 0.2 * max_r;
|
||||
min_radius = target_bb_diag * 0.2 * min_r;
|
||||
radius_range = max_radius - min_radius;
|
||||
max_depth = target_bb_diag * 0.2 * max_d;
|
||||
min_depth = target_bb_diag * 0.2 * 0.02;
|
||||
min_depth = target_bb_diag * 0.2 * min_d;
|
||||
depth_range = max_depth - min_depth;
|
||||
|
||||
this->resolution = res;
|
||||
}
|
||||
|
||||
~CratersArgs(){ delete generator; }
|
||||
|
||||
/* generates a crater radius within the specified range */
|
||||
float generateRadius()
|
||||
{
|
||||
float rnd = generator->generate01closed();
|
||||
return min_radius + radius_range * rnd;
|
||||
}
|
||||
|
||||
/* generates a crater depth within the specified range */
|
||||
float generateDepth()
|
||||
{
|
||||
float rnd = generator->generate01closed();
|
||||
return min_depth + radius_range * rnd;
|
||||
return min_depth + depth_range * rnd;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -171,8 +171,11 @@ void FilterFractal::initParameterSetForCratersGeneration(MeshDocument &md, RichP
|
||||
|
||||
par.addParam(new RichMesh("target_mesh", target, &md, "Target mesh:", "The mesh on which craters will be generated."));
|
||||
par.addParam(new RichMesh("samples_mesh", samples, &md, "Samples layer:", "The samples that represent the central points of craters."));
|
||||
par.addParam(new RichDynamicFloat("max_radius", 0.2, 0, 1, "Craters radius:", "Defines the maximum radius of craters in range [0, 1]. Values near 1 mean very large craters."));
|
||||
par.addParam(new RichDynamicFloat("max_depth", 0.2, 0, 1, "Craters depth:", "Defines the maximum depth of craters in range [0, 1]. Values near 1 mean very deep craters."));
|
||||
par.addParam(new RichDynamicFloat("min_radius", 0.3, 0, 1, "Min crater radius:", "Defines the minimum radius of craters in range [0, 1]. Values near 0 mean very small craters."));
|
||||
par.addParam(new RichDynamicFloat("max_radius", 0.6, 0, 1, "Max crater radius:", "Defines the maximum radius of craters in range [0, 1]. Values near 1 mean very large craters."));
|
||||
par.addParam(new RichDynamicFloat("min_depth", 0.3, 0, 1, "Min crater depth:", "Defines the minimum depth of craters in range [0, 1]."));
|
||||
par.addParam(new RichDynamicFloat("max_depth", 0.6, 0, 1, "Max crater depth:", "Defines the maximum depth of craters in range [0, 1]. Values near 1 mean very deep craters."));
|
||||
par.addParam(new RichDynamicFloat("resolution", 0.5, 0, 1, "Craters resolution:", "This parameter defines the quality of generated craters. 1 means maximum quality."));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -228,7 +231,9 @@ bool FilterFractal::applyCratersGenerationFilter(MeshDocument &md, RichParameter
|
||||
|
||||
// reads parameters
|
||||
CratersArgs args(par.getMesh("target_mesh"), par.getMesh("samples_mesh"),
|
||||
par.getDynamicFloat("max_radius"), par.getDynamicFloat("max_depth"));
|
||||
par.getDynamicFloat("min_radius"), par.getDynamicFloat("max_radius"),
|
||||
par.getDynamicFloat("min_depth"), par.getDynamicFloat("max_depth"),
|
||||
par.getDynamicFloat("resolution"));
|
||||
return generateCraters(md, args, cb);
|
||||
}
|
||||
|
||||
@ -291,37 +296,52 @@ bool FilterFractal::generateCraters(MeshDocument &md, CratersArgs &args, vcg::Ca
|
||||
*/
|
||||
CMeshO::PerVertexAttributeHandle<float> rh = tri::Allocator<CMeshO>::AddPerVertexAttribute<float>(*(args.samples_mesh), std::string("Radius"));
|
||||
CMeshO::PerVertexAttributeHandle<float> dh = tri::Allocator<CMeshO>::AddPerVertexAttribute<float>(*(args.samples_mesh), std::string("Depth"));
|
||||
CMeshO::PerVertexAttributeHandle<std::vector<FacePointer>* > lh = tri::Allocator<CMeshO>::AddPerVertexAttribute<std::vector<FacePointer>* >(*(args.samples_mesh), std::string("CraterFaces"));
|
||||
|
||||
VertexIterator vi;
|
||||
FacePointer fp = 0;
|
||||
CMeshO::PerVertexAttributeHandle<FacePointer> fh = tri::Allocator<CMeshO>::AddPerVertexAttribute<FacePointer>(*(args.samples_mesh), std::string("CentralFace"));
|
||||
|
||||
if(!vcg::tri::HasFFAdjacency(*(args.target_mesh)))
|
||||
{
|
||||
args.target_model->updateDataMask(MeshModel::MM_FACEFACETOPO);
|
||||
}
|
||||
args.target_model->updateDataMask(MeshModel::MM_FACECOLOR);
|
||||
std::vector<FacePointer>::iterator cfi;
|
||||
vcg::tri::UpdateSelection<CMeshO>::ClearFace(*(args.target_mesh));
|
||||
|
||||
VertexIterator vi;
|
||||
float maxRadius = .0;
|
||||
|
||||
// first loop: identification and selection of crater faces
|
||||
for(vi = args.samples_mesh->vert.begin(); vi != args.samples_mesh->vert.end(); ++vi)
|
||||
{
|
||||
rh[vi] = args.generateRadius(); // sets the crater radius
|
||||
if(rh[vi] > maxRadius) maxRadius = rh[vi]; // updates, if necessary, the maxRadius
|
||||
dh[vi] = args.generateDepth(); // sets the crater depth
|
||||
lh[vi] = new std::vector<FacePointer>(); // creates the face list
|
||||
|
||||
fp = CratersUtils<CMeshO>::getClosestFace<float>(args.target_mesh, &*vi);
|
||||
CratersUtils<CMeshO>::SelectCraterFaces<float>(args.target_mesh, fp, &*vi, rh[vi], lh[vi]);
|
||||
|
||||
for(cfi = lh[vi]->begin(); cfi!=lh[vi]->end(); ++cfi)
|
||||
{
|
||||
(*cfi)->C() = Color4b::Red;
|
||||
}
|
||||
fh[vi] = CratersUtils<CMeshO>::getClosestFace<float>(args.target_mesh, &*vi);
|
||||
CratersUtils<CMeshO>::SelectCraterFaces<float>(args.target_mesh, fh[vi], &*vi, rh[vi]);
|
||||
}
|
||||
|
||||
// refinement of crater faces
|
||||
float edgeThreshold = maxRadius * 2 / (50 * args.resolution);
|
||||
int maxIterations = 7;
|
||||
int iter = 0;
|
||||
while(Refine<CMeshO, MidPoint<CMeshO> >
|
||||
(*(args.target_mesh), MidPoint<CMeshO>(args.target_mesh), edgeThreshold, true, cb)
|
||||
&& iter++ < maxIterations);
|
||||
|
||||
// radial function application
|
||||
std::vector<FacePointer> craterFaces;
|
||||
for(vi = args.samples_mesh->vert.begin(); vi != args.samples_mesh->vert.end(); ++vi)
|
||||
{
|
||||
fh[vi] = CratersUtils<CMeshO>::getClosestFace<float>(args.target_mesh, &*vi);
|
||||
CratersUtils<CMeshO>::SelectCraterFaces<float>(args.target_mesh, fh[vi], &*vi, rh[vi], &craterFaces);
|
||||
CratersUtils<CMeshO>::applyRadialPerturbation<float>
|
||||
(args.target_mesh, craterFaces, &(*vi), rh[vi], dh[vi]);
|
||||
}
|
||||
|
||||
tri::Allocator<CMeshO>::DeletePerVertexAttribute<FacePointer>(*(args.samples_mesh), fh);
|
||||
tri::Allocator<CMeshO>::DeletePerVertexAttribute<float>(*(args.samples_mesh), rh);
|
||||
tri::Allocator<CMeshO>::DeletePerVertexAttribute<float>(*(args.samples_mesh), dh);
|
||||
|
||||
// attenzione: qui bisogna eliminare esplicitamente i vettori: non basta eliminare l'attributo
|
||||
tri::Allocator<CMeshO>::DeletePerVertexAttribute<std::vector<FacePointer>* >(*(args.samples_mesh), lh);
|
||||
// updating bounding box and normals
|
||||
vcg::tri::UpdateBounding<CMeshO>::Box(*(args.target_mesh));
|
||||
vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFaceNormalized(*(args.target_mesh));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user