Ejemplo n.º 1
0
bool
Bface::get_quad_verts(Bvert*& a, Bvert*& b, Bvert*& c, Bvert*& d) const
{
   //  Return CCW verts a, b, c, d as in the picture, orienting
   //  things so that the weak edge runs NE as shown:
   //
   //    d ---------- c = w->v2()              ^      
   //    |          / |                        |       
   //    |        /   |                        |       
   //    |    w /     |       tan1        tan2 |       
   //    |    /       |    -------->           |       
   //    |  /     f   |                        |       
   //    |/           |                                
   //    a ---------- b                                
   //     = w->v1()
   //
   if (!is_quad())
      return 0;

   Bedge* w = weak_edge();
   Bface* f = w->ccw_face(w->v2());
   a = w->v1();
   b = f->next_vert_ccw(a);
   c = w->v2();
   d = f->quad_vert();

   return true;
}
Ejemplo n.º 2
0
bool
Bface_list::grow_connected(Bface* f, CSimplexFilter& pass)
{
   // Collect all reachable faces whose flag == 1, starting at f,
   // crossing only edges that are accepted by the given filter.

   if (!(f && f->flag() == 1))
      return false;

   f->set_flag(2);
   push_back(f);

   // check each neighboring edge:
   for (int i=1; i<4; i++) {
      Bedge* e = f->e(i);
      if (pass.accept(e)) {
         // check each adjacent face
         // (includes this, but that will be a no-op):
         for (int j=1; j<=e->num_all_faces(); j++)
            grow_connected(e->f(j), pass);
      }
   }

   return true;
}
Ejemplo n.º 3
0
/**********************************************************************
 * TriStrip:
 **********************************************************************/
Bface*
TriStrip::backup_strip(Bface* f, Bvert*& a) 
{
   // we'd like to draw a triangle strip starting at the 
   // given triangle and proceeding "forward." but to get 
   // the most bang for the buck, we'll first "backup" over 
   // as many triangles as possible to find a starting place 
   // from which we can generate a longer strip.

   assert(!f->flag());

   mark_face(f);

   Bface* ret = f;
   Bvert* b   = f->next_vert_ccw(a);
   Bedge* e;

   int i = 0;
   while((e = f->edge_from_vert((i%2) ? b : a)) &&
         e->consistent_orientation()            &&
         e->is_crossable()                      &&
         (f = e->other_face(f))                 &&
         is_cleared(f)) {
      mark_face(f);
      ret = f;
      Bvert* d = f->other_vertex(a,b);
      b = a;
      a = d;
      i++;
   }

   _orientation = ((i%2) != 0);

   return ret;
}
Ejemplo n.º 4
0
void
EdgeStrip::build_with_tips(CBedge_list& edges, CSimplexFilter& filter)
{
   // Build the strip from the given pool of edges, with the
   // given filter.  Try to start the edge strip at the "tips" of
   // chains of edges of the desired type. The given filter
   // should just screen for edges of the desired kind;
   // internally this method also screens for edges that have not
   // yet been reached (added to the strip).

   // Clear edge flags to screen for unreached edges:
   set_adjacent_edges(edges.get_verts(), 1);
   edges.clear_flags();

   // Pull out the edge tips:
   Bedge_list tips = edges.filter(ChainTipEdgeFilter(filter));

   // Construct the filter that screens out previously reached
   // edges:
   UnreachedSimplexFilter unreached;
   AndFilter       wanted = unreached + filter;

   int k;

   // Start from all the tips first:
   for (k=0; k<tips.num(); k++) {
      Bedge* e = tips[k];
      Bvert* v = (e->v2()->degree(filter) != 2) ? e->v2() : e->v1();
      build(v, e, wanted);
   }

   // Now check the rest:
   for (k=0; k<edges.num(); k++)
      build(0, edges[k], wanted);
}
Ejemplo n.º 5
0
inline Bedge*
find_edge(CPIXEL& pix)
{
   Wvec bc;
   Bedge* e = near_edge(find_face(pix, 1, bc), bc);
   if (e && e->is_weak())
      return 0;
   return e;
}
Ejemplo n.º 6
0
//! Same as try_select_edge(), but deselects.
//! Also requires the found edge is currently selected.
bool
SELECT_WIDGET::try_deselect_edge(CPIXEL &pix)
{

   Bedge* e = find_edge(pix);
   if (!(e && e->is_selected()))
      return false;
   WORLD::add_command(new MESH_DESELECT_CMD(e));
   return true;
}
Ejemplo n.º 7
0
 virtual bool accept(CBsimplex* s) const {
    if (!is_edge(s))                          // reject if non-edge
       return false;
    Bedge* e = (Bedge*)s;
    if (e->sil_stamp() == _stamp)             // reject if previously checked
       return 0;
    e->set_sil_stamp(_stamp);                 // mark as checked this frame
    if (_skip_secondary && e->is_secondary()) // reject secondary edges as needed
       return false;
    return e->is_sil();                       // accept if silhouette
 }
Ejemplo n.º 8
0
bool
OVERSKETCH::find_matching_sil(CGESTUREptr& g)
{
   err_adv(debug, "OVERSKETCH::find_matching_sil");

   const size_t MIN_GEST_PTS = 10;
   if (!(g && g->pts().size() >= MIN_GEST_PTS))
      return false;

   if (BMESH::_freeze_sils)
      return false;

   VisRefImage *vis_ref = VisRefImage::lookup(VIEW::peek());
   if (!vis_ref)
      return false;

   // 1. see if the gesture runs along a silhouette
   //    of a single mesh.

   SilEdgeFilter sil_filter;
   const  PIXEL_list& pts = g->pts();
   BMESHptr mesh = nullptr;
   for (PIXEL_list::size_type i=0; i<pts.size(); i++) {
      Bedge* e = (Bedge*)
         vis_ref->find_near_simplex(pts[i], SIL_SEARCH_RAD, sil_filter);
      if (!(e && e->mesh())) {
         err_adv(debug, "   gesture too far from silhouette");
         return false;
      }
      if (mesh && mesh != e->mesh()) {
         err_adv(debug, "   found a second mesh, rejecting");
         return false;
      }
      mesh = e->mesh();
   }
   if (!dynamic_pointer_cast<LMESH>(mesh)) {
      err_adv(debug, "   found non-LMESH, rejecting");
      return false;
   }

   err_adv(debug, "   gesture aligns with silhouette");
   err_adv(debug, "   mesh level %d", mesh->subdiv_level());

   // 2. extract the portion of the silhouette that matches
   //    the gesture, store in _selected_sils

   return find_matching_sil(pts, mesh->sil_strip());
}
Ejemplo n.º 9
0
bool 
Skin::copy_edge(Bedge* a) const
{
   // copy edge attributes, e.g. from skel to skin

   Bedge* b = _mapper.a_to_b(a);
   if (!(a && b))
      return false;

   if (a->is_weak())
      b->set_bit(Bedge::WEAK_BIT);

   // more?

   return true;
}
Ejemplo n.º 10
0
inline bool 
copy_edge(Bedge* a, CVertMapper& vmap)
{
   // copy edge attributes, e.g. from skel to skin

   Bedge* b = vmap.a_to_b(a);
   if (!(a && b))
      return false;

   if (a->is_weak())
      b->set_bit(Bedge::WEAK_BIT);

   // more?

   return true;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
int
Bedge::redefine(Bvert *v, Bvert *u)
{
    // redefine this edge, replacing v with u

    // precondition:
    //   edge does not already contain u.
    //   v is a vertex of this edge.
    //   faces have already been detached.
    //   can't duplicate an existing edge.

    assert(contains(v) && nfaces() == 0);

    if (contains(u))
        return 0;

    Bedge* dup = 0;
    if (v == _v1) {
        if ((dup = u->lookup_edge(_v2))) {
            // can't redefine, but if this is a crease edge
            // should ensure the duplicated edge is also
            if (is_crease())
                dup->set_crease(crease_val());
            return 0;
        }
        // can redefine:
        *_v1 -= this;     // say bye to old _v1
        _v1 = u;          // record new _v1
        *_v1 += this;     // say hi to new _v1
    } else if (v == _v2) {
        // see comments above
        if ((dup = u->lookup_edge(_v1))) {
            if (is_crease())
                dup->set_crease(crease_val());
            return 0;
        }
        *_v2 -= this;
        _v2 = u;
        *_v2 += this;
    } else assert(0);

    geometry_changed();

    return 1;
}
Ejemplo n.º 13
0
EdgeStrokePool::~EdgeStrokePool()
{
   int i = 0; // loop index
   for (i = 0; i < _strip.edges().num(); i++) {
      Bedge* edge = _strip.edges()[i];
      assert(edge);
      //SimplexData* d = edge->find_data(this->static_name());
      SimplexData* d = edge->find_data((uintptr_t)&(this->foo));

      edge->rem_simplex_data(d);
   }

   i = 0;
   while (i < _num) {
      assert( _array[i]->is_of_type(EdgeStroke::static_name()));
      ((EdgeStroke*)_array[i++])->clear_simplex_data();
   }
}
Ejemplo n.º 14
0
/*****************************************************************
 * 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
      );
}
Ejemplo n.º 15
0
void
EdgeStrip::build_ccw_boundaries(
   CBedge_list& edges,
   CSimplexFilter& face_filter
   )
{
   // Similar to previous...
   //
   // XXX - needs comments

   // Clear edge flags to screen for unreached edges:
   // set edge flags to 1 in 1-ring of verts,
   // then clear edge flags of internal edges
   set_adjacent_edges(edges.get_verts(), 1);
   edges.clear_flags();

   // get an edge filter that accepts "boundary" edges WRT the
   // given face filter
   BoundaryEdgeFilter boundary(face_filter);

   // Pull out the edge tips:
   Bedge_list tips = edges.filter(ChainTipEdgeFilter(boundary));

   // Construct the filter that screens out previously reached
   // edges:
   UnreachedSimplexFilter unreached;
   AndFilter       wanted = unreached + boundary;

   int k;

   // Start from all the tips first:
   for (k=0; k<tips.num(); k++) {
      Bedge* e = tips[k];
      Bvert* v = (e->v2()->degree(boundary) != 2) ? e->v2() : e->v1();
      Bface* f = e->screen_face(face_filter);
      assert(f); // e must have 1 face satisfying the filter

      // If this will start out running ccw, take it.
      // otherwise skip:
      if (f->next_vert_ccw(v) == e->other_vertex(v))
         build(v, e, wanted);
   }

   // Now check the rest:
   for (k=0; k<edges.num(); k++) {
      Bedge* e = edges[k];
      Bface* f = e->screen_face(face_filter);
      assert(f); // e must have 1 face satisfying the filter

      // Go CCW around faces
      build(f->leading_vert_ccw(e), e, wanted);
   }
}
Ejemplo n.º 16
0
Bedge_list 
Bface_list::get_edges() const
{
   // Extract a list of the edges found in the given faces.

   // Get clean slate
   clear_edge_flags();

   // Put edges into output array uniquely:
   Bedge_list ret(size()*2);       // pre-allocate plenty
   for (Bface_list::size_type i=0; i<size(); i++) {
      for (int j=1; j<4; j++) {
         Bedge* e = at(i)->e(j);
         if (e->flag() == 0) {
            e->set_flag(1);
            ret.push_back(e);
         }
      }
   }
   return ret;
}
Ejemplo n.º 17
0
bool
SELECT_WIDGET::select_edges(CPIXEL_list& pts)
{
   err_adv(debug, "SELECT_WIDGET::select_edges:");

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

   // Find edit-level vert near start of pixel trail:
   Bvert* v = find_vert(pts[0]);
   if (!v) {
      err_adv(debug, "  can't get starter vertex");
      return false;
   }

   // 2. Extract edge sequence within tolerance of gest

   Bedge_list chain;

   int k = 0;                           // index of cur position in gesture
   Bvert* cur = v;                      // current vertex
   Bedge* e = 0;
   while ((e = match_span(cur, pts, k))) {
      if(!e->is_selected()) chain += e;
      cur = e->other_vertex(cur);
   }

   err_adv(debug, "  got %d edges", chain.num());

   // Confirm gest is sufficiently close to edge chain

   // 3. Select the edges

   WORLD::add_command(new MESH_SELECT_CMD(chain));

   return true;
}
Ejemplo n.º 18
0
bool
Skin::correct_face(Bface* f, bool& changed)
{
   //                                 
   //  BBBBBBBBBBBBBBB                
   //  B            /|                
   //  B          /  |                
   //  B   f    /    |   Change this, where quad face f        
   //  B      /      |   is adjacent to 2 boundary edgees...
   //  B    /        |                
   //  B  /          |                
   //  B/- - - - - - o                
   //                                 
   //  BBBBBBBBBBBBBBB                
   //  B\            |                
   //  B  \          |                
   //  B    \        |  ... to this, where neither face of
   //  B      \      |  the quad is adjacent to more than 1              
   //  B        \    |  boundary edge.              
   //  B          \  |                
   //  B - - - - - - o                
   //                                 

   assert(f);

   // boundary edges have flag == 1, others have flag == 0
   uint n = num_edge_flags_set(f);
   if (n < 2) return true;      // not a problem
   if (n > 2) {
      // unfixable problem
      err_adv(debug, "  can't fix face with %d boundary edges", n);
      return false;
   }

   // 2 boundary edges; get the non-boundary one:
   Bedge* e = boundary_connector(f);
   assert(e);

   // we want to swap it; only possible if it has 2 faces:
   if (e->nfaces() != 2) {
      err_adv(debug, "  can't fix edge with %d faces", e->nfaces());
      return false;
   }

   // swapping won't do any good if its other face has boundary edges too:
   if (!(num_edge_flags_set(e->f1()) == 0 || num_edge_flags_set(e->f2()) == 0)) {
      err_adv(debug, "  unfixable edge found, giving up");
      return false;
   }

   // try to swap it:
   if (e->do_swap()) {
      err_adv(debug, "  swapped edge");
      return changed = true;
   }
   err_adv(debug, "  edge swap failed");
   return false;
}
Ejemplo n.º 19
0
inline Bedge_list
quad_cell_end_edges(PCell* cell)
{
   // if the cell is a quad (4 sides) and has one neigbhor,
   // return the side opposite from the neighbor.

   assert(cell && cell->num_corners() == 4);

   PCell_list nbrs = cell->nbrs();
   if (nbrs.size() != 1) {
      err_adv(debug, "quad_cell_end_edges: neighbors: %d != 1", nbrs.size());
      return Bedge_list();
   }
   // find an edge of the shared boundary.
   // do it now before messing with flags...
   assert(!cell->shared_boundary(nbrs[0]).empty());
   Bedge* e = cell->shared_boundary(nbrs[0]).front();
   assert(e);

   EdgeStrip boundary = cell->get_boundary();
   assert(boundary.num_line_strips() == 1);

   // iterate around the boundary, setting edge flags to value
   // k that is incremented whenever we pass a cell corner.
   int k = 0;
   PCellCornerVertFilter filter;
   for (int i=0; i<boundary.num(); i++) {
      if (filter.accept(boundary.vert(i)))
         k = (k + 1)%4;
      boundary.edge(i)->set_flag(k);
   }

   // we want the edges with flag == k + 2 mod 4
   return boundary.edges().filter(
      SimplexFlagFilter((e->flag() + 2)%4)
      );
}
Ejemplo n.º 20
0
UVpt
LoopUV::centroid(CLvert* v) const
{
   assert(v);

   switch (UVdata::discontinuity_degree(v)) {
    case 0:
    {
       // No discontinuity:
       UVpt ret;
       for (int i=0; i<v->degree(); i++)
          ret += UVdata::get_uv(v->nbr(i), v->e(i)->get_face());
       return ret / v->degree();
    }
    case 2:
    {
       // Find the 2 discontinuity edges and get the uv values of
       // their opposite vertices that agree with the current vertex.
       CUVpt& uv = UVdata::get_uv(v,_face);
       UVpt ret;
       for (int i=0; i<v->degree(); i++) {
          Bedge* e = v->e(i);
          if (!UVdata::is_continuous(e)) {
             if (UVdata::lookup(e->f1()) && UVdata::get_uv(v,e->f1()) == uv)
                ret += UVdata::get_uv(v->nbr(i), e->f1());
             else if (UVdata::lookup(e->f2()) &&
                      UVdata::get_uv(v,e->f2()) == uv)
                ret += UVdata::get_uv(v->nbr(i), e->f2());
             else
                assert(0);
          }
       }
       return ret/2;
    }
    default:
       // Treat as a corner vertex
       return UVdata::get_uv(v, _face);
   }
}
Ejemplo n.º 21
0
void 
Lface::allocate_subdiv_elements()
{
   // Generate 4 faces and 3 internal edges
   // in the subdivision mesh next level down.

   // NOTE: The specific order that sub-faces are created,
   // and the order of the vertices used in creating them,
   // should not be changed. The barycentric coordinate
   // conversion routines (below) depend on these orderings.

   // Make this lightweight, so you can call
   // it when you're not sure if you need to:
   if (is_set(SUBDIV_ALLOCATED_BIT))
      return;
   set_bit(SUBDIV_ALLOCATED_BIT);

   assert(lmesh() != nullptr);
   lmesh()->allocate_subdiv_mesh();
   LMESHptr submesh = lmesh()->subdiv_mesh();
   assert(submesh != nullptr);


   //                       lv3                                       #
   //                        /\                                       #
   //                       /3 \                                      #
   //                      /    \                                     #
   //                     /      \                                    #
   //                    / child3 \                                   #
   //                   /          \                                  #
   //                  / 1        2 \                                 #
   //            le3  /______________\ le2                            #
   //                /\ 2          1 /\                               #
   //               /3 \            /3 \                              #
   //              /    \  center  /    \                             #
   //             /      \  child /      \                            #
   //            /        \      /        \                           #
   //           /  child1  \    /  child2  \                          #
   //          /            \3 /            \                         #
   //         / 1          2 \/ 1          2 \                        #
   //     lv1 -------------------------------- lv2                    #
   //                       le1                                       #

   // Make sure subdiv elements have
   // been allocated around face boundary:
   lv(1)->allocate_subdiv_vert();
   lv(2)->allocate_subdiv_vert();
   lv(3)->allocate_subdiv_vert();

   le(1)->allocate_subdiv_elements();
   le(2)->allocate_subdiv_elements();
   le(3)->allocate_subdiv_elements();

   Patch* child_patch = _patch ? _patch->get_child() : nullptr;

   // hook up 4 faces (verifying they're not already there):
   if (!subdiv_face1())
      gen_child_face(
         lv(1)->subdiv_vertex(),
         le(1)->subdiv_vertex(),
         le(3)->subdiv_vertex(),
         child_patch, submesh);

   if (!subdiv_face2())
      gen_child_face(
         le(1)->subdiv_vertex(),
         lv(2)->subdiv_vertex(),
         le(2)->subdiv_vertex(),
         child_patch, submesh);

   if (!subdiv_face3())
      gen_child_face(
         le(3)->subdiv_vertex(),
         le(2)->subdiv_vertex(),
         lv(3)->subdiv_vertex(),
         child_patch, submesh);

   if (!subdiv_face_center())
      gen_child_face(
         le(2)->subdiv_vertex(),
         le(3)->subdiv_vertex(),
         le(1)->subdiv_vertex(),
         child_patch, submesh, true);   // true: face is at center

   if (is_quad()) {
      //
      //       o                                         
      //       | .                                       
      //       |   .                                     
      //       |     .  w                                
      //       |       .                                 
      //  sub1 o .----- o.                               
      //       |   .    |  .                             
      //       |     .  |    .                           
      //       |       .|      .                         
      //       o ------ o ----- o                        
      //      v       sub2                               
      //                                                 
      // A quad face is one that has a "weak" edge
      // (shown as the dotted edge labelled 'w' above).
      // A weak edge is considered to be the internal
      // diagonal edge of a quad, with this face making
      // up one half of the quad and the face on the
      // other side (not shown) making up the other
      // half. In subdivision we label the subdivision
      // edges accordingly. I.e. the edge connecting
      // subdivision vertices sub1 and sub2 should be
      // labelled weak.

      Bedge* w = weak_edge();
      Bvert* v = other_vertex(w);
      Bvert* sub1 = ((Ledge*)v->lookup_edge(w->v1()))->subdiv_vertex();
      Bvert* sub2 = ((Ledge*)v->lookup_edge(w->v2()))->subdiv_vertex();
      sub1->lookup_edge(sub2)->set_bit(Bedge::WEAK_BIT);
   }

   // Now that child faces are generated, propagate multi
   // status (if any) to children
   le(1)->push_multi(this);
   le(2)->push_multi(this);
   le(3)->push_multi(this);

   // Notify observers:
   if (_data_list)
      _data_list->notify_subdiv_gen();
}
Ejemplo n.º 22
0
bool 
Bface::local_search(
   Bsimplex            *&end, 
   Wvec             &final_bc,
   CWpt             &target, 
   Wpt              &reached,
   Bsimplex         *repeater,
   int               iters) 
{
   // this is a hack to prevent recursion that goes too deep.
   // however if that is a problem the real cause should be
   // tracked down and fixed.

   if (iters <= 0)
      return 0;

   Wvec      bc;
   bool      is_on_tri = 0;
   Wpt       nearpt    = nearest_pt(target, bc, is_on_tri);
   Bsimplex* sim       = bc2sim(bc);

   if (!is_on_tri) {
      
      if (sim == repeater) // We hit a loop in the recursion, so stop
         return 0;

      if (sim != this) { // We're on the boundary of the face
         if (is_edge(sim)) {
            Bedge* e = (Bedge*)sim;

            // Can't cross a border
            if (!e->is_border()) {

               // recurse starting from the other face.
               int good_path = e->other_face(this)->local_search(
                  end, final_bc, target, reached, sim, iters-1);
               if (good_path == 1)
                  return 1;
               else if (good_path == -1)
                  return repeater ? true : false; // XXX - changed from -1 : 0 -- should check
            }

            else {
               return repeater ? true : false; // XXX - changed from -1 : 0 -- should check
            }
         } else {
            // Try to follow across a vertex
            Bface_list near_faces(16);
            assert(is_vert(sim));
            ((Bvert*)sim)->get_faces(near_faces);
            for (int k = near_faces.size()-1; k>=0; k--) {
               if (near_faces[k] != this) {
                  int good_path = near_faces[k]->local_search(
                           end, final_bc, target, reached, sim, iters-1);
                  if (good_path == 1)
                     return 1;
                  else if (good_path==-1)
                     return repeater ? true : false; // XXX - changed from -1 : 0 -- should check
               }
            }
         }
      }
   }

   reached = nearpt;
   end = this;
   final_bc = bc;

   return 1;
}
Ejemplo n.º 23
0
int 
SELECT_WIDGET:: slash_cb(CGESTUREptr& gest, DrawState*& s)
{

	
	if (_mode==SEL_FACE) //widget is in face selection mode 
	{
		select_list.clear();

		Bface* f = find_face(gest->start(),0.25,MIN_PIX_AREA);
		// f should be the currently selected face
		if (f && f->is_selected() && f->is_quad())
		{
	
			f=f->quad_rep();

		//line in screen space coresponding to the slash
		PIXELline slash(gest->start(),gest->end());

		Bedge *e1,*e2,*e3,*e4;
		Bedge* edge = 0;
		
		//get and test the quad edges against the stroke line 
		f->get_quad_edges(e1,e2,e3,e4);

		if( e1->pix_line().intersect_segs(slash) )
		{
			edge=e1;
		}
		else
		if( e2->pix_line().intersect_segs(slash) )
		{
			edge=e2;
		}
		else
		if( e3->pix_line().intersect_segs(slash) )
		{
			edge=e3;
		}
		else
		if( e4->pix_line().intersect_segs(slash) )
		{
			edge=e4;
		}
		else
		{
			//error
			cerr << "ERROR no intersection" << endl;
			return 1;
		}
		
			//walk the geometry and select faces

			Bface* fn = f;
			do
			{			
				if (!fn->is_selected())	
					select_list +=fn;
		
				assert(edge);			//I'm paranoid too
				assert(edge->f1()!=edge->f2());

				//grabs the face on the other side of the edge
				//even if we are not directly adjacent to this edge
				fn=fn->other_quad_face(edge);
				
				if (fn) //if a valid face than advance the edge pointer
				{
					assert(edge!=fn->opposite_quad_edge(edge));
					edge = fn->opposite_quad_edge(edge);
	
					fn = fn->quad_rep(); //all faces on the selection list are rep faces

				}
				else
					cerr << "No face on the other side of the edge" << endl;

			} //quit if not a valid face or not a quad
			while(fn&&(fn->is_quad())&&edge&&(fn!=f));


			_mode=SLASH_SEL;  //go into pattern editing mode
			end_face=0;		//prepare the 2nd step data
			pattern=0;
			for (int i=0; i<MAX_PATTERN_SIZE; i++)
				pattern_array[i]=1; //fill the default pattern with ones
		}
		else
			cerr << "This is not a quad" << endl;

	}
	else
		if( _mode==SLASH_SEL)//pattern editing mode
		{ //activates upon second slash motion


			//adds the entire list to the selected group
			//undo deselects the entire group

			Bface_list final_list;

			//copy the face pointers to the final list 
			//using the pattern as a repeating template
			//and stop at the end face
			for (int i = 0; i<(end_face ? (end_face) : select_list.num()) ; i++)
			{
				if (pattern ? pattern_array[(i%pattern)+1] : 1)
				final_list+=select_list[i];
			}

		
		   WORLD::add_command(new MESH_SELECT_CMD(final_list));
		
		   return cancel_cb(gest,s);

		}
		else
			cerr << "wrong mode " << endl;
	return 1;
}
Ejemplo n.º 24
0
bool 
UVdata::get_quad_uvs(
   CBvert* a,
   CBvert* b,
   CBvert* c,
   CBvert* d,
   UVpt& uva,
   UVpt& uvb,
   UVpt& uvc,
   UVpt& uvd)
{
   // Pull out the uv-coordinates from the 4 given vertices
   // that supposedly form a quad.

   //    d ---------- c                               
   //    |            |                                
   //    |            |                                
   //    |            |                                
   //    |            |                                
   //    |            |                                
   //    |            |                                
   //    a ---------- b                                
   //

   if (!(a && b && c && d))
      return false;

   // Try the diagonal running NE:
   Bedge* e = a->lookup_edge(c);
   if (e) {
      if (!quad_has_uv(e->f1()))
         return 0;

      // Get the two faces, trying the diagonal running NE
      Bface* lower = lookup_face(a,b,c);
      Bface* upper = lookup_face(a,c,d);

      // Should never fail, but check anyway:
      if (!(upper && lower))
         return 0;

      // Get the data and return happy
      uva = get_uv(a, lower);
      uvb = get_uv(b, lower);
      uvc = get_uv(c, lower);
      uvd = get_uv(d, upper);

      return 1;
   }

   // Try the diagonal the other way:
   e = b->lookup_edge(d);
   if (!(e && quad_has_uv(e->f1())))
      return 0;

   // Get the two faces, trying the diagonal running NE
   Bface* lower = lookup_face(a,b,d);
   Bface* upper = lookup_face(b,c,d);

   // Should never fail, but check anyway:
   if (!(upper && lower))
      return 0;

   // Get the data and return happy
   uva = get_uv(a, lower);
   uvb = get_uv(b, lower);
   uvc = get_uv(c, upper);
   uvd = get_uv(d, upper);

   return 1;
}
Ejemplo n.º 25
0
 // Like above, but returns the next border vertex:
 Bvert* next_border_vert_cw() {
    Bedge* border = next_border_edge_cw();
    return border ? border->other_vertex(this) : nullptr;
 }               
Ejemplo n.º 26
0
Bsimplex*
Bface::ndc_walk(
   CNDCpt& target, 
   CWvec &passed_bc, 
   CNDCpt &nearest,
   int is_on_tri, 
   bool use_passed_in_params) const
{
  // just like local_search, but in NDC space
   //
   // start from this face, move in NDC space
   // across the mesh to reach the target
   //
   // if reached, return the simplex that contains
   // the target point.
   // we only move if it will get us closer to the goal.  Hence, we
   // can never wander off forever.

   // if can't reach it, return 0

   NDCpt y (nearest);
   Wvec  bc(passed_bc);

   if (!use_passed_in_params) {
      y = nearest_pt_ndc(target, bc, is_on_tri);
   }
   Bsimplex* sim   = bc2sim(bc);

   if (is_on_tri) {
      // target is on this triangle
      // return the lowest-dimensional
      // simplex on which it lies
      return sim;
   }

   if (is_edge(sim)) {
      Bedge* e = (Bedge*)sim;
      Bface* f = e->is_sil() ? nullptr : e->other_face(this);
      if (f) {
         Wvec new_bc;
         int  new_on_tri;
         NDCpt new_best = f->nearest_pt_ndc(target, new_bc, new_on_tri);
         if (new_best.dist_sqrd(target) < y.dist_sqrd(target))
            return f->ndc_walk(target, new_bc, new_best, new_on_tri, true); 
         else 
            return nullptr;
      } else {
         return nullptr;
      }
   }

   // better be a vertex
   assert(is_vert(sim));
   Bvert* v = (Bvert*)sim;
   if (v->degree(SilEdgeFilter()) > 0)
      return nullptr;

   Bface_list nbrs(16);
   ((Bvert*)sim)->get_faces(nbrs);
   double dist_sqrd = 1e50;
   Bface* best = nullptr;
   Wvec   best_bc;
   NDCpt  best_nearest;
   int    best_on_tri = 0;
   Wvec   curr_bc;
   NDCpt  curr_nearest;
   int    curr_on_tri=0;

   for (Bface_list::size_type k = 0; k < nbrs.size(); k++) {
      if (nbrs[k] != this) {
         curr_nearest = nbrs[k]->nearest_pt_ndc(target, curr_bc, curr_on_tri);
         if (curr_nearest.dist_sqrd(target) < dist_sqrd ) {
            dist_sqrd = curr_nearest.dist_sqrd(target);
            best_bc = curr_bc;
            best_on_tri = curr_on_tri;
            best_nearest = curr_nearest;
            best = nbrs[k];
         }
      }
   }

   if (dist_sqrd < y.dist_sqrd(target)) {
      return best->ndc_walk(target, best_bc, best_nearest, best_on_tri, true); 
   }

   return nullptr;
}
Ejemplo n.º 27
0
void 
ProxySurface::grow_quad_from_edge(BMESH* m, EdgeStrip* boundary, int i)
{
   // i is the position of the edge in the boundary
   Bedge* e = boundary->edge(i);
   assert(e);
   
   //make sure is still a boundary edge if not, return...
   if(e->nfaces() > 1){
      return;
   }

   Bvert* v2 = boundary->vert(i);
   Bvert* v1 = boundary->next_vert(i);
   assert(v1);
   assert(v2);

   if(!(UVdata::is_continuous(e)))
   {
      cerr << "ProxySurface::grow_quad_from_edge: e is discontinous!!!" << endl;
      return;
   }
 
   UVpt uv_1, uv_2, uv_3, uv_4;

   if(!(UVdata::get_uv(v2, uv_2)))
   {   
      cerr << "ProxySurface::grow_quad_from_edge: v2 vertex does not have UVdata!!!" << endl;
      return;
   }
   
   if(!(UVdata::get_uv(v1, uv_1)))
   {   
      cerr << "ProxySurface::grow_quad_from_edge: v1 vertex does not have UVdata!!!" << endl;
      return;
   }

   // constant in u dir -> v line
   if(uv_1[0] == uv_2[0]){
      if(uv_1[1] > uv_2[1])
      {
         uv_3 = UVpt(uv_2[0]+1,uv_2[1]);
         uv_4 = UVpt(uv_1[0]+1,uv_1[1]);
      } else {
         uv_3 = UVpt(uv_2[0]-1,uv_2[1]);
         uv_4 = UVpt(uv_1[0]-1,uv_1[1]);
      }
   } else {
      assert(uv_1[1] == uv_2[1]);
      //constant in v dir
      if(uv_1[0] > uv_2[0])
      {
         uv_3 = UVpt(uv_2[0],uv_2[1]-1);
         uv_4 = UVpt(uv_1[0],uv_1[1]-1);
      } else {
         uv_3 = UVpt(uv_2[0],uv_2[1]+1);
         uv_4 = UVpt(uv_1[0],uv_1[1]+1);
      }
   }      
   
   // double dist = e->length();
   //cerr << "grow quad: " << i << " " << uv_1 << " " << uv_2 << " " << uv_3 << " " << uv_4 << endl;
   Bvert* v_1 = vertFromUV(uv_1);
   Bvert* v_2 = vertFromUV(uv_2);
   Bvert* v_3 = vertFromUV(uv_3);
   Bvert* v_4 = vertFromUV(uv_4);
   assert(v_1 && v_2 && v_3 && v_4);
   //cerr << "grow quad: " << i << " " << v_1->wloc() << " " << v_2->wloc() << " " << v_3->wloc() << " " << v_4->wloc() << endl;

   m->add_quad(v_1, v_2, v_3, v_4,
               uv_1, uv_2, uv_3, uv_4,
               m->patch(0));
   UVdata::set(v_1, uv_1);
   UVdata::set(v_2, uv_2);
   UVdata::set(v_3, uv_3);
   UVdata::set(v_4, uv_4);
   
 
   //PixelsData::get_pix(v_1, this);
   //PixelsData::get_pix(v_2, this);
   //PixelsData::get_pix(v_3, this);
   //PixelsData::get_pix(v_4, this);

   PixelsData::set_pix(v_1, this,v_1->pix());
   PixelsData::set_pix(v_2, this,v_2->pix());
   PixelsData::set_pix(v_3, this,v_3->pix());
   PixelsData::set_pix(v_4, this,v_4->pix());


}