[FGT - filter_fractal]

- first working version of craters generation filter! Don't use too many samples for now!
This commit is contained in:
Paolo Cignoni cignoni 2010-01-20 11:44:17 +00:00
parent 9befab264c
commit 7bbe3ea6f1
3 changed files with 101 additions and 29 deletions

View File

@ -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> &centre,
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;
}
};

View File

@ -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:

View File

@ -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;
}