CWvec& Bface::vert_normal(CBvert* v, Wvec& n) const { // for gouraud shading: return appropriate // normal to use at a vertex of this face assert(this->contains(v)); if(!v->is_crease()) { n = v->norm(); return n; } // take average of face normals in star of v, // using faces which can be reached from this // face without crossing a crease edge n = weighted_vnorm(this, v); // add weighted normal from this face int count = 1; // count of faces processed // wind around v in clockwise direction // but don't cross a crease edge CBface* f = this; Bedge* e = edge_from_vert(v); for (; e&&!e->is_crease() && (f=e->other_face(f)); e=f->edge_from_vert(v)) { n += weighted_vnorm(f, v); if (++count > v->degree()) { // this should never happen, but it does // happen on effed up models // (i.e. when "3rd faces" get added) break; } } // wind around v in counter-clockwise direction; // as before, don't cross a crease edge f = this; e = edge_before_vert(v); for(; e&&!e->is_crease()&&(f=e->other_face(f)); e=f->edge_before_vert(v)) { n += weighted_vnorm(f, v); if(++count > v->degree()) break; } n = n.normalized(); return n; }
/***************************************************************** * InflateCreaseFilter: *****************************************************************/ bool InflateCreaseFilter::accept(CBsimplex* s) const { // Reject non-edges: if (!is_edge(s)) return false; Bedge* e = (Bedge*)s; if (e->nfaces() < 2) return false; // Accept it if it's labelled a crease, is owned by a // Bcurve, or the adjacent faces make a sharp angle: return ( e->is_crease() || Bcurve::find_controller(e) || rad2deg(norm_angle(e)) > 50 ); }