From 7bbe3ea6f13eb33ab032485fd2e050bd596a7539 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Wed, 20 Jan 2010 11:44:17 +0000 Subject: [PATCH] [FGT - filter_fractal] - first working version of craters generation filter! Don't use too many samples for now! --- src/fgt/filter_fractal/craters_utils.h | 53 ++++++++++++++++++-- src/fgt/filter_fractal/filter_args.h | 17 ++++--- src/fgt/filter_fractal/filter_fractal.cpp | 60 +++++++++++++++-------- 3 files changed, 101 insertions(+), 29 deletions(-) diff --git a/src/fgt/filter_fractal/craters_utils.h b/src/fgt/filter_fractal/craters_utils.h index 1398af3dc..62b324859 100644 --- a/src/fgt/filter_fractal/craters_utils.h +++ b/src/fgt/filter_fractal/craters_utils.h @@ -6,6 +6,7 @@ #include #include #include +#include template 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* craterFaces // vector of crater faces (output) + CoordScalarType radius, // crater radius + std::vector* toFill = 0 ) { assert(vcg::tri::HasFFAdjacency(*m)); @@ -60,6 +61,10 @@ public: std::vector fl; fl.push_back(startingFace); + if(toFill) + { + toFill->clear(); + } FacePointer f; Point3 dummyPoint; std::pair dummyPair; @@ -75,7 +80,11 @@ public: if(vcg::IntersectionSphereTriangle (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 + static void applyRadialPerturbation(MeshType *m, std::vector &craterFaces, + VertexPointer centre, ScalarType radius, ScalarType depth) + { + vcg::tri::UpdateFlags::VertexClearV(*m); + typename std::vector::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::applyRadialPerturbation + (vp->P(), centre->P(), radius, depth); + vp->P() += (centre->N() * perturbation); + } + } + } + } + + template + static ScalarType applyRadialPerturbation(Point3 &p, Point3 ¢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; + } + + }; diff --git a/src/fgt/filter_fractal/filter_args.h b/src/fgt/filter_fractal/filter_args.h index 946edf1d7..77aec75b0 100644 --- a/src/fgt/filter_fractal/filter_args.h +++ b/src/fgt/filter_fractal/filter_args.h @@ -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::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: diff --git a/src/fgt/filter_fractal/filter_fractal.cpp b/src/fgt/filter_fractal/filter_fractal.cpp index e2fb8a18f..21dc0d5bb 100644 --- a/src/fgt/filter_fractal/filter_fractal.cpp +++ b/src/fgt/filter_fractal/filter_fractal.cpp @@ -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 rh = tri::Allocator::AddPerVertexAttribute(*(args.samples_mesh), std::string("Radius")); CMeshO::PerVertexAttributeHandle dh = tri::Allocator::AddPerVertexAttribute(*(args.samples_mesh), std::string("Depth")); - CMeshO::PerVertexAttributeHandle* > lh = tri::Allocator::AddPerVertexAttribute* >(*(args.samples_mesh), std::string("CraterFaces")); - - VertexIterator vi; - FacePointer fp = 0; + CMeshO::PerVertexAttributeHandle fh = tri::Allocator::AddPerVertexAttribute(*(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::iterator cfi; + vcg::tri::UpdateSelection::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(); // creates the face list - - fp = CratersUtils::getClosestFace(args.target_mesh, &*vi); - CratersUtils::SelectCraterFaces(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::getClosestFace(args.target_mesh, &*vi); + CratersUtils::SelectCraterFaces(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 > + (*(args.target_mesh), MidPoint(args.target_mesh), edgeThreshold, true, cb) + && iter++ < maxIterations); + + // radial function application + std::vector craterFaces; + for(vi = args.samples_mesh->vert.begin(); vi != args.samples_mesh->vert.end(); ++vi) + { + fh[vi] = CratersUtils::getClosestFace(args.target_mesh, &*vi); + CratersUtils::SelectCraterFaces(args.target_mesh, fh[vi], &*vi, rh[vi], &craterFaces); + CratersUtils::applyRadialPerturbation + (args.target_mesh, craterFaces, &(*vi), rh[vi], dh[vi]); + } + + tri::Allocator::DeletePerVertexAttribute(*(args.samples_mesh), fh); tri::Allocator::DeletePerVertexAttribute(*(args.samples_mesh), rh); tri::Allocator::DeletePerVertexAttribute(*(args.samples_mesh), dh); - // attenzione: qui bisogna eliminare esplicitamente i vettori: non basta eliminare l'attributo - tri::Allocator::DeletePerVertexAttribute* >(*(args.samples_mesh), lh); + // updating bounding box and normals + vcg::tri::UpdateBounding::Box(*(args.target_mesh)); + vcg::tri::UpdateNormals::PerVertexNormalizedPerFaceNormalized(*(args.target_mesh)); return true; }