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; }
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()); }