bool OVERSKETCH::match_substrip(CPIXEL_list& pts, CBvert_list& chain, EdgeStrip& strip) { err_adv(debug, "OVERSKETCH::match_substrip:"); if (!chain.forms_chain()) { err_adv(debug, " non-chain"); return false; } const double MAX_DIST = 8; PIXEL_list chain_path(chain.wpts()); int k0 = get_near_index(chain_path, pts.front(), MAX_DIST); int k1 = get_near_index(chain_path, pts.back(), MAX_DIST); if (!(0 <= k0 && k0 < (int)chain.size() && 0 <= k1 && k1 < (int)chain.size())) { err_adv(debug, " bad k0/k1: %d/%d", k0, k1); return false; } if (k0 == k1) { err_adv(debug, " bad k0/k1: %d == %d", k0, k1); return false; } make_strip(chain, k0, k1, strip); return true; }
inline ARRAY<double> get_offset_scales(CBvert_list& skels, CSimplexFilter& filter) { ARRAY<double> ret(skels.num()); for (int i=0; i<skels.num(); i++) ret += offset_scale(skels[i], filter); return ret; }
inline void show_yardstick(CBvert_list& verts, double yardstick) { vector<Wline> lines(verts.size()); for (Bvert_list::size_type i=0; i<verts.size(); i++) lines[i] = Wline(verts[i]->loc(), verts[i]->norm()*yardstick); GL_VIEW::draw_lines(lines, Color::yellow, 0.8, 1, false); }
inline PIXEL_list get_pixels(CBvert_list& verts, ProxySurface* p) { PIXEL_list ret(verts.num()); for (int i=0; i<verts.num(); i++) { ret += PixelsData::get_pix(verts[i], p); } return ret; }
inline Bvert_list copy_verts(CBvert_list& verts, LMESHptr mesh) { Bvert_list ret(verts.size()); for (Bvert_list::size_type i=0; i<verts.size(); i++) { ret.push_back(mesh->add_vertex(verts[i]->loc())); } return ret; }
inline Wpt_list centroids(CBvert_list& verts) { Wpt_list ret(verts.num()); for (int i=0; i<verts.num(); i++) { ret += verts[i]->qr_centroid(); } return ret; }
Bvert_list Skin::sticky_verts(CBvert_list& verts) const { Bvert_list ret(verts.num()); for (int i=0; i<verts.num(); i++) { SkinMeme* m = SkinMeme::upcast(find_meme(verts[i])); if (m && m->is_sticky()) { ret += m->vert(); } } return ret; }
inline void show_verts(CBvert_list& verts, int size, CCOLOR& c0, CCOLOR& c1) { if (verts.empty()) return; if (verts.size() == 1) show_vert(verts[0], size, c0); // ramp the colors double di = 1.0/(verts.size()-1); for (Bvert_list::size_type i=0; i<verts.size(); i++) show_vert(verts[i], size, interp(c0, c1, i*di)); }
VertMemeList Bbase::find_boss_vmemes(CBvert_list& verts) { // Convenience: lookup boss memes for a whole list of vertices VertMemeList ret(verts.num()); for (int i=0; i<verts.num(); i++) { VertMeme* vm = find_boss_vmeme(verts[i]); if (vm) ret += vm; } return ret; }
Wpt_list Skin::track_points(CBvert_list& verts) const { Wpt_list ret(verts.num()); for (int i=0; i<verts.num(); i++) { SkinMeme* m = SkinMeme::upcast(find_meme(verts[i])); if (m && m->is_tracking()) { ret += m->track_pt(); } else { ret += verts[i]->loc(); } } return ret; }
inline void get_parents(CBvert_list& verts, Bvert_list& vp, Bedge_list& ep) { // Helper method used below in get_parents(); // from the given list of vertices, return the parent // simplices in two lists: one of Lverts, one of Ledges. if (verts.empty()) return; assert(dynamic_pointer_cast<LMESH>(verts.mesh())); for (Bvert_list::size_type i=0; i<verts.size(); i++) add_p((Lvert*)verts[i], vp, ep); }
inline void get_parents(CBvert_list& verts, Bvert_list& vp, Bedge_list& ep) { // Helper method used below in get_parents(); // from the given list of vertices, return the parent // simplices in two lists: one of Lverts, one of Ledges. if (verts.empty()) return; assert(LMESH::isa(verts.mesh())); for (int i=0; i<verts.num(); i++) add_p((Lvert*)verts[i], vp, ep); }
inline void update_verts(CBvert_list& verts) { // helper for LMESH::update_subdivision(CBface_list& faces) for (int i=0; i<verts.num(); i++) ((Lvert*)verts[i])->update_subdivision(); }
inline bool join(CBvert_list& o, CBvert_list& c, MULTI_CMDptr& cmd, Cstr_ptr& msg) { // Used in Skin::join_to_skel() to join seams of a mesh together. JOIN_SEAM_CMDptr join = new JOIN_SEAM_CMD(o, c); if (join->doit()) { err_adv(debug, " joined %s (%d verts to %d verts)", **msg, o.num(), c.num()); cmd->add(join); return true; } else { err_adv(debug, " error: can't join %s", **msg); return false; } }
// Do a whole list of vertices at a shot: static bool gen_twins(CBvert_list& verts, double h, CSimplexFilter& filter) { bool ret = true; for (int i=0; i<verts.num(); i++) ret = gen_twins(verts[i], h, filter) && ret; return ret; }
inline void update_verts(CBvert_list& verts) { // helper for LMESH::update_subdivision(CBface_list& faces) for (Bvert_list::size_type i=0; i<verts.size(); i++) ((Lvert*)verts[i])->update_subdivision(); }
int Skin::set_sticky(CBvert_list& verts, bool sticky) const { int ret = 0; for (int i=0; i<verts.num(); i++) { ret += ::set_sticky(SkinMeme::upcast(find_meme(verts[i])), sticky); } return ret; }
int Skin::set_offsets(CBvert_list& verts, double h) const { int ret = 0; for (int i=0; i<verts.num(); i++) { ret += ::set_offset(SkinMeme::upcast(find_meme(verts[i])), h); } return ret; }
inline void debug_check_verts(const string& msg, CBvert_list& verts, CBvert_list& dirty_verts) { Bvert_list A = verts.filter(BitSetSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT)); if (!dirty_verts.contains_all(A)) { Bvert_list bad = A.minus(dirty_verts); cerr << msg << ": found " << bad.size() << " vertices missing from dirty list" << endl; WORLD::show_pts(bad.pts(), 8, Color::red); } Bvert_list B = verts.filter(BitClearSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT)); if (dirty_verts.contains_any(B)) { Bvert_list bad = dirty_verts.minus(B); cerr << msg << ": found " << bad.size() << " unexpected vertices in dirty list" << endl; WORLD::show_pts(bad.pts(), 8, Color::blue); } }
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; }
void Skin::set_stay_outside(CBvert_list& verts, bool b) const { for (int i=0; i<verts.num(); i++) { SkinMeme* m = SkinMeme::upcast(find_meme(verts[i])); if (m) { m->set_stay_outside(b); } } }
bool Skin::gen_verts(CBvert_list& skel_verts) { // replicate skel verts to create new skin verts. // ignores verts that have already been done. bool ret = true; for (int i=0; i<skel_verts.num(); i++) if (!gen_vert(skel_verts[i])) ret = false; return ret; }
inline void add_shading(CBvert_list& verts, Wvec l, CCOLOR& col, double s = 1.0) { // normalize the "light" vector: l = l.normalized(); for (size_t i=0; i<verts.size(); i++) { double a = pow(max(l * verts[i]->norm(), 0.0), s); if (a > 0) verts[i]->set_color(interp(verts[i]->color(), col, a), 1); } }
void Skin::restrict(CBvert_list& verts, SimplexFilter* f) const { assert(f); for (int i=0; i<verts.num(); i++) { SkinMeme* m = SkinMeme::upcast(find_meme(verts[i])); if (m) { //assert(m->track_simplex() == 0 || f->accept(m->track_simplex())); m->set_track_filter(f); } } }
SubdivUpdater::SubdivUpdater(LMESHptr m, CBvert_list& verts) : _parent(nullptr) { // Screened in SubdivUpdater::create(): assert(m && m == verts.mesh()); _mesh = m; _verts = verts; // Get bbases, add to inputs _inputs = Bbase::find_owners(verts).bnodes(); if (debug) { err_msg("SubdivUpdater::SubdivUpdater:"); cerr << " "; print_dependencies(); err_msg(" level %d, %d verts, %d boss memes", m->subdiv_level(), verts.size(), Bbase::find_boss_vmemes(verts).size()); } // If not covered, create parent if (!Bbase::is_covered(verts)) { // Get parent verts list Bvert_list parents = LMESH::get_subdiv_inputs(verts); // If non-empty create parent SubdivUpdater if (!parents.empty()) { // Create parent subdiv updater on parent verts // and add to _inputs _parent = create(parents); _inputs += _parent; } } hookup(); }
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 (Bvert_list::size_type i=0; i<verts.size(); i++) { verts[i]->get_q_faces(star); star.clear_flags(); } }
inline void define_offsets( CBvert_list& verts, CVertMapper& tmap, CVertMapper& bmap, CWvec& n, Primitive* p ) { assert(tmap.is_valid() && bmap.is_valid()); for (Bvert_list::size_type i=0; i<verts.size(); i++) { define_offset(verts[i], tmap, bmap, n, p); } }
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(); }
inline Bface_list get_q_faces(CBvert_list& verts) { // Helper method used below in get_parents(); // return all 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 ret, star; for (Bvert_list::size_type i=0; i<verts.size(); i++) { verts[i]->get_q_faces(star); try_append(ret, star); } return ret; }
// XXX - shouldn't have to update 1-ring faces... static bool update_subdivision(CBvert_list& verts, int k=1) { return update_subdivision(verts.one_ring_faces(), k); }