コード例 #1
0
ファイル: lmesh.C プロジェクト: ArnaudGastinel/jot-lib
inline void
clear_face_flags(CBvert_list& verts)
{
   // Helper method used below in get_parents();
   // clear flags of faces adjacent to the given vertices,
   // including faces that are not stricly adjacent, but
   // that are part of a quad that contains the vertex.

   Bface_list star;
   for (int i=0; i<verts.num(); i++) {
      verts[i]->get_q_faces(star);
      star.clear_flags();
   }
}
コード例 #2
0
bool
SELECT_WIDGET::select_faces(CPIXEL_list& pts)
{
   err_adv(debug, "SELECT_WIDGET::select_faces:");

   if (pts.num() < 2) {
      err_adv(debug, "  too few points: %d", pts.num());
      return false;
   }

   Bface* f = find_face(pts[0], 0.25, MIN_PIX_AREA);
   if (!(f && f->is_selected())) {
      err_adv(debug, "  bad starter face");
      return false;
   }
   
//    // XXX - Old code (to be deleted).  Selects faces individually instead of as
//    // a group:
//    for (int i=0; i<pts.num(); i++)
//       try_select_face(pts[i], 0.1);

   Bface_list flist;

   for(int i = 0; i < pts.num(); ++i){
      
      f = find_face(pts[i], 0.1, MIN_PIX_AREA);
      if (!f || f->is_selected())
         continue;
      flist += f;
      
   }
   
   if(flist.num() > 0){
      
      WORLD::add_command(new MESH_SELECT_CMD(flist));
      err_adv(debug, "  succeeded");
      return true;
      
   }
   
   err_adv(debug, "  no faces selected");
   return false;
   
}
コード例 #3
0
ファイル: oversketch.cpp プロジェクト: QuLogic/jot-lib
bool
OVERSKETCH::apply_offsets(CBvert_list& sil_verts, const vector<double>& sil_offsets)
{
   // XXX - preliminary...

   assert(sil_verts.size() == sil_offsets.size());

   // Expand region around oversketched silhouette verts.
   // XXX - Should compute the one-ring size, not use "3"
   Bface_list region = sil_verts.one_ring_faces().n_ring_faces(3);

   // Find the minimum distance to the silhouette verts from the
   // outer boundary of the region
   Wpt_list sil_path = sil_verts.pts();
   double R = min_dist(region.get_boundary().verts().pts(), sil_path);

   Bvert_list region_verts = region.get_verts();
   Wpt_list   new_locs     = region_verts.pts();
   vector<double> offsets;
   for (Bvert_list::size_type i=0; i<region_verts.size(); i++) {
      Wpt foo;
      int k = -1;
      double d = sil_path.closest(region_verts[i]->loc(), foo, k);
      if (k < 0 || k >= (int)sil_offsets.size()) {
         err_adv(debug, "OVERSKETCH::apply_offsets: error: can't find closest");
         continue;
      }
      double s = swell_profile(d/R);
      double h = sil_offsets[k] * s;
//      err_adv(debug, "  d: %f, d/R: %f, s: %f", d, d/R, s);
      offsets.push_back(h);
      new_locs[i] += region_verts[i]->norm()*h;
//       WORLD::show(region_verts[i]->loc(), new_locs[i], 1);
   }

   // now apply new locs
//   FIT_VERTS_CMDptr cmd = make_shared<FIT_VERTS_CMD>(region_verts, new_locs);
   SUBDIV_OFFSET_CMDptr cmd = make_shared<SUBDIV_OFFSET_CMD>(region_verts, offsets);
   cmd->doit();
   WORLD::add_command(cmd);

   return true;
}
コード例 #4
0
ファイル: lmesh.cpp プロジェクト: QuLogic/jot-lib
inline void
try_append(Bface_list& A, Bface* f)
{
   // Helper method used below in try_append();

   if (f && !f->flag()) {
      f->set_flag();
      A.push_back(f);
   }
}
コード例 #5
0
ファイル: inflate.C プロジェクト: ArnaudGastinel/jot-lib
int
INFLATE::tap_cb(CGESTUREptr& gest, DrawState*& state)
{
   err_adv(debug, "INFLATE::tap_cb");

   // Tracks if the tap was near a guideline
   bool near_guidelines = false;

   PIXEL pdummy;
   int idummy;
   if ( PIXEL_list(_lines).closest( PIXEL(gest->start()), pdummy, idummy ) < 5 )
      near_guidelines = true;

   // Check if gesture hits a BFace
   Bface* face = 0;
   Bsurface::hit_ctrl_surface(gest->start(), 1, &face);

   // Fail if Gesture missed guidelines and geometry
   if ( !face && !near_guidelines )
      return cancel_cb(gest,state);

   // Check that we are trying to inflate
   if ( _orig_face ) {

      // Find the reachable faces from the starting point
      Bface_list set
         = _mode ? _faces : Bface_list::reachable_faces(_orig_face);

      // verify that the user tapped a face that is part of the inflation region
      if ( face && !set.contains( face ) ) {
         return cancel_cb(gest,state);
      }

      // Attempt to inflate the surface
      INFLATE_CMDptr cmd = _mode ? (new INFLATE_CMD( _faces, _preview_dist )) :
         (new INFLATE_CMD( _orig_face, _preview_dist ));
      WORLD::add_command(cmd);
   }

   // On fail, cancel
   return cancel_cb(gest,state);
}
コード例 #6
0
ファイル: tri_strip.cpp プロジェクト: QuLogic/jot-lib
void
TriStrip::get_strips(
   Bface* start,
   vector<TriStrip*>& strips
   ) 
{
   // if starting face was visited already, stop
   if (!is_cleared(start))
      return;

   // stack is used to record faces adjacent to
   // the current strip, in order to build additional
   // strips that align with the current one
   static Bface_list stack(1024);
   stack.clear();
   stack.push_back(start);

   BMESHptr mesh = start->mesh();

   while (!stack.empty()) {
      start = stack.back();
      stack.pop_back();
      if (is_cleared(start)) {
         TriStrip* strip = mesh->new_tri_strip();
         strip->build(start, stack);
         strips.push_back(strip);
      }
   }
}
コード例 #7
0
ファイル: bface.cpp プロジェクト: QuLogic/jot-lib
Bface_list
Bface_list::reachable_faces(Bface* f, CSimplexFilter& pass)
{
   // Returns the list of faces reachable from f, crossing
   // only edges accepted by the filter. It sets needed
   // flags (on the entire mesh) then calls grow_connected().

   Bface_list ret;

   if (!(f && f->mesh()))
      return ret;

   // Ensure all reachable face flags are set to 1:

   // XXX -
   //   touches every face in the mesh; a better
   //   implementation would just touch reachable ones
   //   (or is that impossible to implement?)
   f->mesh()->faces().set_flags(1);

   ret.grow_connected(f, pass);
   return ret;
}
コード例 #8
0
ファイル: lmesh.cpp プロジェクト: QuLogic/jot-lib
Bvert_list
LMESH::get_subdiv_inputs(CBvert_list& verts)
{
   static bool debug = Config::get_var_bool("DEBUG_LMESH_SUBDIV_INPUTS",false);

   // Given a set of vertices from the same LMESH, return
   // the vertices of the parent LMESH that affect the
   // subdivision locations of the given vertices.

   // Require verts share common LMESH
   // XXX - could relax this, provided we test each Bvert
   //       to ensure it is really an Lvert.
   if (!dynamic_pointer_cast<LMESH>(verts.mesh()))
      return Bvert_list();

   // Get direct parent vertices and edges
   Bvert_list vp;       // vertex parents
   Bedge_list ep;       // edge parents
   get_parents(verts, vp, ep);

   err_adv(debug, "%d verts: parents: %d verts, %d edges",
           verts.size(), vp.size(), ep.size());

   // Clear flags of all adjacent faces
   clear_face_flags(vp);
   ep.clear_flag02();

   // Put all adjacent faces into a list
   Bface_list faces = get_q_faces(vp);
   err_adv(debug, "parent faces from verts: %d", faces.size());
   try_append(faces, ep.get_primary_faces());
   err_adv(debug, "parent faces from edges too: %d", faces.size());

   // Pull out the vertices:
   return faces.get_verts();
}
コード例 #9
0
ファイル: inflate.C プロジェクト: ArnaudGastinel/jot-lib
//! Given the starting face "orig_face" and an offset amount "dist",
//! determine the appropriate edit level, re-map orig_face to that
//! level, and "inflate" the portion of the mesh reachable from
//! orig_face by amount dist. The offset may be made relative to the
//! local edge length.
bool
INFLATE::do_inflate(
   Bface*               orig_face,
   double               dist,
   Bsurface*&           output,
   Bface_list*&         reversed_faces,
   MULTI_CMDptr         cmd)
{

   // Reject garbage
   if (fabs(dist) < epsAbsMath()) {
      err_adv(debug, "INFLATE::do_inflate: bad offset distance: %f", dist);
      return 0;
   }

   // Throw out trash
   if (!get_lmesh(orig_face)) {
      err_adv(debug, "INFLATE::do_inflate: error: bad face");
      return 0;
   }
   Lface* face = (Lface*)orig_face;

   err_adv(debug, "INFLATE::do_inflate: face at level %d", subdiv_level(face));

   // Decide which level to do inflation -- should match offset dist

   int rel_level = 0;
   // XXX - it may not be a good idea
   //if (!choose_level(face, dist, rel_level))    // defined above
   //   return 0;

   // Remap face to chosen level
   face = remap(face, rel_level);
   if (!face) {
      err_adv(debug, "INFLATE::do_inflate: can't remap %d from level %d",
              rel_level, subdiv_level(face));
      return 0;
   }
   assert(face && face->mesh());
   err_adv(debug, "chosen edit level: %d", subdiv_level(face));

   // Get set of reachable faces:
   Bface_list set = Bface_list::reachable_faces(face);
   assert(set.mesh() != NULL);
   err_adv(debug, "reachable faces: %d, subdiv level: %d, total faces: %d",
           set.num(), set.mesh()->subdiv_level(), set.mesh()->nfaces());

   if (!set.is_consistently_oriented()) {
      err_msg("INFLATE::do_inflate: rejecting inconsistently \
              oriented surface...");
      return 0;
   }
コード例 #10
0
ファイル: inflate.C プロジェクト: ArnaudGastinel/jot-lib
//! Given boundary curve (near-planar), activate the
//! widget to inflate ...
bool
INFLATE::setup(Bface *bf, double dist, double dur)
{

   reset();

   // Given the starting face f and an offset amount h,
   // determine the appropriate edit level, re-map f to that
   // level, and "inflate" the portion of the mesh reachable
   // from f by h, relative to the local edge length.

   // reject garbage
   if (!(bf && LMESH::isa(bf->mesh()))) {
      err_adv(debug, "INFLATE::setup: error: bad face");
      return 0;
   }
   Lface* f = (Lface*)bf;

   err_adv(debug, "setup: face at level %d", bf->mesh()->subdiv_level());

   // get avg edge length of edges in face:
   double avg_len = avg_strong_edge_len(f);
   if (avg_len < epsAbsMath()) {
      err_adv(debug, "INFLATE::setup: bad average edge length: %f", avg_len);
      return 0;
   }


   // Get set of reachable faces:
   Bface_list set
      = Bface_list::reachable_faces(f);
   assert(set.mesh() != NULL);
   err_adv(debug, "reachable faces: %d, subdiv level: %d, total faces: %d",
           set.num(), set.mesh()->subdiv_level(), set.mesh()->nfaces());

   // given face set should be an entire connected piece.
   if (!is_maximal_connected(set
          )) {
      err_adv(debug, "INFLATE::setup: rejecting subset of surface...");
      return 0;
   }

   Bface_list p = set;//get_top_level(set);
   assert(LMESH::isa(p.mesh()));
   err_adv(debug, "top level: %d faces (out of %d)",
           p.num(), p.mesh()->nfaces());

   BMESH* m = p.mesh();
   if (!m) {
      err_adv(debug, "INFLATE::setup: Error: null mesh");
      return 0;
   }
   if (!LMESH::isa(m)) {
      err_adv(debug, "INFLATE::setup: Error: non-LMESH");
      return 0;
   }
   if (!p.is_consistently_oriented()) {
      err_adv(debug, "INFLATE::setup: Error: inconsistently oriented faces");
      return 0;
   }

   // We ensured the mesh in an LMESH so this is okay:
   _boundary=p.get_boundary();

   if (_boundary.edges().empty()) {
      err_adv(debug, "INFLATE::setup: Error: No boundary. Quitting.");
      _boundary.reset();
      return 0;
   }

   // ******** From here on, we accept it ********

   err_adv(debug, "Inflating... %d boundary loops",
           _boundary.num_line_strips());

   _faces = p;
   _mode = false;
   _d     = _boundary.cur_edges().avg_len();
   _mesh  = (LMESH*)m;
   _orig_face = bf;
   _preview_dist = dist;

   // Set the timeout duration
   set_timeout(dur);

   // Become the active widget and get in the world's DRAWN list:
   activate();

   return true;
}
コード例 #11
0
ファイル: sps.C プロジェクト: ArnaudGastinel/jot-lib
void 
remove_nodes(Bface_list& flist, ARRAY<Wvec>& blist, double min_dist, ARRAY<OctreeNode*>& t)
{
//    if (flist.num() != blist.num()) {
//       return;
//    }
   assert(flist.num() == blist.num());
   Wpt_list pts = get_pts(flist, blist);
   ARRAY< ARRAY<int> > N;
   ARRAY<bool> to_remove;
   for (int i = 0; i < pts.num(); i++) {
      N += ARRAY<int>();
      to_remove += false;
   }

   for (int i = 0; i < pts.num(); i++) {
      for (int j = 0; j < t[i]->neibors().num(); j++) {
         int index = t[i]->neibors()[j]->get_term_index();
         
         if (index < pts.num())
         {
            if (pts[i].dist(pts[index]) < min_dist) {
               N[i] += index;
               N[index] += i;
            }
         }
         else
         {
            //cerr << "Sps Warning, index > pts.num()" << endl;
         }

      }
   }

   priority_queue< Priority, vector<Priority> > queue;
   ARRAY<int> versions;
   for (int i = 0; i < pts.num(); i++) {
      if (!to_remove[i] && !N[i].empty()) {
         Priority p;
         p._priority = center(pts, N[i]).dist(pts[i]);
         p._index = i;
         p._version = 0;
         queue.push(p);
      }
      versions += 0;
   }

   while (!queue.empty()) {
      Priority p = queue.top();
      queue.pop();
      int r = p._index;
      if (p._version == versions[r]) {
         to_remove[r] = true;
         for (int i = 0; i < N[r].num(); i++) {
            N[N[r][i]] -= r;
            versions[N[r][i]]++;
            if (!N[N[r][i]].empty()) {
               Priority q;
               q._priority = center(pts, N[N[r][i]]).dist(pts[N[r][i]]);
               q._index = N[r][i];
               q._version = versions[N[r][i]];
               queue.push(q);
            }
         }
      }
   }
   versions.clear();

   Bface_list ftemp(flist);
   ARRAY<Wvec> btemp(blist);
   flist.clear();
   blist.clear();
   for (int i = 0; i < ftemp.num(); i++)
      if (!to_remove[i]) {
         flist += ftemp[i];
         blist += btemp[i];
      }
}
コード例 #12
0
ファイル: tri_strip.cpp プロジェクト: QuLogic/jot-lib
bool
TriStrip::build(
   Bface* start,        // build a new strip starting here.
   Bface_list& stack    // used to build nearby parallel strips
   )
{
   // a set flag means this face is already in a TriStrip
   assert(!start->flag());

   // start fresh
   reset();

   // repeat 1st vertex if needed
   if (!start->orient_strip())
      start->orient_strip(start->v1());

   // get the starting vert. i.e., the strip will
   // continue onto the next face across the edge
   // opposite this vertex.
   Bvert *a = start->orient_strip(), *b, *c;

   // squash and stretch
   start = backup_strip(start,a);

   if (!start) {
      // should never happen, but can happen
      // if there are inconsistently oriented faces
      err_msg("TriStrip::build: error: backup_strip() failed");
      err_msg("*** check mesh for inconsistently oriented faces ***");

      return 0;
   }

   // claim it
   claim_face(start);

   // record direction of strip on 1st face:
   start->orient_strip(a);

   // faces alternate CCW / CW
   if (_orientation) {
      c = start->next_vert_ccw(a);
      b = start->next_vert_ccw(c);
   } else {
      b = start->next_vert_ccw(a);
      c = start->next_vert_ccw(b);
   }

   add(a,start);
   add(b,start);
   add(c,start);

   Bface* opp;
   if ((opp = start->opposite_face(b)) && is_cleared(opp) &&
      opp->patch() == start->patch()) {
      opp->orient_strip(_orientation ? a : c);
      stack.push_back(opp);
   }

   int i=_orientation;
   Bface* cur = start;
   while ((cur = cur->next_strip_face()) && !is_claimed(cur)) {
      claim_face(cur);
      i++;
      a = b;
      b = c;
      c = cur->other_vertex(a,b);
      cur->orient_strip(a);

      if ((opp = cur->opposite_face(b)) && is_cleared(opp) &&
          opp->patch() == start->patch()) {
         opp->orient_strip(i % 2 ? a : c);
         stack.push_back(opp);
      }

      add(c,cur);
   }

   return 1;
}
コード例 #13
0
void 
ProxySurface::trim_proxy_surface()
{
   assert(_proxy_mesh);

   int n = 0; //number of faces outside the bounding box   
   //get all the quads
   Bface_list faces = _proxy_mesh->faces();
   //clear out all the markings
   for(int i=0; i < faces.num(); ++i)
   {
      if(faces[i])
         ProxyData::set_mark(faces[i],this, false);
      //else
      //   cerr << "FACE is NULL" << endl;
   }
   //mark all the faces that do not overap bounding box
   for(int i=0; i < faces.num(); ++i)
   {
      if(faces[i]){
         bool t1 = (is_inside_bounding_box(faces[i]->e1())) ? true : false;
         bool t2 = (is_inside_bounding_box(faces[i]->e2())) ? true : false;
         bool t3 = (is_inside_bounding_box(faces[i]->e3())) ? true : false;
         
         // If all the edges are outside, then mark the face
         if(!t1 && !t2 && !t3){
            //cerr << "we can delete this face" << endl;
            ProxyData::set_mark(faces[i], this, true);
            n++;
         }
      }else {
         //cerr << "FACE is NULL" << endl;
      }
   }

   if(n < 1)
      return; 

   //for all verts check to see if all the faces that it is attached to has a marked
   Bvert_list verts = _proxy_mesh->verts();
   for(int i=0; i < verts.num(); ++i)
   {
      ARRAY<Bface*> ret;
      verts[i]->get_quad_faces(ret);
      // Make sure that all adjasent faces need to be deleted
      bool do_it=true;
      for(int k=0; k < ret.num(); ++k)
      {
         if(ret[k]){
            assert(ret[k]->is_quad());            
            if(!ProxyData::get_mark(ret[k], this) || !ProxyData::get_mark(ret[k]->quad_partner(), this))
            {
              // cerr << "vert degree " << verts[i]->p_degree() << endl;
               do_it = false;
               break;
            }
         }
      }
      if(do_it){
         UVpt remove_uv;
         UVdata::get_uv(verts[i], remove_uv);
         remove_vert_grid(remove_uv);

         _proxy_mesh->remove_vertex(verts[i]);
         _proxy_mesh->changed();
      }
   }
   //clean up faces
   Bface_list faces2 = _proxy_mesh->faces();
   for(int i=0; i < faces2.num(); ++i)
   {
      if(!(faces2[i]->is_quad()) || !(faces2[i]->quad_partner())){
         _proxy_mesh->remove_face(faces2[i]);
         _proxy_mesh->changed();
      }
      
   }

   //debug_grid();

   
}
コード例 #14
0
ファイル: skin.C プロジェクト: ArnaudGastinel/jot-lib
Skin* 
Skin::create_multi_sleeve(
   Bface_list interior,         // interior skeleton surface
   VertMapper skel_map,         // tells how some skel verts are identified
   MULTI_CMDptr cmd)
{
   err_adv(debug, "Skin::create_multi_sleeve");

   //assert(!has_secondary_any_level(interior));
   assert(cmd != 0);

   if (!skel_map.is_valid()) {
      err_msg("Skin::create_multi_sleeve: invalid skel map");
      return 0;
   }

   Bface_list exterior       = interior.exterior_faces();
   Bface_list all_skel_faces = interior + exterior;

   // need an LMESH that contains all faces
   LMESH* mesh = LMESH::upcast(all_skel_faces.mesh());
   if (!mesh) {
      err_adv(debug, "  bad skel mesh");
      return 0;
   }

   // Get relative refinement level
   int R = max_subdiv_edit_level(all_skel_faces, interior);

   err_adv(debug, "  skel region res level: %d", R);

   LMESH* ctrl = mesh->control_mesh();
   int old_lev = ctrl->cur_level();
   int ref_lev = mesh->subdiv_level() + R;
   ctrl->update_subdivision(ref_lev);
   if (ref_lev < old_lev)
      ctrl->update_subdivision(old_lev);

   Skin* cur = new Skin(mesh, exterior, skel_map, R, false, "sleeve", cmd);
   cur->set_all_sticky();
   cur->freeze(cur->skin_faces().get_boundary().edges().get_verts());
   for (int k=1; k<=R; k++) {
      
      err_adv(debug, "  top of loop: k = %d", k);

      // XXX - temporary
      if (!check(interior.mesh()->faces()))
         return cur;

      // Update the skeleton to the next level
      LMESH::update_subdivision(interior + exterior, 1);

      // Map skel faces to next level. Avoid new holes.
      // Take account of new regions that don't exist at
      // previous level.

      err_adv(debug, "  getting interior subdiv faces");
      int n = interior.num();
      interior = get_subdiv_faces(interior, 1); // no holes can form here
      if (4*n != interior.num()) {
         err_adv(debug, "  *** ERROR *** got %d interior subdiv faces from %d",
                 interior.num(), n);
      }

      err_adv(debug, "  getting skel subdiv faces");
      n = cur->skel_faces().num();
      exterior = get_subdiv_faces(cur->skel_faces(), 1);
      if (4*n != exterior.num()) {
         err_adv(debug, "  *** ERROR *** got %d exterior subdiv faces from %d",
                 exterior.num(), n);
      }

      // check for holes:
      if (exterior.has_any_secondary()) {
         err_adv(debug, "  removing secondary skel faces at level %d", k);
         exterior = exterior.primary_faces(); // remove holes
      }

      // check for new regions:
      err_adv(debug, "  checking for new faces");
      Bface_list new_faces = interior.two_ring_faces().minus(interior + exterior);
      assert(new_faces.is_all_primary()); // must be true (we think)
      if (!new_faces.empty()) {
         err_adv(debug, "  adding %d new faces at level %d",
                 new_faces.num(), k);
         exterior.append(new_faces);
      }

      // get version of skel_map at new level:
      cur = new Skin(cur, exterior, cmd);

      // make the ones on or near the boundary "sticky"
      cur->set_all_sticky(false);
      cur->set_sticky(
         cur->skin_faces().
         get_boundary().
         edges().
         get_verts().
         one_ring_faces().
         get_verts()
         );
      cur->freeze(cur->skin_faces().get_boundary().edges().get_verts());

      // put memes in place, not just use position they inherited
      // from subdivision
      cur->do_update();
   }

   // Join skin to skel at level R
   err_adv(debug, "  joining to skel...");
   if (cur->join_to_skel(interior, cmd)) {
      err_adv(debug, "  ...succeeded");
   } else {
      err_adv(debug, "  ...failed");
   }

   _debug_instance = cur;
   return upcast(cur->control());
}
コード例 #15
0
ファイル: skin.C プロジェクト: ArnaudGastinel/jot-lib
static int
max_subdiv_edit_level(Bface_list all, Bface_list core=Bface_list())
{
   // what is the deepest subdiv level that is either:
   //   - controlled by a Bbase
   //   - has holes cut
   //   - has new surface regions attached

   err_adv(debug, "max_subdiv_edit_level:");
   if (all.empty()) {
      assert(core.empty());
      err_adv(debug, "  face list is empty");
      return 0;
   }
   assert(all.mesh() && all.contains_all(core));

   int R = 0;   // level at which deepest edits happened
   int k = 0;   // current level being examined
   while (!all.empty()) {
      k++;
      all = get_subdiv_faces(all,1);
      if (all.empty())
         break;

      // check for controllers
      if (!Bbase::find_owners(all).empty()) {
         err_adv(debug, "  controllers at level %d", k);
         R = k;
      }

      // check for holes at this level:
      if (all.has_any_secondary()) {
         all = all.primary_faces();
         err_adv(debug, "  hole at level %d", k);
         R = k; // holes exist at this level
      }

      // check for new regions
      if (core.empty())
         continue;
      core = get_subdiv_faces(core,1);
      Bface_list new_faces = core.two_ring_faces().primary_faces();
      // see if any of these new ones are actually new:
      new_faces.set_flags(1);
      all.clear_flags();
      new_faces = new_faces.filter(SimplexFlagFilter(1));
      if (!new_faces.empty()) {
         all.append(new_faces);
         err_adv(debug, "  new faces at level %d", k);
         R = k;  // new stuff exists at this level
      }
   }
   return R;
}
コード例 #16
0
ファイル: uv_data.C プロジェクト: ArnaudGastinel/jot-lib
bool
UVdata::handle_subdiv_calc()
{
   // Some of you may have been wondering why anyone would
   // need UVdata on an edge. The whole reason is to pick up
   // this here callback, which is generated when it is time
   // to recompute subdivision values for an edge or vertex.
   // (I.e., this is also why you need UVdata on a vertex).
   //
   // XXX - Currently we aren't keeping track of when
   //       subdivision uv-coords need to be recomputed. We
   //       just get this callback whenever subdivision
   //       *locations* need to be recomputed. So the wrong
   //       thing happens if you change the uv-coords of the
   //       control mesh but not the vertex locations or
   //       connectivity. And if you change the vertex
   //       locations but not the uv-coords the latter get
   //       recomputed even though they don't need to be.

   // XXX - even worser: working on a deadline, we're changing
   //  mesh connectivity at arbitrary subdivision levels
   //  (not previously done), and that's leading to an assertion
   //  failure in subdiv_uv(Bedge*, Bface*) below...
   //  needs to get fixed (later)
   //   lem - 1/6/2002
//   return 0;

   // Don't compute it more than once.  Current policy is uv
   // coords are assigned but not later edited or changed ever.
   // Why? Because with mesh connectivity edits happening at
   // arbitrary levels of subdivision, we don't want parent
   // elements forcing inappropriate uv values on elements at
   // current level. -- lem 12/29/2004; same deadline :(
   if (_did_subdiv) {
//      return false;
   }
   _did_subdiv = true;

   if (is_edge(simplex())) {
      Ledge* e = (Ledge*) simplex();

      if ( !e->get_face() )
         return false;

      if (is_continuous(e)) {
         // Set a single uv-coord on the subdivision vertex
         // to be used regardless of the face containing it.
         _set(e->subdiv_vertex(), subdiv_uv(e, e->get_face()));
      } else {
         // Compute 2 separate subdiv uv-coords, set each one
         // on the 3 sub-faces on each side of the edge.
         // (If a face is missing or has no uv-coords it's a no-op).
         set_subdiv_uv(e, (Lface*)e->f1());
         set_subdiv_uv(e, (Lface*)e->f2());
      }
   } else if (is_vert(simplex())) {
      Lvert* v = (Lvert*) simplex();

      if ( !v->get_face() )
         return false;

      if (is_continuous(v)) {
         // Set a single uv-coord on the subdivision vertex
         // to be used regardless of the face containing it.
         _set(v->subdiv_vertex(), subdiv_uv(v, v->get_face()));
      } else {
         // Compute and set a separate uv-coord for each face
         // surrounding the subdiv vert:
         Bface_list faces;
         v->get_faces(faces);
         for (int i=0; i<faces.num(); i++)
            set_subdiv_uv(v, (Lface*)faces[i]);
      }
   } else {
      // We get here if this UVdata is on a Bface or a null simplex.
      // Neither should ever happen.
      assert(0);
   }

   // Returning 0 means we are not overriding the normal
   // subdivision calculation.
   return 0;
}