static unsigned char * rasterize( VoxelsIOPlugin * plugin, MeshModel & m ) { size_t voxels_num = voxmap_size.X() * voxmap_size.Y() * voxmap_size.Z(); unsigned char * voxels = new unsigned char[ voxels_num * voxel_size ]; if( !voxels ) return NULL; memset( voxels, 0, voxels_num * voxel_size ); vcg::Point3f diff( vcg::Point3f( voxmap_size.X() / 2.f, voxmap_size.Y() / 2.f, voxmap_size.Z() / 2.f ) - m.cm.bbox.Center() ), min( floorf( m.cm.bbox.min.X() ), floorf( m.cm.bbox.min.Y() ), floorf( m.cm.bbox.min.Z() ) ), max( ceilf( m.cm.bbox.max.X() ), ceilf( m.cm.bbox.max.Y() ), ceilf( m.cm.bbox.max.Z() ) ); MeshEP mesh; make_mesh( m, &mesh ); TriMeshGrid grid; grid.Set( mesh.face.begin(), mesh.face.end() ); int slice_size = voxmap_size.Y() * voxmap_size.X(); TriMeshGrid::CoordType xyz; for( xyz.Z() = min.Z() + .5f; xyz.Z() < max.Z(); xyz.Z() += 1.f ) { for( xyz.Y() = min.Y() + .5f; xyz.Y() < max.Y(); xyz.Y() += 1.f ) for( xyz.X() = min.X() + .5f; xyz.X() < max.X(); xyz.X() += 1.f ) if( vcg::tri::Inside< TriMeshGrid, MeshEP >::Is_Inside( mesh, grid, xyz ) ) { qint64 i = static_cast<int>(xyz.Z() + diff.Z()) * slice_size + static_cast<int>(xyz.Y() + diff.Y()) * voxmap_size.X() + static_cast<int>(xyz.X() + diff.X()); memset( voxels + i * voxel_size, UCHAR_MAX, voxel_size ); } std::cout << xyz.Z() << "/" << max.Z() << std::endl; plugin->Log( "%f/%f", xyz.Z(), max.Z() ); } return voxels; }
// The Real Core Function doing the actual mesh processing. // Move Vertex of a random quantity bool ExtraSamplePlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb) { switch(ID(action)) { case FP_DECOMPOSER : { CMeshO &m = md.mm()->cm; CutMesh cm; vcg::tri::Append<CutMesh,CMeshO>::MeshCopy(cm,m); vcg::tri::Allocator<CutMesh>::CompactEveryVector(cm); vcg::tri::UpdateTopology<CutMesh>::FaceFace(cm); vcg::tri::UpdateTopology<CutMesh>::VertexFace(cm); vcg::tri::UpdateNormal<CutMesh>::PerFace(cm); //Get Parameters vcg::Point3f upperPoint = par.getPoint3f("upperPoint"); vcg::Point3f lowerPoint = par.getPoint3f("lowerPoint"); float dihedral = par.getDynamicFloat("dihedral"); float ambient = par.getDynamicFloat("ambient"); float geodesic = par.getDynamicFloat("geodesic"); float geomin = par.getDynamicFloat("geo-factor-min"); float geomax = par.getDynamicFloat("geo-factor-max"); float elength = par.getDynamicFloat("e-length"); CutMesh::FacePointer startFace = NULL; CutMesh::FacePointer endFace = NULL; //getting the closest faces to the passed point parameters TriMeshGrid grid; grid.Set(cm.face.begin(),cm.face.end()); vcg::Point3<CutMesh::ScalarType> closest; float maxDist = cm.bbox.Diag(); float minDist; startFace = vcg::tri::GetClosestFaceBase(cm, grid, upperPoint, maxDist, minDist, closest); endFace = vcg::tri::GetClosestFaceBase(cm, grid, lowerPoint, maxDist, minDist, closest); assert(startFace!=NULL && endFace!=NULL); std::vector<CutVertex::VertexPointer> seedVec; for(int i=0; i<3; i++) seedVec.push_back(startFace->V(i)); //getting the geodesic distance from the start/end face and some other data //that will be used in the weight computation typename CutMesh::template PerFaceAttributeHandle <float> gfH1 = vcg::tri::Allocator<CutMesh>::template AddPerFaceAttribute<float>(cm, std::string("GeoDis1")); vcg::tri::Geodesic<CutMesh>::Compute(cm, seedVec); float max1=0.0f; float maxq=0.0f; //getting also the maximum perFaceQuality value for(CutMesh::FaceIterator fit= cm.face.begin(); fit!=cm.face.end(); fit++){ if(fit->Q()>=maxq) maxq=fit->Q(); gfH1[fit] = (fit->V(0)->Q()+fit->V(1)->Q()+fit->V(2)->Q())/3.0f; if(gfH1[fit]>=max1) max1=gfH1[fit]; } //this functor will be used to compute edge weights on the dual graph WeightFunctor<CutMesh> wf(ambient, dihedral, geodesic, elength, startFace, endFace, gfH1, max1, geomin, geomax, maxq); //start actual computation vcg::tri::GraphBuilder<CutMesh, WeightFunctor<CutMesh> >::Compute(cm, wf, startFace, endFace); vcg::tri::Allocator<CutMesh>::DeletePerFaceAttribute(cm,gfH1); vcg::tri::Append<CMeshO,CutMesh>::MeshCopy(m,cm); return true; } } return false; }