Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}